12using LiquidSFZ::Synth;
 
   16  enum { STATE_IDLE, STATE_LOAD };
 
   25  uint   want_sample_rate_ = 0;
 
   26  uint   have_sample_rate_ = 0;
 
   34        if (state_.load() == STATE_LOAD)
 
   36            if (want_sfz_ != have_sfz_)
 
   38                printerr (
"LiquidSFZ: loading %s...", want_sfz_.
c_str());
 
   39                bool result = synth_.load (want_sfz_);
 
   40                printerr (
"%s\n", result ? 
"OK" : 
"FAIL");
 
   43                have_sfz_ = want_sfz_;
 
   45            if (want_sample_rate_ != have_sample_rate_)
 
   47                synth_.set_sample_rate (want_sample_rate_);
 
   48                have_sample_rate_ = want_sample_rate_;
 
   50            state_.store (STATE_IDLE);
 
   53    printerr (
"LiquidSFZ: run() done\n");
 
   56  LiquidSFZLoader (Synth &synth) :
 
   59    thread_ = 
std::thread (&LiquidSFZLoader::run, 
this);
 
   61    printerr (
"LiquidSFZLoader()\n");
 
   68    printerr (
"~LiquidSFZLoader()\n");
 
   74    if (state_.load() == STATE_IDLE)
 
   76        if (want_sfz_ == have_sfz_ && (want_sample_rate_ == have_sample_rate_ || want_sfz_ == 
""))
 
   79    state_.store (STATE_LOAD);
 
   91  set_sample_rate (
uint sample_rate)
 
   93    want_sample_rate_ = sample_rate;
 
  102  bool synth_need_reset_ = 
false;
 
  103  LiquidSFZLoader loader_;
 
  109  static constexpr const int PID_CC_OFFSET = 1000;
 
  116    loader_.set_sample_rate (sample_rate());
 
  118    stereo_out_ = 
add_output_bus (
"Stereo Out", SpeakerArrangement::STEREO);
 
  119    assert_return (bus_info (stereo_out_).ident == 
"stereo_out");
 
  125  build_parameter_map()
 
  128    pmap[INSTRUMENT] = 
Param { 
"instrument", 
_(
"Instrument"), 
_(
"Inst"), 
"", 
"", {}, 
"", {
 
  129        String (
"blurb=") + 
_(
"Instrument File Name"),
 
  132    auto ccs = synth_.list_ccs();
 
  133    for (
const auto& cc_info : ccs)
 
  135        uint32_t pid = cc_info.cc() + PID_CC_OFFSET;
 
  136        pmap[pid] = 
Param { 
string_format (
"cc_%d", cc_info.cc()), cc_info.label(), cc_info.label(),
 
  137                            cc_info.default_value() / 127. * 100, 
"%", { 0, 100 } };
 
  142  reset (
uint64 target_stamp)
 override 
  144    synth_need_reset_ = 
true;
 
  148  adjust_param (uint32_t tag)
 override 
  153        loader_.load (text_param_from_quark (INSTRUMENT, 
irintf (get_param (tag))));
 
  158  generate_cc_event (
const MidiEvent& event)
 
  160    const int cc = 
event.param - PID_CC_OFFSET;
 
  161    const int cc_value = 
std::clamp (
irintf (event.pvalue * 0.01 * 127), 0, 127);
 
  171    synth_.add_event_cc (event.
frame, 0, cc, cc_value);
 
  174  render (
uint n_frames)
 override 
  180        if (synth_need_reset_)
 
  182            synth_.system_reset();
 
  183            synth_need_reset_ = 
false;
 
  187        for (
const auto &ev : evinput)
 
  189            switch (ev.message())
 
  191              case MidiMessage::NOTE_OFF:
 
  192                synth_.add_event_note_off (ev.frame, ev.channel, ev.key);
 
  194              case MidiMessage::NOTE_ON:
 
  195                synth_.add_event_note_on (ev.frame, ev.channel, ev.key, 
std::clamp (
irintf (ev.velocity * 127), 0, 127));
 
  197              case MidiMessage::ALL_NOTES_OFF:
 
  198              case MidiMessage::ALL_SOUND_OFF:
 
  199                synth_.all_sound_off();    
 
  201              case MidiMessage::PARAM_VALUE:
 
  203                adjust_param (ev.param);
 
  204                if (ev.param >= PID_CC_OFFSET)
 
  205                  generate_cc_event (ev);
 
  215        synth_.process (output, n_frames);
 
  219        float *left_out = 
oblock (stereo_out_, 0);
 
  220        float *right_out = 
oblock (stereo_out_, 1);
 
  227  LiquidSFZ (
const ProcessorSetup &psetup) :
 
  235    info.
label        = 
"LiquidSFZ";
 
  242static auto liquidsfz = register_audio_processor<LiquidSFZ> (
"Ase::Devices::LiquidSFZ");
 
Audio signal AudioProcessor base class, implemented by all effects and instruments.
 
void prepare_event_input()
 
MidiEventInput midi_event_input()
Access the current MidiEvent inputs during render(), needs prepare_event_input().
 
OBusId add_output_bus(CString uilabel, SpeakerArrangement speakerarrangement, const String &hints="", const String &blurb="")
Add an output bus with uilabel and channels configured via speakerarrangement.
 
virtual void initialize(SpeakerArrangement busses)=0
 
void apply_event(const MidiEvent &event)
Assign MidiEvent::PARAM_VALUE event values to parameters.
 
void install_params(const AudioParams::Map ¶ms)
Reset list of parameters, enqueues parameter value initializaiton events.
 
float * oblock(OBusId b, uint c)
 
int wait() noexcept
Unlock ScopedSemaphore.
 
int post() noexcept
Unlock ScopedSemaphore.
 
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
 
#define _(...)
Retrieve the translation of a C or C++ string.
 
int run(const StringS &test_names)
Run named tests.
 
The Anklang C++ API namespace.
 
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
 
CString website_url
Website of/about this AudioProcessor.
 
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
void floatfill(float *dst, float f, size_t n)
Fill n values of dst with f.
 
OBusId
ID type for AudioProcessor output buses, buses are numbered with increasing index.
 
CString version
Version identifier.
 
CString creator_name
Name of the creator.
 
CString label
Preferred user interface name.
 
std::string String
Convenience alias for std::string.
 
uint32_t uint
Provide 'uint' as convenience type.
 
CString category
Category to allow grouping for processors of similar function.
 
Detailed information and common properties of AudioProcessor subclasses.
 
MidiEvent data structure.
 
uint frame
Offset into current block, delayed if negative.
 
Structured initializer for Parameter.
 
Parameter list construction helper.