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.