1 /*
2 * liquidsfz - sfz sampler
3 *
4 * Copyright (C) 2019 Stefan Westerfeld
5 *
6 * This library is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by the
8 * Free Software Foundation; either version 2.1 of the License, or (at your
9 * option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <math.h>
22
23 #include <array>
24
25 #include "voice.hh"
26 #include "synth.hh"
27
28 using namespace LiquidSFZInternal;
29
30 using std::clamp;
31
32 double
pan_stereo_factor(double region_pan,int ch)33 Voice::pan_stereo_factor (double region_pan, int ch)
34 {
35 /* sine panning law (constant power panning) */
36 const double pan = ch == 0 ? -region_pan : region_pan;
37 return sin ((pan + 100) / 400 * M_PI);
38 }
39
40 double
velocity_track_factor(const Region & r,int midi_velocity)41 Voice::velocity_track_factor (const Region& r, int midi_velocity)
42 {
43 double curve;
44 if (r.amp_velcurve.empty())
45 curve = (midi_velocity * midi_velocity) / (127.0 * 127.0);
46 else
47 curve = r.amp_velcurve.get (midi_velocity);
48
49 double veltrack_factor = r.amp_veltrack * 0.01;
50
51 double offset = (veltrack_factor >= 0) ? 1 : 0;
52 double v = (offset - veltrack_factor) + veltrack_factor * curve;
53
54 return v;
55 }
56
57 void
update_replay_speed(bool now)58 Voice::update_replay_speed (bool now)
59 {
60 double semi_tones = (key_ - region_->pitch_keycenter) * (region_->pitch_keytrack * 0.01);
61 semi_tones += (region_->tune + pitch_random_cent_) * 0.01;
62 semi_tones += region_->transpose;
63
64 /* pitch bend */
65 if (pitch_bend_value_ >= 0)
66 semi_tones += pitch_bend_value_ * (region_->bend_up * 0.01);
67 else
68 semi_tones += pitch_bend_value_ * (region_->bend_down * -0.01);
69
70 semi_tones += synth_->get_cc_vec_value (channel_, region_->tune_cc) * 0.01; // tune_oncc
71
72 replay_speed_.set (exp2f (semi_tones / 12) * region_->cached_sample->sample_rate / sample_rate_, now);
73 }
74
75 uint
off_by()76 Voice::off_by()
77 {
78 return region_->off_by;
79 }
80
81 void
start(const Region & region,int channel,int key,int velocity,double time_since_note_on,uint64_t global_frame_count,uint sample_rate)82 Voice::start (const Region& region, int channel, int key, int velocity, double time_since_note_on, uint64_t global_frame_count, uint sample_rate)
83 {
84 start_frame_count_ = global_frame_count;
85 sample_rate_ = sample_rate;
86 region_ = ®ion;
87 channel_ = channel;
88 key_ = key;
89 velocity_ = velocity;
90 trigger_ = region.trigger;
91 left_gain_.reset (sample_rate, 0.020);
92 right_gain_.reset (sample_rate, 0.020);
93 replay_speed_.reset (sample_rate, 0.020);
94
95 amp_random_gain_ = db_to_factor (region.amp_random * synth_->normalized_random_value());
96 pitch_random_cent_ = region.pitch_random * synth_->normalized_random_value();
97
98 velocity_gain_ = velocity_track_factor (region, velocity);
99 rt_decay_gain_ = 1.0;
100 if (region.trigger == Trigger::RELEASE)
101 {
102 rt_decay_gain_ = db_to_factor (-time_since_note_on * region.rt_decay);
103 synth_->debug ("rt_decay_gain %f\n", rt_decay_gain_);
104 }
105
106 double delay = region.delay;
107 delay += synth_->get_cc_vec_value (channel_, region_->delay_cc); // delay_oncc
108 delay_samples_ = std::max (delay * sample_rate, 0.0);
109
110 /* loop? */
111 loop_enabled_ = false;
112 if (region_->loop_mode == LoopMode::SUSTAIN || region_->loop_mode == LoopMode::CONTINUOUS)
113 {
114 if (region_->loop_end > region_->loop_start)
115 loop_enabled_ = true;
116 }
117
118 /* play start position */
119 uint offset = region.offset;
120 offset += lrint (region.offset_random * synth_->normalized_random_value());
121 offset += lrint (synth_->get_cc_vec_value (channel_, region.offset_cc));
122 ppos_ = offset;
123 if (ppos_ > region.loop_end)
124 loop_enabled_ = false;
125
126 update_volume_gain();
127 update_amplitude_gain();
128 update_pan_gain();
129 update_lr_gain (true);
130
131 set_pitch_bend (synth_->get_pitch_bend (channel));
132 update_replay_speed (true);
133
134 const float vnorm = velocity * (1 / 127.f);
135 envelope_.set_delay (amp_value (vnorm, region.ampeg_delay));
136 envelope_.set_attack (amp_value (vnorm, region.ampeg_attack));
137 envelope_.set_hold (amp_value (vnorm, region.ampeg_hold));
138 envelope_.set_decay (amp_value (vnorm, region.ampeg_decay));
139 envelope_.set_sustain (amp_value (vnorm, region.ampeg_sustain));
140 envelope_.set_release (amp_value (vnorm, region.ampeg_release));
141 envelope_.start (region, sample_rate_);
142
143 state_ = ACTIVE;
144 synth_->debug ("location %s\n", region.location.c_str());
145 synth_->debug ("new voice %s - channels %d\n", region.sample.c_str(), region.cached_sample->channels);
146
147 filter_envelope_.set_shape (Envelope::Shape::LINEAR);
148 filter_envelope_.set_delay (amp_value (vnorm, region.fileg_delay));
149 filter_envelope_.set_attack (amp_value (vnorm, region.fileg_attack));
150 filter_envelope_.set_hold (amp_value (vnorm, region.fileg_hold));
151 filter_envelope_.set_decay (amp_value (vnorm, region.fileg_decay));
152 filter_envelope_.set_sustain (amp_value (vnorm, region.fileg_sustain));
153 filter_envelope_.set_release (amp_value (vnorm, region.fileg_release));
154 filter_envelope_.start (region, sample_rate_);
155
156 filter_envelope_depth_ = amp_value (vnorm, region.fileg_depth);
157
158 start_filter (fimpl_, ®ion.fil);
159 start_filter (fimpl2_, ®ion.fil2);
160
161 lfo_gen_.start (region, channel_, sample_rate_);
162 }
163
164 void
start_filter(FImpl & fi,const FilterParams * params)165 Voice::start_filter (FImpl& fi, const FilterParams *params)
166 {
167 fi.params = params;
168
169 fi.filter.reset (params->type, sample_rate_);
170
171 fi.cutoff_smooth.reset (sample_rate_, 0.005);
172 fi.resonance_smooth.reset (sample_rate_, 0.005);
173
174 update_cutoff (fi, true);
175 update_resonance (fi, true);
176 }
177
178 float
amp_value(float vnorm,const EGParam & amp_param)179 Voice::amp_value (float vnorm, const EGParam& amp_param)
180 {
181 float value = amp_param.base + amp_param.vel2 * vnorm;
182 value += synth_->get_cc_vec_value (channel_, amp_param.cc_vec);
183
184 return value;
185 }
186
187 void
update_pan_gain()188 Voice::update_pan_gain()
189 {
190 float pan = region_->pan;
191 pan += synth_->get_cc_vec_value (channel_, region_->pan_cc);
192 pan = clamp (pan, -100.f, 100.f);
193
194 pan_left_gain_ = pan_stereo_factor (pan, 0);
195 pan_right_gain_ = pan_stereo_factor (pan, 1);
196 }
197
198 void
update_lr_gain(bool now)199 Voice::update_lr_gain (bool now)
200 {
201 const float global_gain = (1 / 32768.) * synth_->gain() * volume_gain_ * velocity_gain_ * rt_decay_gain_ * amplitude_gain_;
202
203 synth_->debug (" - gain l=%.2f r=%.2f\n", 32768 * pan_left_gain_ * global_gain, 32768 * pan_right_gain_ * global_gain);
204 left_gain_.set (pan_left_gain_ * global_gain, now);
205 right_gain_.set (pan_right_gain_ * global_gain, now);
206 }
207
208 float
apply_xfcurve(float f,XFCurve curve)209 Voice::apply_xfcurve (float f, XFCurve curve)
210 {
211 if (curve == XFCurve::POWER)
212 return sqrtf (f);
213 else
214 return f;
215 }
216
217 float
xfin_gain(int value,int lo,int hi,XFCurve curve)218 Voice::xfin_gain (int value, int lo, int hi, XFCurve curve)
219 {
220 if (value < lo)
221 return 0;
222 if (value < hi && hi > lo)
223 return apply_xfcurve (float (value - lo) / (hi - lo), curve);
224 else
225 return 1;
226 }
227
228 float
xfout_gain(int value,int lo,int hi,XFCurve curve)229 Voice::xfout_gain (int value, int lo, int hi, XFCurve curve)
230 {
231 if (value > hi)
232 return 0;
233 if (value > lo && hi > lo)
234 return apply_xfcurve (1 - float (value - lo) / (hi - lo), curve);
235 else
236 return 1;
237 }
238
239 void
update_volume_gain()240 Voice::update_volume_gain()
241 {
242 float volume = region_->volume;
243 volume += synth_->get_cc_vec_value (channel_, region_->gain_cc);
244
245 volume_gain_ = db_to_factor (volume);
246
247 volume_gain_ *= amp_random_gain_;
248 volume_gain_ *= xfin_gain (velocity_, region_->xfin_lovel, region_->xfin_hivel, region_->xf_velcurve);
249 volume_gain_ *= xfout_gain (velocity_, region_->xfout_lovel, region_->xfout_hivel, region_->xf_velcurve);
250
251 volume_gain_ *= xfin_gain (key_, region_->xfin_lokey, region_->xfin_hikey, region_->xf_keycurve);
252 volume_gain_ *= xfout_gain (key_, region_->xfout_lokey, region_->xfout_hikey, region_->xf_keycurve);
253
254 // xfin_locc / xfin_hicc
255 for (auto xfcc : region_->xfin_ccs)
256 volume_gain_ *= xfin_gain (synth_->get_cc (channel_, xfcc.cc), xfcc.lo, xfcc.hi, region_->xf_cccurve);
257
258 // xfout_locc / xfout_hicc
259 for (auto xfcc : region_->xfout_ccs)
260 volume_gain_ *= xfout_gain (synth_->get_cc (channel_, xfcc.cc), xfcc.lo, xfcc.hi, region_->xf_cccurve);
261 }
262
263 void
update_amplitude_gain()264 Voice::update_amplitude_gain()
265 {
266 float gain = region_->amplitude * 0.01f;
267
268 /* for CCs modulating amplitude, the amplitudes of the individual CCs are multiplied (not added) */
269 for (const auto& entry : region_->amplitude_cc)
270 gain *= synth_->get_cc_curve (channel_, entry) * entry.value * 0.01f;
271
272 amplitude_gain_ = gain;
273 }
274
275 void
update_cutoff(FImpl & fi,bool now)276 Voice::update_cutoff (FImpl& fi, bool now)
277 {
278 float delta_cent = synth_->get_cc_vec_value (channel_, fi.params->cutoff_cc);
279
280 // key tracking
281 delta_cent += (key_ - fi.params->keycenter) * fi.params->keytrack;
282
283 // velocity tracking
284 delta_cent += velocity_ * (1 / 127.f) * fi.params->veltrack;
285
286 /* FIXME: maybe smooth only cc value */
287 fi.cutoff_smooth.set (fi.params->cutoff * exp2f (delta_cent * (1 / 1200.f)), now);
288 }
289
290 void
update_resonance(FImpl & fi,bool now)291 Voice::update_resonance (FImpl& fi, bool now)
292 {
293 fi.resonance_smooth.set (fi.params->resonance + synth_->get_cc_vec_value (channel_, fi.params->resonance_cc), now);
294 }
295
296 void
stop(OffMode off_mode)297 Voice::stop (OffMode off_mode)
298 {
299 state_ = Voice::RELEASED;
300 envelope_.stop (off_mode);
301 filter_envelope_.stop (OffMode::NORMAL);
302 }
303
304 void
kill()305 Voice::kill()
306 {
307 state_ = Voice::IDLE;
308 }
309
310 void
update_cc(int controller)311 Voice::update_cc (int controller)
312 {
313 if (region_->xfin_ccs.size() || region_->xfout_ccs.size())
314 {
315 update_volume_gain();
316 update_lr_gain (false);
317 }
318 if (region_->pan_cc.contains (controller))
319 {
320 update_pan_gain();
321 update_lr_gain (false);
322 }
323 if (region_->gain_cc.contains (controller))
324 {
325 update_volume_gain();
326 update_lr_gain (false);
327 }
328 if (region_->amplitude_cc.contains (controller))
329 {
330 update_amplitude_gain();
331 update_lr_gain (false);
332 }
333
334 if (region_->tune_cc.contains (controller))
335 update_replay_speed (false);
336
337 auto update_filter = [controller, this] (FImpl& fi)
338 {
339 if (fi.params->cutoff_cc.contains (controller))
340 update_cutoff (fi, false);
341
342 if (fi.params->resonance_cc.contains (controller))
343 update_resonance (fi, false);
344 };
345 update_filter (fimpl_);
346 update_filter (fimpl2_);
347 lfo_gen_.update_ccs();
348 }
349
350 void
update_gain()351 Voice::update_gain()
352 {
353 update_lr_gain (false);
354 }
355
356 void
set_pitch_bend(int bend)357 Voice::set_pitch_bend (int bend)
358 {
359 pitch_bend_value_ = bend / double (0x2000) - 1.0;
360 }
361
362 void
update_pitch_bend(int bend)363 Voice::update_pitch_bend (int bend)
364 {
365 set_pitch_bend (bend);
366 update_replay_speed (false);
367 }
368
369 void
process(float ** orig_outputs,uint orig_n_frames)370 Voice::process (float **orig_outputs, uint orig_n_frames)
371 {
372 const auto csample = region_->cached_sample;
373 const auto channels = csample->channels;
374
375 auto get_samples_mono = [csample, this] (uint x, auto& fsamples)
376 {
377 for (uint i = 0; i < fsamples.size(); i++)
378 {
379 if (x >= csample->samples.size())
380 {
381 fsamples[i] = 0;
382 }
383 else
384 {
385 fsamples[i] = csample->samples[x];
386 x++;
387
388 if (loop_enabled_)
389 if (x > uint (region_->loop_end))
390 x = region_->loop_start;
391 }
392 }
393 };
394
395 auto get_samples_stereo = [csample, this] (uint x, auto& fsamples)
396 {
397 for (uint i = 0; i < fsamples.size(); i += 2)
398 {
399 if (x >= csample->samples.size())
400 {
401 fsamples[i] = 0;
402 fsamples[i + 1] = 0;
403 }
404 else
405 {
406 fsamples[i] = csample->samples[x];
407 fsamples[i + 1] = csample->samples[x + 1];
408 x += 2;
409
410 if (loop_enabled_)
411 if (x > uint (region_->loop_end * 2))
412 x = region_->loop_start * 2;
413 }
414 }
415 };
416 /* delay start of voice for delay_samples_ frames */
417 uint dframes = std::min (orig_n_frames, delay_samples_);
418 delay_samples_ -= dframes;
419
420 /* compute n_frames / outputs according to delay */
421 uint n_frames = orig_n_frames - dframes;
422 float *outputs[2] =
423 {
424 orig_outputs[0] + dframes,
425 orig_outputs[1] + dframes
426 };
427
428 /* render lfos */
429 float lfo_buffer[lfo_gen_.buffer_size (n_frames)];
430 lfo_gen_.process (lfo_buffer, n_frames);
431
432 const float *lfo_pitch = lfo_gen_.get (LFOGen::PITCH);
433 if (!lfo_pitch)
434 lfo_pitch = synth_->const_block_1();
435
436 const float *lfo_volume = lfo_gen_.get (LFOGen::VOLUME);
437 if (!lfo_volume)
438 lfo_volume = synth_->const_block_1();
439
440 /* render voice */
441 float out_l[n_frames];
442 float out_r[n_frames];
443
444 for (uint i = 0; i < n_frames; i++)
445 {
446 const uint ii = ppos_;
447 const uint x = ii * channels;
448 const float frac = ppos_ - ii;
449 if (x < csample->samples.size() && !envelope_.done())
450 {
451 const float amp_gain = envelope_.get_next();
452 if (channels == 1)
453 {
454 std::array<float, 2> fsamples;
455 get_samples_mono (x, fsamples);
456
457 const float interp = fsamples[0] * (1 - frac) + fsamples[1] * frac;
458 out_l[i] = interp * amp_gain;
459 out_r[i] = interp * amp_gain;
460 }
461 else if (channels == 2)
462 {
463 std::array<float, 4> fsamples;
464 get_samples_stereo (x, fsamples);
465
466 out_l[i] = (fsamples[0] * (1 - frac) + fsamples[2] * frac) * amp_gain;
467 out_r[i] = (fsamples[1] * (1 - frac) + fsamples[3] * frac) * amp_gain;
468 }
469 else
470 {
471 assert (false);
472 }
473 }
474 else
475 {
476 state_ = IDLE;
477
478 /* output memory is uninitialized, so we need to explicitely write every sampl when done */
479 out_l[i] = 0;
480 out_r[i] = 0;
481 }
482 ppos_ += replay_speed_.get_next() * lfo_pitch[i];
483 if (loop_enabled_)
484 while (ppos_ > region_->loop_end)
485 ppos_ -= (region_->loop_end - region_->loop_start);
486 }
487
488 /* process filters */
489 process_filter (fimpl_, true, out_l, out_r, n_frames, lfo_gen_.get (LFOGen::CUTOFF));
490 process_filter (fimpl2_, false, out_l, out_r, n_frames, nullptr);
491
492 /* add samples to output buffer */
493 if (channels == 2)
494 {
495 for (uint i = 0; i < n_frames; i++)
496 {
497 outputs[0][i] += out_l[i] * lfo_volume[i] * left_gain_.get_next();
498 outputs[1][i] += out_r[i] * lfo_volume[i] * right_gain_.get_next();
499 }
500 }
501 else
502 {
503 for (uint i = 0; i < n_frames; i++)
504 {
505 outputs[0][i] += out_l[i] * lfo_volume[i] * left_gain_.get_next();
506 outputs[1][i] += out_l[i] * lfo_volume[i] * right_gain_.get_next();
507 }
508 }
509 }
510
511 void
process_filter(FImpl & fi,bool envelope,float * left,float * right,uint n_frames,const float * lfo_cutoff_factor)512 Voice::process_filter (FImpl& fi, bool envelope, float *left, float *right, uint n_frames, const float *lfo_cutoff_factor)
513 {
514 if (fi.params->type == Filter::Type::NONE)
515 return;
516
517 float mod_cutoff[n_frames];
518 float mod_resonance[n_frames];
519 float mod_env[n_frames];
520
521 auto run_filter = [&] (const auto& cr_func)
522 {
523 const auto csample = region_->cached_sample;
524 const auto channels = csample->channels;
525
526 if (channels == 2)
527 fi.filter.process_mod (left, right, cr_func, n_frames);
528 else
529 fi.filter.process_mod_mono (left, cr_func, n_frames);
530 };
531
532 if (envelope && filter_envelope_depth_)
533 {
534 const float depth_factor = filter_envelope_depth_ / 1200.;
535
536 if (fi.cutoff_smooth.is_constant() && filter_envelope_.is_constant() && fi.resonance_smooth.is_constant() && !lfo_cutoff_factor)
537 {
538 float cutoff = fi.cutoff_smooth.get_next() * exp2f (filter_envelope_.get_next() * depth_factor);
539 float resonance = fi.resonance_smooth.get_next();
540
541 run_filter ([&] (int i)
542 {
543 return Filter::CR (cutoff, resonance);
544 });
545 }
546 else
547 {
548 for (uint i = 0; i < n_frames; i++)
549 {
550 mod_cutoff[i] = fi.cutoff_smooth.get_next();
551 mod_env[i] = filter_envelope_.get_next();
552 mod_resonance[i] = fi.resonance_smooth.get_next();
553 }
554
555 run_filter ([&] (int i)
556 {
557 float cutoff = mod_cutoff[i] * exp2f (mod_env[i] * depth_factor);
558 if (lfo_cutoff_factor)
559 cutoff *= lfo_cutoff_factor[i];
560
561 return Filter::CR (cutoff, mod_resonance[i]);
562 });
563 }
564 }
565 else
566 {
567 if (fi.cutoff_smooth.is_constant() && fi.resonance_smooth.is_constant() && !lfo_cutoff_factor)
568 {
569 float cutoff = fi.cutoff_smooth.get_next();
570 float resonance = fi.resonance_smooth.get_next();
571
572 run_filter ([&] (int i)
573 {
574 return Filter::CR (cutoff, resonance);
575 });
576 }
577 else
578 {
579 for (uint i = 0; i < n_frames; i++)
580 {
581 mod_cutoff[i] = fi.cutoff_smooth.get_next();
582 mod_resonance[i] = fi.resonance_smooth.get_next();
583 }
584 run_filter ([&] (int i)
585 {
586 float cutoff = mod_cutoff[i];
587 if (lfo_cutoff_factor)
588 cutoff *= lfo_cutoff_factor[i];
589
590 return Filter::CR (cutoff, mod_resonance[i]);
591 });
592 }
593 }
594 }
595