1 // samplv1.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 *****************************************************************************/
21
22 #include "samplv1.h"
23
24 #include "samplv1_sample.h"
25
26 #include "samplv1_wave.h"
27 #include "samplv1_ramp.h"
28
29 #include "samplv1_list.h"
30
31 #include "samplv1_filter.h"
32 #include "samplv1_formant.h"
33
34 #include "samplv1_fx.h"
35 #include "samplv1_reverb.h"
36
37 #include "samplv1_pshifter.h"
38
39 #include "samplv1_config.h"
40 #include "samplv1_controls.h"
41 #include "samplv1_programs.h"
42 #include "samplv1_tuning.h"
43
44 #include "samplv1_sched.h"
45
46
47 #ifdef CONFIG_DEBUG_0
48 #include <cstdio>
49 #endif
50
51 #include <cstring>
52
53
54 //-------------------------------------------------------------------------
55 // samplv1_impl
56 //
57 // -- borrowed and revamped from synth.h of synth4
58 // Copyright (C) 2007 jorgen, linux-vst.com
59 //
60
61 const uint8_t MAX_VOICES = 64; // max polyphony
62 const uint8_t MAX_NOTES = 128;
63
64 const float MIN_ENV_MSECS = 0.5f; // min 500 usec per stage
65 const float MAX_ENV_MSECS = 5000.0f; // max 5 sec per stage (default)
66
67 const float OCTAVE_SCALE = 12.0f;
68 const float TUNING_SCALE = 1.0f;
69 const float SWEEP_SCALE = 0.5f;
70 const float PITCH_SCALE = 0.5f;
71
72 const uint8_t MAX_DIRECT_NOTES = (MAX_VOICES >> 2);
73
74
75 // maximum helper
76
samplv1_max(float a,float b)77 inline float samplv1_max ( float a, float b )
78 {
79 return (a > b ? a : b);
80 }
81
82
83 // hyperbolic-tangent fast approximation
84
samplv1_tanhf(const float x)85 inline float samplv1_tanhf ( const float x )
86 {
87 const float x2 = x * x;
88 return x * (27.0f + x2) / (27.0f + 9.0f * x2);
89 }
90
91
92 // sigmoids
93
samplv1_sigmoid(const float x)94 inline float samplv1_sigmoid ( const float x )
95 {
96 // return 2.0f / (1.0f + ::expf(-5.0f * x)) - 1.0f;
97 return samplv1_tanhf(2.0f * x);
98 }
99
samplv1_sigmoid_0(const float x,const float t0)100 inline float samplv1_sigmoid_0 ( const float x, const float t0 )
101 {
102 const float t1 = 1.0f - t0;
103 #if 0
104 if (x > +t1)
105 return +t1 + t0 * samplv1_tanhf(+(x - t1) / t0);
106 else
107 if (x < -t1)
108 return -t1 - t0 * samplv1_tanhf(-(x + t1) / t0);
109 else
110 return x;
111 #else
112 return (x < -1.0f ? -t1 : (x > +1.0f ? t1 : t1 * x * (1.5f - 0.5f * x * x)));
113 #endif
114 }
115
samplv1_sigmoid_1(const float x,const float t0=0.01f)116 inline float samplv1_sigmoid_1 ( const float x, const float t0 = 0.01f )
117 {
118 return 0.5f * (1.0f + samplv1_sigmoid_0(2.0f * x - 1.0f, t0));
119 }
120
121
122 // velocity hard-split curve
123
samplv1_velocity(const float x,const float p=0.2f)124 inline float samplv1_velocity ( const float x, const float p = 0.2f )
125 {
126 return ::powf(x, (1.0f - p));
127 }
128
129
130 // pitchbend curve
131
samplv1_pow2f(const float x)132 inline float samplv1_pow2f ( const float x )
133 {
134 // simplest power-of-2 straight linearization
135 // -- x argument valid in [-1, 1] interval
136 // return 1.0f + (x < 0.0f ? 0.5f : 1.0f) * x;
137 return ::powf(2.0f, x);
138 }
139
140
141 // convert note to frequency (hertz)
142
samplv1_freq2(float delta)143 inline float samplv1_freq2 ( float delta )
144 {
145 return ::powf(2.0f, delta / 12.0f);
146 }
147
samplv1_freq(int note)148 inline float samplv1_freq ( int note )
149 {
150 return (440.0f / 32.0f) * samplv1_freq2(float(note - 9));
151 }
152
153
154 // parameter port (basic)
155
156 class samplv1_port
157 {
158 public:
159
samplv1_port()160 samplv1_port() : m_port(nullptr), m_value(0.0f), m_vport(0.0f) {}
161
~samplv1_port()162 virtual ~samplv1_port() {}
163
set_port(float * port)164 void set_port(float *port)
165 { m_port = port; }
port() const166 float *port() const
167 { return m_port; }
168
set_value(float value)169 virtual void set_value(float value)
170 { m_value = value; if (m_port) m_vport = *m_port; }
171
value() const172 float value() const
173 { return m_value; }
value_ptr()174 float *value_ptr()
175 { tick(1); return &m_value; }
176
tick(uint32_t)177 virtual float tick(uint32_t /*nstep*/)
178 {
179 if (m_port && ::fabsf(*m_port - m_vport) > 0.001f)
180 set_value(*m_port);
181
182 return m_value;
183 }
184
operator *()185 float operator *()
186 { return tick(1); }
187
188 private:
189
190 float *m_port;
191 float m_value;
192 float m_vport;
193 };
194
195
196 // parameter port (smoothed)
197
198 class samplv1_port2 : public samplv1_port
199 {
200 public:
201
samplv1_port2()202 samplv1_port2() : m_vtick(0.0f), m_vstep(0.0f), m_nstep(0) {}
203
204 static const uint32_t NSTEP = 32;
205
set_value(float value)206 void set_value(float value)
207 {
208 m_vtick = samplv1_port::value();
209
210 m_nstep = NSTEP;
211 m_vstep = (value - m_vtick) / float(m_nstep);
212
213 samplv1_port::set_value(value);
214 }
215
tick(uint32_t nstep)216 float tick(uint32_t nstep)
217 {
218 if (m_nstep == 0)
219 return samplv1_port::tick(nstep);
220
221 if (m_nstep >= nstep) {
222 m_vtick += m_vstep * float(nstep);
223 m_nstep -= nstep;
224 } else {
225 m_vtick += m_vstep * float(m_nstep);
226 m_nstep = 0;
227 }
228
229 return m_vtick;
230 }
231
232 private:
233
234 float m_vtick;
235 float m_vstep;
236 uint32_t m_nstep;
237 };
238
239
240 // parameter port (scheduled/detached)
241
242 class samplv1_port3_sched : public samplv1_sched
243 {
244 public:
245
246 // ctor.
samplv1_port3_sched(samplv1 * pSampl)247 samplv1_port3_sched(samplv1 *pSampl)
248 : samplv1_sched(pSampl, samplv1_sched::Controller) {}
249
250 // (pure) virtual prober.
251 virtual float probe(int sid) const = 0;
252 };
253
254
255 class samplv1_port3 : public samplv1_port
256 {
257 public:
258
samplv1_port3(samplv1_port3_sched * sched,samplv1::ParamIndex index)259 samplv1_port3(samplv1_port3_sched *sched, samplv1::ParamIndex index)
260 : m_sched(sched), m_index(index) {}
261
set_value(float value)262 void set_value(float value)
263 {
264 const float v0 = m_sched->probe(m_index);
265 const float d0 = ::fabsf(value - v0);
266
267 samplv1_port::set_value(value);
268
269 if (d0 > 0.001f)
270 m_sched->schedule(m_index);
271 }
272
set_value_sync(float value)273 void set_value_sync(float value)
274 {
275 samplv1_port::set_value(value);
276 }
277
278 private:
279
280 samplv1_port3_sched *m_sched;
281 samplv1::ParamIndex m_index;
282 };
283
284
285 // envelope
286
287 struct samplv1_env
288 {
289 // envelope stages
290
291 enum Stage { Idle = 0, Attack, Decay, Sustain, Release, End };
292
293 // per voice
294
295 struct State
296 {
297 // ctor.
Statesamplv1_env::State298 State() : running(false), stage(Idle),
299 phase(0.0f), delta(0.0f), value(0.0f),
300 c1(1.0f), c0(0.0f), frames(0) {}
301
302 // process
ticksamplv1_env::State303 float tick()
304 {
305 if (running && frames > 0) {
306 phase += delta;
307 value = c1 * phase * (2.0f - phase) + c0;
308 --frames;
309 }
310 return value;
311 }
312
313 // state
314 bool running;
315 Stage stage;
316 float phase;
317 float delta;
318 float value;
319 float c1, c0;
320 uint32_t frames;
321 };
322
startsamplv1_env323 void start(State *p)
324 {
325 p->running = true;
326 p->stage = Attack;
327 p->frames = uint32_t(*attack * *attack * max_frames);
328 if (p->frames < min_frames1) // prevent click on too fast attack
329 p->frames = min_frames1;
330 p->phase = 0.0f;
331 p->delta = 1.0f / float(p->frames);
332 p->value = 0.0f;
333 p->c1 = 1.0f;
334 p->c0 = 0.0f;
335 }
336
nextsamplv1_env337 void next(State *p)
338 {
339 if (p->stage == Attack) {
340 p->stage = Decay;
341 p->frames = uint32_t(*decay * *decay * max_frames);
342 if (p->frames < min_frames2) // prevent click on too fast decay
343 p->frames = min_frames2;
344 p->phase = 0.0f;
345 p->delta = 1.0f / float(p->frames);
346 p->c1 = *sustain - 1.0f;
347 p->c0 = p->value;
348 }
349 else if (p->stage == Decay) {
350 p->running = false; // stay at this stage until note_off received
351 p->stage = Sustain;
352 p->frames = 0;
353 p->phase = 0.0f;
354 p->delta = 0.0f;
355 p->c1 = 0.0f;
356 p->c0 = p->value;
357 }
358 else if (p->stage == Release) {
359 p->running = false;
360 p->stage = End;
361 p->frames = 0;
362 p->phase = 0.0f;
363 p->delta = 0.0f;
364 p->value = 0.0f;
365 p->c1 = 0.0f;
366 p->c0 = 0.0f;
367 }
368 }
369
note_offsamplv1_env370 void note_off(State *p)
371 {
372 p->running = true;
373 p->stage = Release;
374 p->frames = uint32_t(*release * *release * max_frames);
375 if (p->frames < min_frames2) // prevent click on too fast release
376 p->frames = min_frames2;
377 p->phase = 0.0f;
378 p->delta = 1.0f / float(p->frames);
379 p->c1 = -(p->value);
380 p->c0 = p->value;
381 }
382
note_off_fastsamplv1_env383 void note_off_fast(State *p)
384 {
385 p->running = true;
386 p->stage = Release;
387 p->frames = min_frames2;
388 p->phase = 0.0f;
389 p->delta = 1.0f / float(p->frames);
390 p->c1 = -(p->value);
391 p->c0 = p->value;
392 }
393
restartsamplv1_env394 void restart(State *p, bool legato)
395 {
396 p->running = true;
397 if (legato) {
398 p->stage = Decay;
399 p->frames = min_frames2;
400 p->phase = 0.0f;
401 p->delta = 1.0f / float(p->frames);
402 p->c1 = *sustain - p->value;
403 p->c0 = 0.0f;
404 } else {
405 p->stage = Attack;
406 p->frames = uint32_t(*attack * *attack * max_frames);
407 if (p->frames < min_frames1)
408 p->frames = min_frames1;
409 p->phase = 0.0f;
410 p->delta = 1.0f / float(p->frames);
411 p->c1 = 1.0f;
412 p->c0 = 0.0f;
413 }
414 }
415
idlesamplv1_env416 void idle(State *p)
417 {
418 p->running = false;
419 p->stage = Idle;
420 p->frames = 0;
421 p->phase = 0.0f;
422 p->delta = 0.0f;
423 p->value = 1.0f;
424 p->c1 = 0.0f;
425 p->c0 = 0.0f;
426 }
427
428 // parameters
429
430 samplv1_port attack;
431 samplv1_port decay;
432 samplv1_port sustain;
433 samplv1_port release;
434
435 uint32_t min_frames1;
436 uint32_t min_frames2;
437 uint32_t max_frames;
438 };
439
440
441 // midi control
442
443 struct samplv1_ctl
444 {
samplv1_ctlsamplv1_ctl445 samplv1_ctl() { reset(); }
446
resetsamplv1_ctl447 void reset()
448 {
449 pressure = 0.0f;
450 pitchbend = 1.0f;
451 modwheel = 0.0f;
452 panning = 0.0f;
453 volume = 1.0f;
454 sustain = false;
455 }
456
457 float pressure;
458 float pitchbend;
459 float modwheel;
460 float panning;
461 float volume;
462 bool sustain;
463 };
464
465
466 // dco
467
468 class samplv1_gen : samplv1_port3_sched
469 {
470 public:
471
samplv1_gen(samplv1 * pSampl)472 samplv1_gen(samplv1 *pSampl)
473 : samplv1_port3_sched(pSampl),
474 reverse(this, samplv1::GEN1_REVERSE),
475 offset(this, samplv1::GEN1_OFFSET),
476 offset_1(this, samplv1::GEN1_OFFSET_1),
477 offset_2(this, samplv1::GEN1_OFFSET_2),
478 loop(this, samplv1::GEN1_LOOP),
479 loop_1(this, samplv1::GEN1_LOOP_1),
480 loop_2(this, samplv1::GEN1_LOOP_2) {}
481
482 samplv1_port sample;
483 samplv1_port3 reverse;
484 samplv1_port3 offset;
485 samplv1_port3 offset_1;
486 samplv1_port3 offset_2;
487 samplv1_port3 loop;
488 samplv1_port3 loop_1;
489 samplv1_port3 loop_2;
490 samplv1_port octave;
491 samplv1_port tuning;
492 samplv1_port glide;
493 samplv1_port envtime;
494
495 float sample0, envtime0;
496
497 protected:
498
probe(int sid) const499 float probe(int sid) const
500 {
501 float ret = 0.0f;
502 samplv1 *pSampl = samplv1_port3_sched::instance();
503
504 switch (samplv1::ParamIndex(sid)) {
505 case samplv1::GEN1_REVERSE:
506 ret = (pSampl->isReverse() ? 1.0f : 0.0f);
507 break;
508 case samplv1::GEN1_OFFSET:
509 ret = (pSampl->isOffset() ? 1.0f : 0.0f);
510 break;
511 case samplv1::GEN1_OFFSET_1: {
512 const uint32_t iSampleLength
513 = pSampl->sample()->length();
514 const uint32_t iOffsetStart
515 = pSampl->offsetStart();
516 ret = (iSampleLength > 0
517 ? float(iOffsetStart) / float(iSampleLength)
518 : 0.0f);
519 break;
520 }
521 case samplv1::GEN1_OFFSET_2: {
522 const uint32_t iSampleLength
523 = pSampl->sample()->length();
524 const uint32_t iOffsetEnd
525 = pSampl->offsetEnd();
526 ret = (iSampleLength > 0
527 ? float(iOffsetEnd) / float(iSampleLength)
528 : 1.0f);
529 break;
530 }
531 case samplv1::GEN1_LOOP:
532 ret = (pSampl->isLoop() ? 1.0f : 0.0f);
533 break;
534 case samplv1::GEN1_LOOP_1: {
535 const uint32_t iSampleLength
536 = pSampl->sample()->length();
537 const uint32_t iLoopStart
538 = pSampl->loopStart();
539 ret = (iSampleLength > 0
540 ? float(iLoopStart) / float(iSampleLength)
541 : 0.0f);
542 break;
543 }
544 case samplv1::GEN1_LOOP_2: {
545 const uint32_t iSampleLength
546 = pSampl->sample()->length();
547 const uint32_t iLoopEnd
548 = pSampl->loopEnd();
549 ret = (iSampleLength > 0
550 ? float(iLoopEnd) / float(iSampleLength)
551 : 1.0f);
552 break;
553 }
554 default:
555 break;
556 }
557
558 return ret;
559 }
560
process(int sid)561 void process(int sid)
562 {
563 samplv1 *pSampl = samplv1_port3_sched::instance();
564
565 switch (samplv1::ParamIndex(sid)) {
566 case samplv1::GEN1_REVERSE:
567 pSampl->setReverse(reverse.value() > 0.5f, true);
568 break;
569 case samplv1::GEN1_OFFSET:
570 pSampl->setOffset(offset.value() > 0.5f, true);
571 break;
572 case samplv1::GEN1_OFFSET_1:
573 if (pSampl->isOffset()) {
574 const uint32_t iSampleLength
575 = pSampl->sample()->length();
576 const uint32_t iOffsetEnd
577 = pSampl->offsetEnd();
578 uint32_t iOffsetStart
579 = uint32_t(offset_1.value() * float(iSampleLength));
580 if (pSampl->isLoop()) {
581 const uint32_t iLoopStart
582 = pSampl->loopStart();
583 if (iOffsetStart >= iLoopStart)
584 iOffsetStart = iLoopStart - 1;
585 }
586 if (iOffsetStart >= iOffsetEnd)
587 iOffsetStart = iOffsetEnd - 1;
588 pSampl->setOffsetRange(iOffsetStart, iOffsetEnd, true);
589 }
590 break;
591 case samplv1::GEN1_OFFSET_2:
592 if (pSampl->isOffset()) {
593 const uint32_t iSampleLength
594 = pSampl->sample()->length();
595 const uint32_t iOffsetStart
596 = pSampl->offsetStart();
597 uint32_t iOffsetEnd
598 = uint32_t(offset_2.value() * float(iSampleLength));
599 if (pSampl->isLoop()) {
600 const uint32_t iLoopEnd
601 = pSampl->loopEnd();
602 if (iLoopEnd >= iOffsetEnd)
603 iOffsetEnd = iLoopEnd + 1;
604 }
605 if (iOffsetStart >= iOffsetEnd)
606 iOffsetEnd = iOffsetStart + 1;
607 pSampl->setOffsetRange(iOffsetStart, iOffsetEnd, true);
608 }
609 break;
610 case samplv1::GEN1_LOOP:
611 pSampl->setLoop(loop.value() > 0.5f, true);
612 break;
613 case samplv1::GEN1_LOOP_1:
614 if (pSampl->isLoop()) {
615 const uint32_t iSampleLength
616 = pSampl->sample()->length();
617 const uint32_t iLoopEnd
618 = pSampl->loopEnd();
619 uint32_t iLoopStart
620 = uint32_t(loop_1.value() * float(iSampleLength));
621 if (pSampl->isOffset()) {
622 const uint32_t iOffsetStart
623 = pSampl->offsetStart();
624 if (iLoopStart < iOffsetStart)
625 iLoopStart = iOffsetStart;
626 }
627 if (iLoopStart >= iLoopEnd)
628 iLoopStart = iLoopEnd - 1;
629 pSampl->setLoopRange(iLoopStart, iLoopEnd, true);
630 }
631 break;
632 case samplv1::GEN1_LOOP_2:
633 if (pSampl->isLoop()) {
634 const uint32_t iSampleLength
635 = pSampl->sample()->length();
636 const uint32_t iLoopStart
637 = pSampl->loopStart();
638 uint32_t iLoopEnd
639 = uint32_t(loop_2.value() * float(iSampleLength));
640 if (pSampl->isOffset()) {
641 const uint32_t iOffsetEnd
642 = pSampl->offsetEnd();
643 if (iLoopEnd > iOffsetEnd)
644 iLoopEnd = iOffsetEnd;
645 }
646 if (iLoopStart >= iLoopEnd)
647 iLoopEnd = iLoopStart + 1;
648 pSampl->setLoopRange(iLoopStart, iLoopEnd, true);
649 }
650 break;
651 default:
652 break;
653 }
654 }
655 };
656
657
658 // dcf
659
660 struct samplv1_dcf
661 {
662 samplv1_port enabled;
663 samplv1_port2 cutoff;
664 samplv1_port2 reso;
665 samplv1_port type;
666 samplv1_port slope;
667 samplv1_port2 envelope;
668
669 samplv1_env env;
670 };
671
672
673 // lfo
674 struct samplv1_voice;
675
676 struct samplv1_lfo
677 {
678 samplv1_port enabled;
679 samplv1_port shape;
680 samplv1_port width;
681 samplv1_port2 bpm;
682 samplv1_port2 rate;
683 samplv1_port sync;
684 samplv1_port2 sweep;
685 samplv1_port2 pitch;
686 samplv1_port2 cutoff;
687 samplv1_port2 reso;
688 samplv1_port2 panning;
689 samplv1_port2 volume;
690
691 samplv1_env env;
692
693 samplv1_voice *psync;
694 };
695
696
697 // dca
698
699 struct samplv1_dca
700 {
701 samplv1_port enabled;
702 samplv1_port volume;
703
704 samplv1_env env;
705 };
706
707
708
709 // def (ranges)
710
711 struct samplv1_def
712 {
713 samplv1_port pitchbend;
714 samplv1_port modwheel;
715 samplv1_port pressure;
716 samplv1_port velocity;
717 samplv1_port channel;
718 samplv1_port mono;
719 };
720
721
722 // out (mix)
723
724 struct samplv1_out
725 {
726 samplv1_port width;
727 samplv1_port panning;
728 samplv1_port fxsend;
729 samplv1_port volume;
730 };
731
732
733 // chorus (fx)
734
735 struct samplv1_cho
736 {
737 samplv1_port wet;
738 samplv1_port delay;
739 samplv1_port feedb;
740 samplv1_port rate;
741 samplv1_port mod;
742 };
743
744
745 // flanger (fx)
746
747 struct samplv1_fla
748 {
749 samplv1_port wet;
750 samplv1_port delay;
751 samplv1_port feedb;
752 samplv1_port daft;
753 };
754
755
756 // phaser (fx)
757
758 struct samplv1_pha
759 {
760 samplv1_port wet;
761 samplv1_port rate;
762 samplv1_port feedb;
763 samplv1_port depth;
764 samplv1_port daft;
765 };
766
767
768 // delay (fx)
769
770 struct samplv1_del
771 {
772 samplv1_port wet;
773 samplv1_port delay;
774 samplv1_port feedb;
775 samplv1_port bpm;
776 };
777
778
779 // reverb
780
781 struct samplv1_rev
782 {
783 samplv1_port wet;
784 samplv1_port room;
785 samplv1_port damp;
786 samplv1_port feedb;
787 samplv1_port width;
788 };
789
790
791 // dynamic(compressor/limiter)
792
793 struct samplv1_dyn
794 {
795 samplv1_port compress;
796 samplv1_port limiter;
797 };
798
799
800 // keyboard/note range
801
802 struct samplv1_key
803 {
804 samplv1_port low;
805 samplv1_port high;
806
is_notesamplv1_key807 bool is_note(int key)
808 {
809 return (key >= int(*low) && int(*high) >= key);
810 }
811 };
812
813
814 // glide (portamento)
815
816 struct samplv1_glide
817 {
samplv1_glidesamplv1_glide818 samplv1_glide(float& last) : m_last(last) { reset(); }
819
resetsamplv1_glide820 void reset( uint32_t frames = 0, float freq = 0.0f )
821 {
822 m_frames = frames;
823
824 if (m_frames > 0) {
825 m_freq = m_last;
826 m_step = (m_last - freq) / float(m_frames);
827 } else {
828 m_freq = freq;
829 m_step = 0.0f;
830 }
831
832 m_last = freq;
833 }
834
ticksamplv1_glide835 float tick()
836 {
837 if (m_frames > 0) {
838 m_freq -= m_step;
839 --m_frames;
840 }
841
842 return m_freq;
843 }
844
845 private:
846
847 uint32_t m_frames;
848
849 float m_step;
850 float m_freq;
851
852 float& m_last;
853 };
854
855
856 // balance smoother (1 parameters)
857
858 class samplv1_bal1 : public samplv1_ramp1
859 {
860 public:
861
samplv1_bal1()862 samplv1_bal1() : samplv1_ramp1(2) {}
863
864 protected:
865
evaluate(uint16_t i)866 float evaluate(uint16_t i)
867 {
868 samplv1_ramp1::update();
869
870 const float wbal = 0.25f * M_PI
871 * (1.0f + m_param1_v);
872
873 return M_SQRT2 * (i & 1 ? ::sinf(wbal) : ::cosf(wbal));
874 }
875 };
876
877
878 // balance smoother (2 parameters)
879
880 class samplv1_bal2 : public samplv1_ramp2
881 {
882 public:
883
samplv1_bal2()884 samplv1_bal2() : samplv1_ramp2(2) {}
885
886 protected:
887
evaluate(uint16_t i)888 float evaluate(uint16_t i)
889 {
890 samplv1_ramp2::update();
891
892 const float wbal = 0.25f * M_PI
893 * (1.0f + m_param1_v)
894 * (1.0f + m_param2_v);
895
896 return M_SQRT2 * (i & 1 ? ::sinf(wbal) : ::cosf(wbal));
897 }
898 };
899
900
901 // pressure smoother (3 parameters)
902
903 class samplv1_pre : public samplv1_ramp3
904 {
905 public:
906
samplv1_pre()907 samplv1_pre() : samplv1_ramp3() {}
908
909 protected:
910
evaluate(uint16_t)911 float evaluate(uint16_t)
912 {
913 samplv1_ramp3::update();
914
915 return m_param1_v * samplv1_max(m_param2_v, m_param3_v);
916 }
917 };
918
919
920 // common phasor (LFO sync)
921
922 class samplv1_phasor
923 {
924 public:
925
samplv1_phasor(uint32_t nsize=1024)926 samplv1_phasor(uint32_t nsize = 1024)
927 : m_nsize(nsize), m_nframes(0) {}
928
process(uint32_t nframes)929 void process(uint32_t nframes)
930 {
931 m_nframes += nframes;
932 while (m_nframes >= m_nsize)
933 m_nframes -= m_nsize;
934 }
935
pshift() const936 float pshift() const
937 { return float(m_nframes) / float(m_nsize); }
938
939 private:
940
941 uint32_t m_nsize;
942 uint32_t m_nframes;
943 };
944
945
946 // forward decl.
947
948 class samplv1_impl;
949
950
951 // voice
952
953 struct samplv1_voice : public samplv1_list<samplv1_voice>
954 {
955 samplv1_voice(samplv1_impl *pImpl);
956
957 int note; // voice note
958
959 float vel; // key velocity
960 float pre; // key pressure/after-touch
961
962 samplv1_generator gen1; // generator
963 samplv1_oscillator lfo1; // low frequency oscilattor
964
965 float gen1_freq; // frequency and phase
966
967 float lfo1_sample;
968
969 samplv1_filter1 dcf11, dcf12; // filters
970 samplv1_filter2 dcf13, dcf14;
971 samplv1_filter3 dcf15, dcf16;
972 samplv1_formant dcf17, dcf18;
973
974 samplv1_env::State dca1_env; // envelope states
975 samplv1_env::State dcf1_env;
976 samplv1_env::State lfo1_env;
977
978 samplv1_glide gen1_glide; // glides (portamento)
979
980 samplv1_pre dca1_pre;
981
982 float out1_panning;
983 float out1_volume;
984
985 samplv1_bal1 out1_pan; // output panning
986 samplv1_ramp1 out1_vol; // output volume
987
988 bool sustain;
989 };
990
991
992 // MIDI input asynchronous status notification
993
994 class samplv1_midi_in : public samplv1_sched
995 {
996 public:
997
samplv1_midi_in(samplv1 * pSampl)998 samplv1_midi_in (samplv1 *pSampl)
999 : samplv1_sched(pSampl, MidiIn),
1000 m_enabled(false), m_count(0) {}
1001
schedule_event()1002 void schedule_event()
1003 { if (m_enabled && ++m_count < 2) schedule(-1); }
schedule_note(int key,int vel)1004 void schedule_note(int key, int vel)
1005 { if (m_enabled) schedule((vel << 7) | key); }
1006
process(int)1007 void process(int) {}
1008
enabled(bool on)1009 void enabled(bool on)
1010 { m_enabled = on; m_count = 0; }
1011
count()1012 uint32_t count()
1013 {
1014 const uint32_t ret = m_count;
1015 m_count = 0;
1016 return ret;
1017 }
1018
1019 private:
1020
1021 bool m_enabled;
1022 uint32_t m_count;
1023 };
1024
1025
1026 // micro-tuning/instance implementation
1027
1028 class samplv1_tun
1029 {
1030 public:
1031
samplv1_tun()1032 samplv1_tun() : enabled(false), refPitch(440.0f), refNote(69) {}
1033
1034 bool enabled;
1035 float refPitch;
1036 int refNote;
1037 QString scaleFile;
1038 QString keyMapFile;
1039 };
1040
1041
1042 // polyphonic sampler implementation
1043
1044 class samplv1_impl
1045 {
1046 public:
1047
1048 samplv1_impl(samplv1 *pSampl, uint16_t nchannels, float srate);
1049
1050 ~samplv1_impl();
1051
1052 void setChannels(uint16_t nchannels);
1053 uint16_t channels() const;
1054
1055 void setSampleRate(float srate);
1056 float sampleRate() const;
1057
1058 void setSampleFile(const char *pszSampleFile, uint16_t otabs);
1059 const char *sampleFile() const;
1060 uint16_t octaves() const;
1061
1062 void setBufferSize(uint32_t nsize);
1063 uint32_t bufferSize() const;
1064
1065 void setTempo(float bpm);
1066 float tempo() const;
1067
1068 void setParamPort(samplv1::ParamIndex index, float *pfParam);
1069 samplv1_port *paramPort(samplv1::ParamIndex index);
1070
1071 void setParamValue(samplv1::ParamIndex index, float fValue);
1072 float paramValue(samplv1::ParamIndex index);
1073
1074 void updateEnvTimes();
1075
1076 samplv1_controls *controls();
1077 samplv1_programs *programs();
1078
1079 void setTuningEnabled(bool enabled);
1080 bool isTuningEnabled() const;
1081
1082 void setTuningRefPitch(float refPitch);
1083 float tuningRefPitch() const;
1084
1085 void setTuningRefNote(int refNote);
1086 int tuningRefNote() const;
1087
1088 void setTuningScaleFile(const char *pszScaleFile);
1089 const char *tuningScaleFile() const;
1090
1091 void setTuningKeyMapFile(const char *pszKeyMapFile);
1092 const char *tuningKeyMapFile() const;
1093
1094 void resetTuning();
1095
1096 void process_midi(uint8_t *data, uint32_t size);
1097 void process(float **ins, float **outs, uint32_t nframes);
1098
1099 void stabilize();
1100 void reset();
1101
1102 void sampleReverseTest();
1103 void sampleReverseSync();
1104
1105 void sampleOffsetTest();
1106 void sampleOffsetSync();
1107 void sampleOffsetRangeSync();
1108
1109 void sampleLoopTest();
1110 void sampleLoopSync();
1111 void sampleLoopRangeSync();
1112
1113 void midiInEnabled(bool on);
1114 uint32_t midiInCount();
1115
1116 void directNoteOn(int note, int vel);
1117
1118 bool running(bool on);
1119
1120 samplv1_sample gen1_sample;
1121 samplv1_wave_lf lfo1_wave;
1122
1123 float gen1_last;
1124
1125 samplv1_formant::Impl dcf1_formant;
1126
1127 protected:
1128
1129 void allSoundOff();
1130 void allControllersOff();
1131 void allNotesOff();
1132 void allSustainOff();
1133 void allSustainOn();
1134
get_bpm(float bpm) const1135 float get_bpm ( float bpm ) const
1136 { return (bpm > 0.0f ? bpm : m_bpm); }
1137
alloc_voice()1138 samplv1_voice *alloc_voice ()
1139 {
1140 samplv1_voice *pv = m_free_list.next();
1141 if (pv) {
1142 m_free_list.remove(pv);
1143 m_play_list.append(pv);
1144 ++m_nvoices;
1145 }
1146 return pv;
1147 }
1148
free_voice(samplv1_voice * pv)1149 void free_voice ( samplv1_voice *pv )
1150 {
1151 if (m_lfo1.psync == pv)
1152 m_lfo1.psync = nullptr;
1153
1154 m_play_list.remove(pv);
1155 m_free_list.append(pv);
1156 --m_nvoices;
1157 }
1158
1159 void alloc_sfxs(uint32_t nsize);
1160
1161 private:
1162
1163 samplv1_config m_config;
1164 samplv1_controls m_controls;
1165 samplv1_programs m_programs;
1166 samplv1_midi_in m_midi_in;
1167 samplv1_tun m_tun;
1168
1169 uint16_t m_nchannels;
1170 float m_srate;
1171 float m_bpm;
1172
1173 float m_freqs[MAX_NOTES];
1174
1175 samplv1_ctl m_ctl1;
1176
1177 samplv1_gen m_gen1;
1178 samplv1_dcf m_dcf1;
1179 samplv1_lfo m_lfo1;
1180 samplv1_dca m_dca1;
1181 samplv1_out m_out1;
1182
1183 samplv1_def m_def;
1184
1185 samplv1_cho m_cho;
1186 samplv1_fla m_fla;
1187 samplv1_pha m_pha;
1188 samplv1_del m_del;
1189 samplv1_rev m_rev;
1190 samplv1_dyn m_dyn;
1191
1192 samplv1_key m_key;
1193
1194 samplv1_voice **m_voices;
1195 samplv1_voice *m_notes[MAX_NOTES];
1196
1197 samplv1_list<samplv1_voice> m_free_list;
1198 samplv1_list<samplv1_voice> m_play_list;
1199
1200 samplv1_ramp1 m_wid1;
1201 samplv1_bal2 m_pan1;
1202 samplv1_ramp3 m_vol1;
1203
1204 float **m_sfxs;
1205 uint32_t m_nsize;
1206
1207 samplv1_fx_chorus m_chorus;
1208 samplv1_fx_flanger *m_flanger;
1209 samplv1_fx_phaser *m_phaser;
1210 samplv1_fx_delay *m_delay;
1211 samplv1_fx_comp *m_comp;
1212
1213 samplv1_reverb m_reverb;
1214
1215 // process direct note on/off...
1216 volatile uint16_t m_direct_note;
1217
1218 struct direct_note {
1219 uint8_t status, note, vel;
1220 } m_direct_notes[MAX_DIRECT_NOTES];
1221
1222 volatile int m_nvoices;
1223
1224 volatile bool m_running;
1225 };
1226
1227
1228 // voice constructor
1229
samplv1_voice(samplv1_impl * pImpl)1230 samplv1_voice::samplv1_voice ( samplv1_impl *pImpl ) :
1231 note(-1),
1232 vel(0.0f),
1233 pre(0.0f),
1234 gen1(&pImpl->gen1_sample),
1235 lfo1(&pImpl->lfo1_wave),
1236 gen1_freq(0.0f),
1237 lfo1_sample(0.0f),
1238 dcf17(&pImpl->dcf1_formant),
1239 dcf18(&pImpl->dcf1_formant),
1240 gen1_glide(pImpl->gen1_last),
1241 out1_volume(1.0f),
1242 out1_panning(0.0f),
1243 sustain(false)
1244 {
1245 }
1246
1247
1248 // engine constructor
1249
samplv1_impl(samplv1 * pSampl,uint16_t nchannels,float srate)1250 samplv1_impl::samplv1_impl (
1251 samplv1 *pSampl, uint16_t nchannels, float srate )
1252 : gen1_sample(srate), m_controls(pSampl), m_programs(pSampl),
1253 m_midi_in(pSampl), m_bpm(180.0f), m_gen1(pSampl),
1254 m_nvoices(0), m_running(false)
1255 {
1256 // null sample.
1257 m_gen1.sample0 = 0.0f;
1258
1259 // max env. stage length (default)
1260 m_gen1.envtime0 = 0.0001f * MAX_ENV_MSECS;
1261
1262 // glide note.
1263 gen1_last = 0.0f;
1264
1265 // allocate voice pool.
1266 m_voices = new samplv1_voice * [MAX_VOICES];
1267
1268 for (int i = 0; i < MAX_VOICES; ++i) {
1269 m_voices[i] = new samplv1_voice(this);
1270 m_free_list.append(m_voices[i]);
1271 }
1272
1273 for (int note = 0; note < MAX_NOTES; ++note)
1274 m_notes[note] = nullptr;
1275
1276 // local buffers none yet
1277 m_sfxs = nullptr;
1278 m_nsize = 0;
1279
1280 // flangers none yet
1281 m_flanger = nullptr;
1282
1283 // phasers none yet
1284 m_phaser = nullptr;
1285
1286 // delays none yet
1287 m_delay = nullptr;
1288
1289 // compressors none yet
1290 m_comp = nullptr;
1291
1292 // Pitch-shifting support...
1293 samplv1_pshifter::setDefaultType(
1294 samplv1_pshifter::Type(m_config.iPitchShiftType));
1295
1296 // Micro-tuning support, if any...
1297 resetTuning();
1298
1299 // load controllers & programs database...
1300 m_config.loadControls(&m_controls);
1301 m_config.loadPrograms(&m_programs);
1302
1303 // number of channels
1304 setChannels(nchannels);
1305
1306 // set default sample rate
1307 setSampleRate(srate);
1308
1309 // reset all voices
1310 allControllersOff();
1311 allNotesOff();
1312
1313 running(true);
1314 }
1315
1316
1317 // destructor
1318
~samplv1_impl(void)1319 samplv1_impl::~samplv1_impl (void)
1320 {
1321 #if 0
1322 // DO NOT save programs database here:
1323 // prevent multi-instance clash...
1324 m_config.savePrograms(&m_programs);
1325 #endif
1326
1327 // deallocate sample filenames
1328 setSampleFile(nullptr, 0);
1329
1330 // deallocate voice pool.
1331 for (int i = 0; i < MAX_VOICES; ++i)
1332 delete m_voices[i];
1333
1334 delete [] m_voices;
1335
1336 // deallocate local buffers
1337 alloc_sfxs(0);
1338
1339 // deallocate channels
1340 setChannels(0);
1341 }
1342
1343
setChannels(uint16_t nchannels)1344 void samplv1_impl::setChannels ( uint16_t nchannels )
1345 {
1346 m_nchannels = nchannels;
1347
1348 // deallocate flangers
1349 if (m_flanger) {
1350 delete [] m_flanger;
1351 m_flanger = nullptr;
1352 }
1353
1354 // deallocate phasers
1355 if (m_phaser) {
1356 delete [] m_phaser;
1357 m_phaser = nullptr;
1358 }
1359
1360 // deallocate delays
1361 if (m_delay) {
1362 delete [] m_delay;
1363 m_delay = nullptr;
1364 }
1365
1366 // deallocate compressors
1367 if (m_comp) {
1368 delete [] m_comp;
1369 m_comp = nullptr;
1370 }
1371 }
1372
1373
channels(void) const1374 uint16_t samplv1_impl::channels (void) const
1375 {
1376 return m_nchannels;
1377 }
1378
1379
setSampleRate(float srate)1380 void samplv1_impl::setSampleRate ( float srate )
1381 {
1382 // set internal sample rate
1383 m_srate = srate;
1384
1385 // update waves sample rate
1386 gen1_sample.setSampleRate(m_srate);
1387 lfo1_wave.setSampleRate(m_srate);
1388
1389 updateEnvTimes();
1390
1391 dcf1_formant.setSampleRate(m_srate);
1392 }
1393
1394
sampleRate(void) const1395 float samplv1_impl::sampleRate (void) const
1396 {
1397 return m_srate;
1398 }
1399
1400
setBufferSize(uint32_t nsize)1401 void samplv1_impl::setBufferSize ( uint32_t nsize )
1402 {
1403 // set nominal buffer size
1404 if (m_nsize < nsize) alloc_sfxs(nsize);
1405 }
1406
1407
bufferSize(void) const1408 uint32_t samplv1_impl::bufferSize (void) const
1409 {
1410 return m_nsize;
1411 }
1412
1413
setTempo(float bpm)1414 void samplv1_impl::setTempo ( float bpm )
1415 {
1416 // set nominal tempo (BPM)
1417 m_bpm = bpm;
1418 }
1419
1420
tempo(void) const1421 float samplv1_impl::tempo (void) const
1422 {
1423 return m_bpm;
1424 }
1425
1426
1427 // allocate local buffers
alloc_sfxs(uint32_t nsize)1428 void samplv1_impl::alloc_sfxs ( uint32_t nsize )
1429 {
1430 if (m_sfxs) {
1431 for (uint16_t k = 0; k < m_nchannels; ++k)
1432 delete [] m_sfxs[k];
1433 delete [] m_sfxs;
1434 m_sfxs = nullptr;
1435 m_nsize = 0;
1436 }
1437
1438 if (m_nsize < nsize) {
1439 m_nsize = nsize;
1440 m_sfxs = new float * [m_nchannels];
1441 for (uint16_t k = 0; k < m_nchannels; ++k)
1442 m_sfxs[k] = new float [m_nsize];
1443 }
1444 }
1445
1446
updateEnvTimes(void)1447 void samplv1_impl::updateEnvTimes (void)
1448 {
1449 // update envelope range times in frames
1450 const float srate_ms = 0.001f * m_srate;
1451
1452 float envtime_msecs = 10000.0f * m_gen1.envtime0;
1453 if (envtime_msecs < MIN_ENV_MSECS) {
1454 const uint32_t envtime_frames
1455 = (gen1_sample.offsetEnd() - gen1_sample.offsetStart()) >> 1;
1456 envtime_msecs = envtime_frames / srate_ms;
1457 }
1458 if (envtime_msecs < MIN_ENV_MSECS)
1459 envtime_msecs = MIN_ENV_MSECS * 4.0f;
1460
1461 const uint32_t min_frames1 = uint32_t(srate_ms * MIN_ENV_MSECS);
1462 const uint32_t min_frames2 = (min_frames1 << 2);
1463 const uint32_t max_frames = uint32_t(srate_ms * envtime_msecs);
1464
1465 m_dcf1.env.min_frames1 = min_frames1;
1466 m_dcf1.env.min_frames2 = min_frames2;
1467 m_dcf1.env.max_frames = max_frames;
1468
1469 m_lfo1.env.min_frames1 = min_frames1;
1470 m_lfo1.env.min_frames2 = min_frames2;
1471 m_lfo1.env.max_frames = max_frames;
1472
1473 m_dca1.env.min_frames1 = min_frames1;
1474 m_dca1.env.min_frames2 = min_frames2;
1475 m_dca1.env.max_frames = max_frames;
1476 }
1477
1478
setSampleFile(const char * pszSampleFile,uint16_t otabs)1479 void samplv1_impl::setSampleFile ( const char *pszSampleFile, uint16_t otabs )
1480 {
1481 reset();
1482
1483 if (pszSampleFile) {
1484 m_gen1.sample0 = *m_gen1.sample;
1485 gen1_sample.open(pszSampleFile, samplv1_freq(m_gen1.sample0), otabs);
1486 } else {
1487 gen1_sample.close();
1488 }
1489
1490 updateEnvTimes();
1491 }
1492
1493
sampleFile(void) const1494 const char *samplv1_impl::sampleFile (void) const
1495 {
1496 return gen1_sample.filename();
1497 }
1498
1499
octaves(void) const1500 uint16_t samplv1_impl::octaves (void) const
1501 {
1502 return gen1_sample.otabs();
1503 }
1504
1505
setParamPort(samplv1::ParamIndex index,float * pfParam)1506 void samplv1_impl::setParamPort ( samplv1::ParamIndex index, float *pfParam )
1507 {
1508 static float s_fDummy = 0.0f;
1509
1510 if (pfParam == nullptr)
1511 pfParam = &s_fDummy;
1512
1513 samplv1_port *pParamPort = paramPort(index);
1514 if (pParamPort)
1515 pParamPort->set_port(pfParam);
1516
1517 // check null connections.
1518 if (pfParam == &s_fDummy)
1519 return;
1520
1521 // reset ramps after port (re)connection.
1522 switch (index) {
1523 case samplv1::OUT1_VOLUME:
1524 case samplv1::DCA1_VOLUME:
1525 m_vol1.reset(
1526 m_out1.volume.value_ptr(),
1527 m_dca1.volume.value_ptr(),
1528 &m_ctl1.volume);
1529 break;
1530 case samplv1::OUT1_WIDTH:
1531 m_wid1.reset(
1532 m_out1.width.value_ptr());
1533 break;
1534 case samplv1::OUT1_PANNING:
1535 m_pan1.reset(
1536 m_out1.panning.value_ptr(),
1537 &m_ctl1.panning);
1538 break;
1539 default:
1540 break;
1541 }
1542 }
1543
1544
paramPort(samplv1::ParamIndex index)1545 samplv1_port *samplv1_impl::paramPort ( samplv1::ParamIndex index )
1546 {
1547 samplv1_port *pParamPort = nullptr;
1548
1549 switch (index) {
1550 case samplv1::GEN1_SAMPLE: pParamPort = &m_gen1.sample; break;
1551 case samplv1::GEN1_REVERSE: pParamPort = &m_gen1.reverse; break;
1552 case samplv1::GEN1_OFFSET: pParamPort = &m_gen1.offset; break;
1553 case samplv1::GEN1_OFFSET_1: pParamPort = &m_gen1.offset_1; break;
1554 case samplv1::GEN1_OFFSET_2: pParamPort = &m_gen1.offset_2; break;
1555 case samplv1::GEN1_LOOP: pParamPort = &m_gen1.loop; break;
1556 case samplv1::GEN1_LOOP_1: pParamPort = &m_gen1.loop_1; break;
1557 case samplv1::GEN1_LOOP_2: pParamPort = &m_gen1.loop_2; break;
1558 case samplv1::GEN1_OCTAVE: pParamPort = &m_gen1.octave; break;
1559 case samplv1::GEN1_TUNING: pParamPort = &m_gen1.tuning; break;
1560 case samplv1::GEN1_GLIDE: pParamPort = &m_gen1.glide; break;
1561 case samplv1::GEN1_ENVTIME: pParamPort = &m_gen1.envtime; break;
1562 case samplv1::DCF1_ENABLED: pParamPort = &m_dcf1.enabled; break;
1563 case samplv1::DCF1_CUTOFF: pParamPort = &m_dcf1.cutoff; break;
1564 case samplv1::DCF1_RESO: pParamPort = &m_dcf1.reso; break;
1565 case samplv1::DCF1_TYPE: pParamPort = &m_dcf1.type; break;
1566 case samplv1::DCF1_SLOPE: pParamPort = &m_dcf1.slope; break;
1567 case samplv1::DCF1_ENVELOPE: pParamPort = &m_dcf1.envelope; break;
1568 case samplv1::DCF1_ATTACK: pParamPort = &m_dcf1.env.attack; break;
1569 case samplv1::DCF1_DECAY: pParamPort = &m_dcf1.env.decay; break;
1570 case samplv1::DCF1_SUSTAIN: pParamPort = &m_dcf1.env.sustain; break;
1571 case samplv1::DCF1_RELEASE: pParamPort = &m_dcf1.env.release; break;
1572 case samplv1::LFO1_ENABLED: pParamPort = &m_lfo1.enabled; break;
1573 case samplv1::LFO1_SHAPE: pParamPort = &m_lfo1.shape; break;
1574 case samplv1::LFO1_WIDTH: pParamPort = &m_lfo1.width; break;
1575 case samplv1::LFO1_BPM: pParamPort = &m_lfo1.bpm; break;
1576 case samplv1::LFO1_RATE: pParamPort = &m_lfo1.rate; break;
1577 case samplv1::LFO1_SYNC: pParamPort = &m_lfo1.sync; break;
1578 case samplv1::LFO1_SWEEP: pParamPort = &m_lfo1.sweep; break;
1579 case samplv1::LFO1_PITCH: pParamPort = &m_lfo1.pitch; break;
1580 case samplv1::LFO1_CUTOFF: pParamPort = &m_lfo1.cutoff; break;
1581 case samplv1::LFO1_RESO: pParamPort = &m_lfo1.reso; break;
1582 case samplv1::LFO1_PANNING: pParamPort = &m_lfo1.panning; break;
1583 case samplv1::LFO1_VOLUME: pParamPort = &m_lfo1.volume; break;
1584 case samplv1::LFO1_ATTACK: pParamPort = &m_lfo1.env.attack; break;
1585 case samplv1::LFO1_DECAY: pParamPort = &m_lfo1.env.decay; break;
1586 case samplv1::LFO1_SUSTAIN: pParamPort = &m_lfo1.env.sustain; break;
1587 case samplv1::LFO1_RELEASE: pParamPort = &m_lfo1.env.release; break;
1588 case samplv1::DCA1_ENABLED: pParamPort = &m_dca1.enabled; break;
1589 case samplv1::DCA1_VOLUME: pParamPort = &m_dca1.volume; break;
1590 case samplv1::DCA1_ATTACK: pParamPort = &m_dca1.env.attack; break;
1591 case samplv1::DCA1_DECAY: pParamPort = &m_dca1.env.decay; break;
1592 case samplv1::DCA1_SUSTAIN: pParamPort = &m_dca1.env.sustain; break;
1593 case samplv1::DCA1_RELEASE: pParamPort = &m_dca1.env.release; break;
1594 case samplv1::OUT1_WIDTH: pParamPort = &m_out1.width; break;
1595 case samplv1::OUT1_PANNING: pParamPort = &m_out1.panning; break;
1596 case samplv1::OUT1_FXSEND: pParamPort = &m_out1.fxsend; break;
1597 case samplv1::OUT1_VOLUME: pParamPort = &m_out1.volume; break;
1598 case samplv1::DEF1_PITCHBEND: pParamPort = &m_def.pitchbend; break;
1599 case samplv1::DEF1_MODWHEEL: pParamPort = &m_def.modwheel; break;
1600 case samplv1::DEF1_PRESSURE: pParamPort = &m_def.pressure; break;
1601 case samplv1::DEF1_VELOCITY: pParamPort = &m_def.velocity; break;
1602 case samplv1::DEF1_CHANNEL: pParamPort = &m_def.channel; break;
1603 case samplv1::DEF1_MONO: pParamPort = &m_def.mono; break;
1604 case samplv1::CHO1_WET: pParamPort = &m_cho.wet; break;
1605 case samplv1::CHO1_DELAY: pParamPort = &m_cho.delay; break;
1606 case samplv1::CHO1_FEEDB: pParamPort = &m_cho.feedb; break;
1607 case samplv1::CHO1_RATE: pParamPort = &m_cho.rate; break;
1608 case samplv1::CHO1_MOD: pParamPort = &m_cho.mod; break;
1609 case samplv1::FLA1_WET: pParamPort = &m_fla.wet; break;
1610 case samplv1::FLA1_DELAY: pParamPort = &m_fla.delay; break;
1611 case samplv1::FLA1_FEEDB: pParamPort = &m_fla.feedb; break;
1612 case samplv1::FLA1_DAFT: pParamPort = &m_fla.daft; break;
1613 case samplv1::PHA1_WET: pParamPort = &m_pha.wet; break;
1614 case samplv1::PHA1_RATE: pParamPort = &m_pha.rate; break;
1615 case samplv1::PHA1_FEEDB: pParamPort = &m_pha.feedb; break;
1616 case samplv1::PHA1_DEPTH: pParamPort = &m_pha.depth; break;
1617 case samplv1::PHA1_DAFT: pParamPort = &m_pha.daft; break;
1618 case samplv1::DEL1_WET: pParamPort = &m_del.wet; break;
1619 case samplv1::DEL1_DELAY: pParamPort = &m_del.delay; break;
1620 case samplv1::DEL1_FEEDB: pParamPort = &m_del.feedb; break;
1621 case samplv1::DEL1_BPM: pParamPort = &m_del.bpm; break;
1622 case samplv1::REV1_WET: pParamPort = &m_rev.wet; break;
1623 case samplv1::REV1_ROOM: pParamPort = &m_rev.room; break;
1624 case samplv1::REV1_DAMP: pParamPort = &m_rev.damp; break;
1625 case samplv1::REV1_FEEDB: pParamPort = &m_rev.feedb; break;
1626 case samplv1::REV1_WIDTH: pParamPort = &m_rev.width; break;
1627 case samplv1::DYN1_COMPRESS: pParamPort = &m_dyn.compress; break;
1628 case samplv1::DYN1_LIMITER: pParamPort = &m_dyn.limiter; break;
1629 case samplv1::KEY1_LOW: pParamPort = &m_key.low; break;
1630 case samplv1::KEY1_HIGH: pParamPort = &m_key.high; break;
1631 default: break;
1632 }
1633
1634 return pParamPort;
1635 }
1636
1637
setParamValue(samplv1::ParamIndex index,float fValue)1638 void samplv1_impl::setParamValue ( samplv1::ParamIndex index, float fValue )
1639 {
1640 samplv1_port *pParamPort = paramPort(index);
1641 if (pParamPort)
1642 pParamPort->set_value(fValue);
1643 }
1644
1645
paramValue(samplv1::ParamIndex index)1646 float samplv1_impl::paramValue ( samplv1::ParamIndex index )
1647 {
1648 samplv1_port *pParamPort = paramPort(index);
1649 return (pParamPort ? pParamPort->value() : 0.0f);
1650 }
1651
1652
1653 // handle midi input
1654
process_midi(uint8_t * data,uint32_t size)1655 void samplv1_impl::process_midi ( uint8_t *data, uint32_t size )
1656 {
1657 for (uint32_t i = 0; i < size; ++i) {
1658
1659 // channel status
1660 const int channel = (data[i] & 0x0f) + 1;
1661 const int status = (data[i] & 0xf0);
1662
1663 // channel filter
1664 const int ch = int(*m_def.channel);
1665 const int on = (ch == 0 || ch == channel);
1666
1667 // all system common/real-time ignored
1668 if (status == 0xf0)
1669 continue;
1670
1671 // check data size (#1)
1672 if (++i >= size)
1673 break;
1674
1675 const int key = (data[i] & 0x7f);
1676
1677 // program change
1678 if (status == 0xc0) {
1679 if (on) m_programs.prog_change(key);
1680 continue;
1681 }
1682
1683 // channel aftertouch
1684 if (status == 0xd0) {
1685 if (on) m_ctl1.pressure = float(key) / 127.0f;
1686 continue;
1687 }
1688
1689 // check data size (#2)
1690 if (++i >= size)
1691 break;
1692
1693 // channel value
1694 const int value = (data[i] & 0x7f);
1695
1696 // channel/controller filter
1697 if (!on) {
1698 if (status == 0xb0)
1699 m_controls.process_enqueue(channel, key, value);
1700 continue;
1701 }
1702
1703 // note on
1704 if (status == 0x90 && value > 0) {
1705 if (!m_key.is_note(key))
1706 continue;
1707 samplv1_voice *pv;
1708 // mono voice modes
1709 if (*m_def.mono > 0.0f) {
1710 int n = 0;
1711 for (pv = m_play_list.next(); pv; pv = pv->next()) {
1712 if (pv->note >= 0
1713 && pv->dca1_env.stage != samplv1_env::Release) {
1714 m_dcf1.env.note_off_fast(&pv->dcf1_env);
1715 m_lfo1.env.note_off_fast(&pv->lfo1_env);
1716 m_dca1.env.note_off_fast(&pv->dca1_env);
1717 if (++n > 1) { // there shall be only one
1718 m_notes[pv->note] = nullptr;
1719 pv->note = -1;
1720 }
1721 }
1722 }
1723 }
1724 pv = m_notes[key];
1725 if (pv && pv->note >= 0/* && !m_ctl1.sustain*/) {
1726 // retrigger fast release
1727 m_dcf1.env.note_off_fast(&pv->dcf1_env);
1728 m_lfo1.env.note_off_fast(&pv->lfo1_env);
1729 m_dca1.env.note_off_fast(&pv->dca1_env);
1730 m_notes[pv->note] = nullptr;
1731 pv->note = -1;
1732 }
1733 // find free voice
1734 pv = alloc_voice();
1735 if (pv) {
1736 // waveform
1737 pv->note = key;
1738 // velocity
1739 const float vel = float(value) / 127.0f;
1740 // quadratic velocity law
1741 pv->vel = samplv1_velocity(vel * vel, *m_def.velocity);
1742 // pressure/after-touch
1743 pv->pre = 0.0f;
1744 pv->dca1_pre.reset(
1745 m_def.pressure.value_ptr(),
1746 &m_ctl1.pressure, &pv->pre);
1747 // frequencies
1748 const float gen1_tuning
1749 = *m_gen1.octave * OCTAVE_SCALE
1750 + *m_gen1.tuning * TUNING_SCALE;
1751 pv->gen1_freq = m_freqs[key] * samplv1_freq2(gen1_tuning);
1752 // generator
1753 pv->gen1.start(pv->gen1_freq);
1754 // filters
1755 const int dcf1_type = int(*m_dcf1.type);
1756 pv->dcf11.reset(samplv1_filter1::Type(dcf1_type));
1757 pv->dcf12.reset(samplv1_filter1::Type(dcf1_type));
1758 pv->dcf13.reset(samplv1_filter2::Type(dcf1_type));
1759 pv->dcf14.reset(samplv1_filter2::Type(dcf1_type));
1760 pv->dcf15.reset(samplv1_filter3::Type(dcf1_type));
1761 pv->dcf16.reset(samplv1_filter3::Type(dcf1_type));
1762 // formant filters
1763 const float dcf1_cutoff = *m_dcf1.cutoff;
1764 const float dcf1_reso = *m_dcf1.reso;
1765 pv->dcf17.reset_filters(dcf1_cutoff, dcf1_reso);
1766 pv->dcf18.reset_filters(dcf1_cutoff, dcf1_reso);
1767 // envelopes
1768 if (*m_dcf1.enabled > 0.0f)
1769 m_dcf1.env.start(&pv->dcf1_env);
1770 else
1771 m_dcf1.env.idle(&pv->dcf1_env);
1772 if (*m_lfo1.enabled > 0.0f)
1773 m_lfo1.env.start(&pv->lfo1_env);
1774 else
1775 m_lfo1.env.idle(&pv->lfo1_env);
1776 if (*m_dca1.enabled > 0.0f)
1777 m_dca1.env.start(&pv->dca1_env);
1778 else
1779 m_dca1.env.idle(&pv->dca1_env);
1780 // something about the loop
1781 pv->gen1.setLoop(gen1_sample.isLoop());
1782 // lfos
1783 const float lfo1_pshift
1784 = (m_lfo1.psync ? m_lfo1.psync->lfo1.pshift() : 0.0f);
1785 pv->lfo1_sample = pv->lfo1.start(lfo1_pshift);
1786 if (*m_lfo1.sync > 0.0f && m_lfo1.psync == nullptr)
1787 m_lfo1.psync = pv;
1788 // glides (portamentoa)
1789 const float gen1_frames
1790 = uint32_t(*m_gen1.glide * *m_gen1.glide * m_srate);
1791 pv->gen1_glide.reset(gen1_frames, pv->gen1_freq);
1792 // panning
1793 pv->out1_panning = 0.0f;
1794 pv->out1_pan.reset(&pv->out1_panning);
1795 // volume
1796 pv->out1_volume = 1.0f;
1797 pv->out1_vol.reset(&pv->out1_volume);
1798 // sustain
1799 pv->sustain = false;
1800 // allocated
1801 m_notes[key] = pv;
1802 }
1803 m_midi_in.schedule_note(key, value);
1804 }
1805 // note off
1806 else if (status == 0x80 || (status == 0x90 && value == 0)) {
1807 if (!m_key.is_note(key))
1808 continue;
1809 samplv1_voice *pv = m_notes[key];
1810 if (pv && pv->note >= 0) {
1811 if (m_ctl1.sustain)
1812 pv->sustain = true;
1813 else
1814 if (!pv->sustain) {
1815 if (pv->dca1_env.stage != samplv1_env::Release) {
1816 m_dca1.env.note_off(&pv->dca1_env);
1817 m_dcf1.env.note_off(&pv->dcf1_env);
1818 m_lfo1.env.note_off(&pv->lfo1_env);
1819 // pv->gen1.setLoop(false);
1820 }
1821 m_notes[pv->note] = nullptr;
1822 pv->note = -1;
1823 // mono legato?
1824 if (*m_def.mono > 0.0f) {
1825 do pv = pv->prev(); while (pv && pv->note < 0);
1826 if (pv && pv->note >= 0) {
1827 const bool legato = (*m_def.mono > 1.0f);
1828 m_dcf1.env.restart(&pv->dcf1_env, legato);
1829 m_lfo1.env.restart(&pv->lfo1_env, legato);
1830 m_dca1.env.restart(&pv->dca1_env, legato);
1831 pv->gen1.setLoop(*m_gen1.loop > 0.0f);
1832 if (!legato) pv->gen1.start(pv->gen1_freq);
1833 m_notes[pv->note] = pv;
1834 }
1835 }
1836 }
1837 }
1838 m_midi_in.schedule_note(key, 0);
1839 }
1840 // key pressure/poly.aftertouch
1841 else if (status == 0xa0) {
1842 if (!m_key.is_note(key))
1843 continue;
1844 samplv1_voice *pv = m_notes[key];
1845 if (pv && pv->note >= 0)
1846 pv->pre = *m_def.pressure * float(value) / 127.0f;
1847 }
1848 // control change
1849 else if (status == 0xb0) {
1850 switch (key) {
1851 case 0x00:
1852 // bank-select MSB (cc#0)
1853 m_programs.bank_select_msb(value);
1854 break;
1855 case 0x01:
1856 // modulation wheel (cc#1)
1857 m_ctl1.modwheel = *m_def.modwheel * float(value) / 127.0f;
1858 break;
1859 case 0x07:
1860 // channel volume (cc#7)
1861 m_ctl1.volume = float(value) / 127.0f;
1862 break;
1863 case 0x0a:
1864 // channel panning (cc#10)
1865 m_ctl1.panning = float(value - 64) / 64.0f;
1866 break;
1867 case 0x20:
1868 // bank-select LSB (cc#32)
1869 m_programs.bank_select_lsb(value);
1870 break;
1871 case 0x40:
1872 // sustain/damper pedal (cc#64)
1873 if (m_ctl1.sustain && value < 64)
1874 allSustainOff();
1875 m_ctl1.sustain = bool(value >= 64);
1876 break;
1877 case 0x42:
1878 // sustenuto pedal (cc#66)
1879 if (value < 64)
1880 allSustainOff();
1881 else
1882 allSustainOn();
1883 break;
1884 case 0x78:
1885 // all sound off (cc#120)
1886 allSoundOff();
1887 break;
1888 case 0x79:
1889 // all controllers off (cc#121)
1890 allControllersOff();
1891 break;
1892 case 0x7b:
1893 // all notes off (cc#123)
1894 allNotesOff();
1895 break;
1896 }
1897 // process controllers...
1898 m_controls.process_enqueue(channel, key, value);
1899 }
1900 // pitch bend
1901 else if (status == 0xe0) {
1902 const float pitchbend = float(key + (value << 7) - 0x2000) / 8192.0f;
1903 m_ctl1.pitchbend = samplv1_pow2f(*m_def.pitchbend * pitchbend);
1904 }
1905 }
1906
1907 // process pending controllers...
1908 m_controls.process_dequeue();
1909
1910 // asynchronous event notification...
1911 m_midi_in.schedule_event();
1912 }
1913
1914
1915 // all controllers off
1916
allControllersOff(void)1917 void samplv1_impl::allControllersOff (void)
1918 {
1919 m_ctl1.reset();
1920 }
1921
1922
1923 // all sound off
1924
allSoundOff(void)1925 void samplv1_impl::allSoundOff (void)
1926 {
1927 m_chorus.setSampleRate(m_srate);
1928 m_chorus.reset();
1929
1930 for (uint16_t k = 0; k < m_nchannels; ++k) {
1931 m_phaser[k].setSampleRate(m_srate);
1932 m_delay[k].setSampleRate(m_srate);
1933 m_comp[k].setSampleRate(m_srate);
1934 m_flanger[k].reset();
1935 m_phaser[k].reset();
1936 m_delay[k].reset();
1937 m_comp[k].reset();
1938 }
1939
1940 m_reverb.setSampleRate(m_srate);
1941 m_reverb.reset();
1942 }
1943
1944
1945 // all notes off
1946
allNotesOff(void)1947 void samplv1_impl::allNotesOff (void)
1948 {
1949 samplv1_voice *pv = m_play_list.next();
1950 while (pv) {
1951 if (pv->note >= 0)
1952 m_notes[pv->note] = nullptr;
1953 free_voice(pv);
1954 pv = m_play_list.next();
1955 }
1956
1957 gen1_last = 0.0f;
1958
1959 m_lfo1.psync = nullptr;
1960
1961 m_direct_note = 0;
1962 }
1963
1964
1965 // all sustained notes off
1966
allSustainOff(void)1967 void samplv1_impl::allSustainOff (void)
1968 {
1969 samplv1_voice *pv = m_play_list.next();
1970 while (pv) {
1971 if (pv->note >= 0 && pv->sustain) {
1972 pv->sustain = false;
1973 if (pv->dca1_env.stage != samplv1_env::Release) {
1974 m_dca1.env.note_off(&pv->dca1_env);
1975 m_dcf1.env.note_off(&pv->dcf1_env);
1976 m_lfo1.env.note_off(&pv->lfo1_env);
1977 pv->gen1.setLoop(false);
1978 m_notes[pv->note] = nullptr;
1979 pv->note = -1;
1980 }
1981 }
1982 pv = pv->next();
1983 }
1984 }
1985
1986
1987 // sustain all notes on (sustenuto)
1988
allSustainOn(void)1989 void samplv1_impl::allSustainOn (void)
1990 {
1991 samplv1_voice *pv = m_play_list.next();
1992 while (pv) {
1993 if (pv->note >= 0 && !pv->sustain)
1994 pv->sustain = true;
1995 pv = pv->next();
1996 }
1997 }
1998
1999
2000 // direct note-on triggered on next cycle...
directNoteOn(int note,int vel)2001 void samplv1_impl::directNoteOn ( int note, int vel )
2002 {
2003 if (vel > 0 && m_nvoices >= MAX_DIRECT_NOTES)
2004 return;
2005
2006 const uint32_t i = m_direct_note;
2007 if (i < MAX_DIRECT_NOTES) {
2008 const int ch1 = int(*m_def.channel);
2009 const int chan = (ch1 > 0 ? ch1 - 1 : 0) & 0x0f;
2010 direct_note& data = m_direct_notes[i];
2011 data.status = (vel > 0 ? 0x90 : 0x80) | chan;
2012 data.note = note;
2013 data.vel = vel;
2014 ++m_direct_note;
2015 }
2016 }
2017
2018
2019 // controllers accessor
2020
controls(void)2021 samplv1_controls *samplv1_impl::controls (void)
2022 {
2023 return &m_controls;
2024 }
2025
2026
2027 // programs accessor
2028
programs(void)2029 samplv1_programs *samplv1_impl::programs (void)
2030 {
2031 return &m_programs;
2032 }
2033
2034
2035 // Micro-tuning support
2036
setTuningEnabled(bool enabled)2037 void samplv1_impl::setTuningEnabled ( bool enabled )
2038 {
2039 m_tun.enabled = enabled;
2040 }
2041
isTuningEnabled(void) const2042 bool samplv1_impl::isTuningEnabled (void) const
2043 {
2044 return m_tun.enabled;
2045 }
2046
2047
setTuningRefPitch(float refPitch)2048 void samplv1_impl::setTuningRefPitch ( float refPitch )
2049 {
2050 m_tun.refPitch = refPitch;
2051 }
2052
tuningRefPitch(void) const2053 float samplv1_impl::tuningRefPitch (void) const
2054 {
2055 return m_tun.refPitch;
2056 }
2057
2058
setTuningRefNote(int refNote)2059 void samplv1_impl::setTuningRefNote ( int refNote )
2060 {
2061 m_tun.refNote = refNote;
2062 }
2063
tuningRefNote(void) const2064 int samplv1_impl::tuningRefNote (void) const
2065 {
2066 return m_tun.refNote;
2067 }
2068
2069
setTuningScaleFile(const char * pszScaleFile)2070 void samplv1_impl::setTuningScaleFile ( const char *pszScaleFile )
2071 {
2072 m_tun.scaleFile = QString::fromUtf8(pszScaleFile);
2073 }
2074
tuningScaleFile(void) const2075 const char *samplv1_impl::tuningScaleFile (void) const
2076 {
2077 return m_tun.scaleFile.toUtf8().constData();
2078 }
2079
2080
setTuningKeyMapFile(const char * pszKeyMapFile)2081 void samplv1_impl::setTuningKeyMapFile ( const char *pszKeyMapFile )
2082 {
2083 m_tun.keyMapFile = QString::fromUtf8(pszKeyMapFile);
2084 }
2085
tuningKeyMapFile(void) const2086 const char *samplv1_impl::tuningKeyMapFile (void) const
2087 {
2088 return m_tun.keyMapFile.toUtf8().constData();
2089 }
2090
2091
resetTuning(void)2092 void samplv1_impl::resetTuning (void)
2093 {
2094 if (m_tun.enabled) {
2095 // Instance micro-tuning, possibly from Scala keymap and scale files...
2096 samplv1_tuning tuning(
2097 m_tun.refPitch,
2098 m_tun.refNote);
2099 if (m_tun.keyMapFile.isEmpty())
2100 if (!m_tun.keyMapFile.isEmpty())
2101 tuning.loadKeyMapFile(m_tun.keyMapFile);
2102 if (!m_tun.scaleFile.isEmpty())
2103 tuning.loadScaleFile(m_tun.scaleFile);
2104 for (int note = 0; note < MAX_NOTES; ++note)
2105 m_freqs[note] = tuning.noteToPitch(note);
2106 // Done instance tuning.
2107 }
2108 else
2109 if (m_config.bTuningEnabled) {
2110 // Global/config micro-tuning, possibly from Scala keymap and scale files...
2111 samplv1_tuning tuning(
2112 m_config.fTuningRefPitch,
2113 m_config.iTuningRefNote);
2114 if (!m_config.sTuningKeyMapFile.isEmpty())
2115 tuning.loadKeyMapFile(m_config.sTuningKeyMapFile);
2116 if (!m_config.sTuningScaleFile.isEmpty())
2117 tuning.loadScaleFile(m_config.sTuningScaleFile);
2118 for (int note = 0; note < MAX_NOTES; ++note)
2119 m_freqs[note] = tuning.noteToPitch(note);
2120 // Done global/config tuning.
2121 } else {
2122 // Native/default tuning, 12-tone equal temperament western standard...
2123 for (int note = 0; note < MAX_NOTES; ++note)
2124 m_freqs[note] = samplv1_freq(note);
2125 // Done native/default tuning.
2126 }
2127 }
2128
2129
2130 // all stabilize
2131
stabilize(void)2132 void samplv1_impl::stabilize (void)
2133 {
2134 for (int i = 0; i < samplv1::NUM_PARAMS; ++i) {
2135 samplv1_port *pParamPort = paramPort(samplv1::ParamIndex(i));
2136 if (pParamPort)
2137 pParamPort->tick(samplv1_port2::NSTEP);
2138 }
2139 }
2140
2141
2142 // all reset clear
2143
reset(void)2144 void samplv1_impl::reset (void)
2145 {
2146 m_vol1.reset(
2147 m_out1.volume.value_ptr(),
2148 m_dca1.volume.value_ptr(),
2149 &m_ctl1.volume);
2150 m_pan1.reset(
2151 m_out1.panning.value_ptr(),
2152 &m_ctl1.panning);
2153 m_wid1.reset(
2154 m_out1.width.value_ptr());
2155
2156 // flangers
2157 if (m_flanger == nullptr)
2158 m_flanger = new samplv1_fx_flanger [m_nchannels];
2159
2160 // phasers
2161 if (m_phaser == nullptr)
2162 m_phaser = new samplv1_fx_phaser [m_nchannels];
2163
2164 // delays
2165 if (m_delay == nullptr)
2166 m_delay = new samplv1_fx_delay [m_nchannels];
2167
2168 // compressors
2169 if (m_comp == nullptr)
2170 m_comp = new samplv1_fx_comp [m_nchannels];
2171
2172 // reverbs
2173 m_reverb.reset();
2174
2175 // controllers reset.
2176 m_controls.reset();
2177
2178 allSoundOff();
2179 // allControllersOff();
2180 allNotesOff();
2181 }
2182
2183
2184 // MIDI input asynchronous status notification accessors
2185
midiInEnabled(bool on)2186 void samplv1_impl::midiInEnabled ( bool on )
2187 {
2188 m_midi_in.enabled(on);
2189 }
2190
2191
midiInCount(void)2192 uint32_t samplv1_impl::midiInCount (void)
2193 {
2194 return m_midi_in.count();
2195 }
2196
2197
2198 // synthesize
2199
process(float ** ins,float ** outs,uint32_t nframes)2200 void samplv1_impl::process ( float **ins, float **outs, uint32_t nframes )
2201 {
2202 if (!m_running) return;
2203
2204 float *v_outs[m_nchannels];
2205 float *v_sfxs[m_nchannels];
2206
2207 // FIXME: fx-send buffer reallocation... seriously?
2208 if (m_nsize < nframes) alloc_sfxs(nframes);
2209
2210 uint16_t k;
2211
2212 for (k = 0; k < m_nchannels; ++k) {
2213 ::memset(m_sfxs[k], 0, nframes * sizeof(float));
2214 ::memcpy(outs[k], ins[k], nframes * sizeof(float));
2215 }
2216
2217 // process direct note on/off...
2218 while (m_direct_note > 0) {
2219 const direct_note& data
2220 = m_direct_notes[--m_direct_note];
2221 process_midi((uint8_t *) &data, sizeof(data));
2222 }
2223
2224 // channel indexes
2225
2226 const uint16_t k11 = 0;
2227 const uint16_t k12 = (gen1_sample.channels() > 1 ? 1 : 0);
2228
2229 // controls
2230
2231 const bool lfo1_enabled = (*m_lfo1.enabled > 0.0f);
2232
2233 const float lfo1_freq = (lfo1_enabled
2234 ? get_bpm(*m_lfo1.bpm) / (60.01f - *m_lfo1.rate * 60.0f) : 0.0f);
2235
2236 const float modwheel1 = (lfo1_enabled
2237 ? m_ctl1.modwheel + PITCH_SCALE * *m_lfo1.pitch : 0.0f);
2238
2239 const bool dcf1_enabled = (*m_dcf1.enabled > 0.0f);
2240
2241 const float fxsend1 = *m_out1.fxsend * *m_out1.fxsend;
2242
2243 if (m_gen1.sample0 != *m_gen1.sample) {
2244 m_gen1.sample0 = *m_gen1.sample;
2245 gen1_sample.reset(samplv1_freq(m_gen1.sample0));
2246 }
2247
2248 if (m_gen1.envtime0 != *m_gen1.envtime) {
2249 m_gen1.envtime0 = *m_gen1.envtime;
2250 updateEnvTimes();
2251 }
2252
2253 if (lfo1_enabled) {
2254 lfo1_wave.reset_test(
2255 samplv1_wave::Shape(*m_lfo1.shape), *m_lfo1.width);
2256 }
2257
2258 // per voice
2259
2260 samplv1_voice *pv = m_play_list.next();
2261
2262 while (pv) {
2263
2264 samplv1_voice *pv_next = pv->next();
2265
2266 // output buffers
2267
2268 for (k = 0; k < m_nchannels; ++k) {
2269 v_outs[k] = outs[k];
2270 v_sfxs[k] = m_sfxs[k];
2271 }
2272
2273 uint32_t nblock = nframes;
2274
2275 while (nblock > 0) {
2276
2277 uint32_t ngen = nblock;
2278
2279 // process envelope stages
2280
2281 if (pv->dca1_env.running && pv->dca1_env.frames < ngen)
2282 ngen = pv->dca1_env.frames;
2283 if (pv->dcf1_env.running && pv->dcf1_env.frames < ngen)
2284 ngen = pv->dcf1_env.frames;
2285 if (pv->lfo1_env.running && pv->lfo1_env.frames < ngen)
2286 ngen = pv->lfo1_env.frames;
2287
2288 for (uint32_t j = 0; j < ngen; ++j) {
2289
2290 // velocities
2291
2292 const float vel1
2293 = (pv->vel + (1.0f - pv->vel) * pv->dca1_pre.value(j));
2294
2295 // generators
2296
2297 const float lfo1_env
2298 = (lfo1_enabled ? pv->lfo1_env.tick() : 0.0f);
2299 const float lfo1
2300 = (lfo1_enabled ? pv->lfo1_sample * lfo1_env : 0.0f);
2301
2302 pv->gen1.next(pv->gen1_freq
2303 * (m_ctl1.pitchbend + modwheel1 * lfo1)
2304 + pv->gen1_glide.tick());
2305
2306 float gen1 = pv->gen1.value(k11);
2307 float gen2 = pv->gen1.value(k12);
2308
2309 if (lfo1_enabled) {
2310 pv->lfo1_sample = pv->lfo1.sample(lfo1_freq
2311 * (1.0f + SWEEP_SCALE * *m_lfo1.sweep * lfo1_env));
2312 }
2313
2314 // filters
2315
2316 if (dcf1_enabled) {
2317 const float env1 = 0.5f
2318 * (1.0f + *m_dcf1.envelope * pv->dcf1_env.tick());
2319 const float cutoff1 = samplv1_sigmoid_1(*m_dcf1.cutoff
2320 * env1 * (1.0f + *m_lfo1.cutoff * lfo1));
2321 const float reso1 = samplv1_sigmoid_1(*m_dcf1.reso
2322 * env1 * (1.0f + *m_lfo1.reso * lfo1));
2323 switch (int(*m_dcf1.slope)) {
2324 case 3: // Formant
2325 gen1 = pv->dcf17.output(gen1, cutoff1, reso1);
2326 gen2 = pv->dcf18.output(gen2, cutoff1, reso1);
2327 break;
2328 case 2: // Biquad
2329 gen1 = pv->dcf15.output(gen1, cutoff1, reso1);
2330 gen2 = pv->dcf16.output(gen2, cutoff1, reso1);
2331 break;
2332 case 1: // 24db/octave
2333 gen1 = pv->dcf13.output(gen1, cutoff1, reso1);
2334 gen2 = pv->dcf14.output(gen2, cutoff1, reso1);
2335 break;
2336 case 0: // 12db/octave
2337 default:
2338 gen1 = pv->dcf11.output(gen1, cutoff1, reso1);
2339 gen2 = pv->dcf12.output(gen2, cutoff1, reso1);
2340 break;
2341 }
2342 }
2343
2344 // volumes
2345
2346 const float wid1 = m_wid1.value(j);
2347 const float mid1 = 0.5f * (gen1 + gen2);
2348 const float sid1 = 0.5f * (gen1 - gen2);
2349 const float vol1 = vel1 * m_vol1.value(j)
2350 * pv->dca1_env.tick()
2351 * pv->out1_vol.value(j);
2352
2353 // outputs
2354
2355 const float out1 = vol1 * (mid1 + sid1 * wid1)
2356 * pv->out1_pan.value(j, 0)
2357 * m_pan1.value(j, 0);
2358 const float out2 = vol1 * (mid1 - sid1 * wid1)
2359 * pv->out1_pan.value(j, 1)
2360 * m_pan1.value(j, 1);
2361
2362 for (k = 0; k < m_nchannels; ++k) {
2363 const float dry = (k & 1 ? out2 : out1);
2364 const float wet = fxsend1 * dry;
2365 *v_outs[k]++ += dry - wet;
2366 *v_sfxs[k]++ += wet;
2367 }
2368
2369 if (j == 0) {
2370 pv->out1_panning = lfo1 * *m_lfo1.panning;
2371 pv->out1_volume = lfo1 * *m_lfo1.volume + 1.0f;
2372 }
2373 }
2374
2375 nblock -= ngen;
2376
2377 // voice ramps countdown
2378
2379 pv->dca1_pre.process(ngen);
2380 pv->out1_pan.process(ngen);
2381 pv->out1_vol.process(ngen);
2382
2383 // envelope countdowns
2384
2385 if (pv->dca1_env.running && pv->dca1_env.frames == 0)
2386 m_dca1.env.next(&pv->dca1_env);
2387
2388 if (pv->gen1.isOver() ||
2389 pv->dca1_env.stage == samplv1_env::End) {
2390 if (pv->note < 0)
2391 free_voice(pv);
2392 nblock = 0;
2393 } else {
2394 if (pv->dcf1_env.running && pv->dcf1_env.frames == 0)
2395 m_dcf1.env.next(&pv->dcf1_env);
2396 if (pv->lfo1_env.running && pv->lfo1_env.frames == 0)
2397 m_lfo1.env.next(&pv->lfo1_env);
2398 }
2399 }
2400
2401 // next playing voice
2402
2403 pv = pv_next;
2404 }
2405
2406 // chorus
2407 if (m_nchannels > 1) {
2408 m_chorus.process(m_sfxs[0], m_sfxs[1], nframes, *m_cho.wet,
2409 *m_cho.delay, *m_cho.feedb, *m_cho.rate, *m_cho.mod);
2410 }
2411
2412 // effects
2413 for (k = 0; k < m_nchannels; ++k) {
2414 float *in = m_sfxs[k];
2415 // flanger
2416 m_flanger[k].process(in, nframes, *m_fla.wet,
2417 *m_fla.delay, *m_fla.feedb, *m_fla.daft * float(k));
2418 // phaser
2419 m_phaser[k].process(in, nframes, *m_pha.wet,
2420 *m_pha.rate, *m_pha.feedb, *m_pha.depth, *m_pha.daft * float(k));
2421 // delay
2422 m_delay[k].process(in, nframes, *m_del.wet,
2423 *m_del.delay, *m_del.feedb, get_bpm(*m_del.bpm));
2424 }
2425
2426 // reverb
2427 if (m_nchannels > 1) {
2428 m_reverb.process(m_sfxs[0], m_sfxs[1], nframes, *m_rev.wet,
2429 *m_rev.feedb, *m_rev.room, *m_rev.damp, *m_rev.width);
2430 }
2431
2432 // output mix-down
2433 for (k = 0; k < m_nchannels; ++k) {
2434 uint32_t n;
2435 float *sfx = m_sfxs[k];
2436 // compressor
2437 if (int(*m_dyn.compress) > 0)
2438 m_comp[k].process(sfx, nframes);
2439 // limiter
2440 if (int(*m_dyn.limiter) > 0) {
2441 float *p = sfx;
2442 float *q = sfx;
2443 for (n = 0; n < nframes; ++n)
2444 *q++ = samplv1_sigmoid(*p++);
2445 }
2446 // mix-down
2447 float *out = outs[k];
2448 for (n = 0; n < nframes; ++n)
2449 *out++ += *sfx++;
2450 }
2451
2452 // post-processing
2453 m_dca1.volume.tick(nframes);
2454 m_out1.width.tick(nframes);
2455 m_out1.panning.tick(nframes);
2456 m_out1.volume.tick(nframes);
2457
2458 m_wid1.process(nframes);
2459 m_pan1.process(nframes);
2460 m_vol1.process(nframes);
2461
2462 m_controls.process(nframes);
2463 }
2464
2465
sampleReverseTest(void)2466 void samplv1_impl::sampleReverseTest (void)
2467 {
2468 if (m_running)
2469 m_gen1.reverse.tick(1);
2470 }
2471
2472
sampleReverseSync(void)2473 void samplv1_impl::sampleReverseSync (void)
2474 {
2475 const bool bReverse
2476 = gen1_sample.isReverse();
2477
2478 m_gen1.reverse.set_value_sync(bReverse ? 1.0f : 0.0f);
2479 }
2480
2481
sampleOffsetTest(void)2482 void samplv1_impl::sampleOffsetTest (void)
2483 {
2484 if (m_running) {
2485 m_gen1.offset.tick(1);
2486 m_gen1.offset_1.tick(1);
2487 m_gen1.offset_2.tick(1);
2488 }
2489 }
2490
2491
sampleOffsetSync(void)2492 void samplv1_impl::sampleOffsetSync (void)
2493 {
2494 const bool bOffset
2495 = gen1_sample.isOffset();
2496
2497 m_gen1.offset.set_value_sync(bOffset ? 1.0f : 0.0f);
2498 }
2499
2500
sampleOffsetRangeSync(void)2501 void samplv1_impl::sampleOffsetRangeSync (void)
2502 {
2503 const uint32_t iSampleLength
2504 = gen1_sample.length();
2505 const uint32_t iOffsetStart
2506 = gen1_sample.offsetStart();
2507 const uint32_t iOffsetEnd
2508 = gen1_sample.offsetEnd();
2509
2510 const float offset_1 = (iSampleLength > 0
2511 ? float(iOffsetStart) / float(iSampleLength)
2512 : 0.0f);
2513 const float offset_2 = (iSampleLength > 0
2514 ? float(iOffsetEnd) / float(iSampleLength)
2515 : 1.0f);
2516
2517 m_gen1.offset_1.set_value_sync(offset_1);
2518 m_gen1.offset_2.set_value_sync(offset_2);
2519 }
2520
2521
sampleLoopTest(void)2522 void samplv1_impl::sampleLoopTest (void)
2523 {
2524 if (m_running) {
2525 m_gen1.loop.tick(1);
2526 m_gen1.loop_1.tick(1);
2527 m_gen1.loop_2.tick(1);
2528 }
2529 }
2530
2531
sampleLoopSync(void)2532 void samplv1_impl::sampleLoopSync (void)
2533 {
2534 const bool bLoop
2535 = gen1_sample.isLoop();
2536
2537 m_gen1.loop.set_value_sync(bLoop ? 1.0f : 0.0f);
2538 }
2539
2540
sampleLoopRangeSync(void)2541 void samplv1_impl::sampleLoopRangeSync (void)
2542 {
2543 const uint32_t iSampleLength
2544 = gen1_sample.length();
2545 const uint32_t iLoopStart
2546 = gen1_sample.loopStart();
2547 const uint32_t iLoopEnd
2548 = gen1_sample.loopEnd();
2549
2550 const float loop_1 = (iSampleLength > 0
2551 ? float(iLoopStart) / float(iSampleLength)
2552 : 0.0f);
2553 const float loop_2 = (iSampleLength > 0
2554 ? float(iLoopEnd) / float(iSampleLength)
2555 : 1.0f);
2556
2557 m_gen1.loop_1.set_value_sync(loop_1);
2558 m_gen1.loop_2.set_value_sync(loop_2);
2559 }
2560
2561
2562 // process running state...
running(bool on)2563 bool samplv1_impl::running ( bool on )
2564 {
2565 const bool running = m_running;
2566 m_running = on;
2567 return running;
2568 }
2569
2570
2571 //-------------------------------------------------------------------------
2572 // samplv1 - decl.
2573 //
2574
samplv1(uint16_t nchannels,float srate)2575 samplv1::samplv1 ( uint16_t nchannels, float srate )
2576 {
2577 m_pImpl = new samplv1_impl(this, nchannels, srate);
2578 }
2579
2580
~samplv1(void)2581 samplv1::~samplv1 (void)
2582 {
2583 delete m_pImpl;
2584 }
2585
2586
setChannels(uint16_t nchannels)2587 void samplv1::setChannels ( uint16_t nchannels )
2588 {
2589 m_pImpl->setChannels(nchannels);
2590 }
2591
2592
channels(void) const2593 uint16_t samplv1::channels (void) const
2594 {
2595 return m_pImpl->channels();
2596 }
2597
2598
setSampleRate(float srate)2599 void samplv1::setSampleRate ( float srate )
2600 {
2601 m_pImpl->setSampleRate(srate);
2602 }
2603
2604
sampleRate(void) const2605 float samplv1::sampleRate (void) const
2606 {
2607 return m_pImpl->sampleRate();
2608 }
2609
2610
setSampleFile(const char * pszSampleFile,uint16_t iOctaves,bool bSync)2611 void samplv1::setSampleFile ( const char *pszSampleFile, uint16_t iOctaves, bool bSync )
2612 {
2613 m_pImpl->setSampleFile(pszSampleFile, iOctaves);
2614
2615 if (bSync) updateSample();
2616 }
2617
2618
sampleFile(void) const2619 const char *samplv1::sampleFile (void) const
2620 {
2621 return m_pImpl->sampleFile();
2622 }
2623
2624
octaves(void) const2625 uint16_t samplv1::octaves (void) const
2626 {
2627 return m_pImpl->octaves();
2628 }
2629
2630
sample(void) const2631 samplv1_sample *samplv1::sample (void) const
2632 {
2633 return &(m_pImpl->gen1_sample);
2634 }
2635
2636
setReverse(bool bReverse,bool bSync)2637 void samplv1::setReverse ( bool bReverse, bool bSync )
2638 {
2639 m_pImpl->gen1_sample.setReverse(bReverse);
2640 m_pImpl->sampleReverseSync();
2641
2642 if (bSync) updateSample();
2643 }
2644
isReverse(void) const2645 bool samplv1::isReverse (void) const
2646 {
2647 return m_pImpl->gen1_sample.isReverse();
2648 }
2649
2650
setOffset(bool bOffset,bool bSync)2651 void samplv1::setOffset ( bool bOffset, bool bSync )
2652 {
2653 m_pImpl->gen1_sample.setOffset(bOffset);
2654 m_pImpl->sampleOffsetSync();
2655
2656 if (bSync) updateOffsetRange();
2657 }
2658
isOffset(void) const2659 bool samplv1::isOffset (void) const
2660 {
2661 return m_pImpl->gen1_sample.isOffset();
2662 }
2663
2664
setOffsetRange(uint32_t iOffsetStart,uint32_t iOffsetEnd,bool bSync)2665 void samplv1::setOffsetRange ( uint32_t iOffsetStart, uint32_t iOffsetEnd, bool bSync )
2666 {
2667 m_pImpl->gen1_sample.setOffsetRange(iOffsetStart, iOffsetEnd);
2668 m_pImpl->sampleOffsetRangeSync();
2669 m_pImpl->updateEnvTimes();
2670
2671 if (bSync) updateOffsetRange();
2672 }
2673
offsetStart(void) const2674 uint32_t samplv1::offsetStart (void) const
2675 {
2676 return m_pImpl->gen1_sample.offsetStart();
2677 }
2678
offsetEnd(void) const2679 uint32_t samplv1::offsetEnd (void) const
2680 {
2681 return m_pImpl->gen1_sample.offsetEnd();
2682 }
2683
2684
setLoop(bool bLoop,bool bSync)2685 void samplv1::setLoop ( bool bLoop, bool bSync )
2686 {
2687 m_pImpl->gen1_sample.setLoop(bLoop);
2688 m_pImpl->sampleLoopSync();
2689
2690 if (bSync) updateLoopRange();
2691 }
2692
isLoop(void) const2693 bool samplv1::isLoop (void) const
2694 {
2695 return m_pImpl->gen1_sample.isLoop();
2696 }
2697
2698
setLoopRange(uint32_t iLoopStart,uint32_t iLoopEnd,bool bSync)2699 void samplv1::setLoopRange ( uint32_t iLoopStart, uint32_t iLoopEnd, bool bSync )
2700 {
2701 m_pImpl->gen1_sample.setLoopRange(iLoopStart, iLoopEnd);
2702 m_pImpl->sampleLoopRangeSync();
2703
2704 if (bSync) updateLoopRange();
2705 }
2706
loopStart(void) const2707 uint32_t samplv1::loopStart (void) const
2708 {
2709 return m_pImpl->gen1_sample.loopStart();
2710 }
2711
loopEnd(void) const2712 uint32_t samplv1::loopEnd (void) const
2713 {
2714 return m_pImpl->gen1_sample.loopEnd();
2715 }
2716
2717
setLoopFade(uint32_t iLoopFade,bool bSync)2718 void samplv1::setLoopFade ( uint32_t iLoopFade, bool bSync )
2719 {
2720 m_pImpl->gen1_sample.setLoopCrossFade(iLoopFade);
2721
2722 if (bSync) updateLoopFade();
2723 }
2724
loopFade(void) const2725 uint32_t samplv1::loopFade (void) const
2726 {
2727 return uint32_t(m_pImpl->gen1_sample.loopCrossFade());
2728 }
2729
2730
setLoopZero(bool bLoopZero,bool bSync)2731 void samplv1::setLoopZero ( bool bLoopZero, bool bSync )
2732 {
2733 m_pImpl->gen1_sample.setLoopZeroCrossing(bLoopZero);
2734
2735 if (bSync) updateLoopZero();
2736 }
2737
isLoopZero(void) const2738 bool samplv1::isLoopZero (void) const
2739 {
2740 return m_pImpl->gen1_sample.isLoopZeroCrossing();
2741 }
2742
2743
setBufferSize(uint32_t nsize)2744 void samplv1::setBufferSize ( uint32_t nsize )
2745 {
2746 m_pImpl->setBufferSize(nsize);
2747 }
2748
bufferSize(void) const2749 uint32_t samplv1::bufferSize (void) const
2750 {
2751 return m_pImpl->bufferSize();
2752 }
2753
2754
setTempo(float bpm)2755 void samplv1::setTempo ( float bpm )
2756 {
2757 m_pImpl->setTempo(bpm);
2758 }
2759
tempo(void) const2760 float samplv1::tempo (void) const
2761 {
2762 return m_pImpl->tempo();
2763 }
2764
2765
setParamPort(ParamIndex index,float * pfParam)2766 void samplv1::setParamPort ( ParamIndex index, float *pfParam )
2767 {
2768 m_pImpl->setParamPort(index, pfParam);
2769 }
2770
paramPort(ParamIndex index) const2771 samplv1_port *samplv1::paramPort ( ParamIndex index ) const
2772 {
2773 return m_pImpl->paramPort(index);
2774 }
2775
2776
setParamValue(ParamIndex index,float fValue)2777 void samplv1::setParamValue ( ParamIndex index, float fValue )
2778 {
2779 m_pImpl->setParamValue(index, fValue);
2780 }
2781
paramValue(ParamIndex index) const2782 float samplv1::paramValue ( ParamIndex index ) const
2783 {
2784 return m_pImpl->paramValue(index);
2785 }
2786
2787
process_midi(uint8_t * data,uint32_t size)2788 void samplv1::process_midi ( uint8_t *data, uint32_t size )
2789 {
2790 #ifdef CONFIG_DEBUG_0
2791 fprintf(stderr, "samplv1[%p]::process_midi(%u)", this, size);
2792 for (uint32_t i = 0; i < size; ++i)
2793 fprintf(stderr, " %02x", data[i]);
2794 fprintf(stderr, "\n");
2795 #endif
2796
2797 m_pImpl->process_midi(data, size);
2798 }
2799
2800
process(float ** ins,float ** outs,uint32_t nframes)2801 void samplv1::process ( float **ins, float **outs, uint32_t nframes )
2802 {
2803 m_pImpl->process(ins, outs, nframes);
2804
2805 m_pImpl->sampleReverseTest();
2806 }
2807
2808
2809 // controllers accessor
2810
controls(void) const2811 samplv1_controls *samplv1::controls (void) const
2812 {
2813 return m_pImpl->controls();
2814 }
2815
2816
2817 // programs accessor
2818
programs(void) const2819 samplv1_programs *samplv1::programs (void) const
2820 {
2821 return m_pImpl->programs();
2822 }
2823
2824
2825 // process state
2826
running(bool on)2827 bool samplv1::running ( bool on )
2828 {
2829 return m_pImpl->running(on);
2830 }
2831
2832
2833 // all stabilize
2834
stabilize(void)2835 void samplv1::stabilize (void)
2836 {
2837 m_pImpl->stabilize();
2838 }
2839
2840
2841 // all reset clear
2842
reset(void)2843 void samplv1::reset (void)
2844 {
2845 m_pImpl->reset();
2846 }
2847
2848
sampleOffsetLoopTest(void)2849 void samplv1::sampleOffsetLoopTest (void)
2850 {
2851 m_pImpl->sampleOffsetTest();
2852 m_pImpl->sampleLoopTest();
2853 }
2854
2855
2856 // MIDI input asynchronous status notification accessors
2857
midiInEnabled(bool on)2858 void samplv1::midiInEnabled ( bool on )
2859 {
2860 m_pImpl->midiInEnabled(on);
2861 }
2862
2863
midiInCount(void)2864 uint32_t samplv1::midiInCount (void)
2865 {
2866 return m_pImpl->midiInCount();
2867 }
2868
2869
2870 // MIDI direct note on/off triggering
2871
directNoteOn(int note,int vel)2872 void samplv1::directNoteOn ( int note, int vel )
2873 {
2874 m_pImpl->directNoteOn(note, vel);
2875 }
2876
2877
2878 // Micro-tuning support
setTuningEnabled(bool enabled)2879 void samplv1::setTuningEnabled ( bool enabled )
2880 {
2881 m_pImpl->setTuningEnabled(enabled);
2882 }
2883
isTuningEnabled(void) const2884 bool samplv1::isTuningEnabled (void) const
2885 {
2886 return m_pImpl->isTuningEnabled();
2887 }
2888
2889
setTuningRefPitch(float refPitch)2890 void samplv1::setTuningRefPitch ( float refPitch )
2891 {
2892 m_pImpl->setTuningRefPitch(refPitch);
2893 }
2894
tuningRefPitch(void) const2895 float samplv1::tuningRefPitch (void) const
2896 {
2897 return m_pImpl->tuningRefPitch();
2898 }
2899
2900
setTuningRefNote(int refNote)2901 void samplv1::setTuningRefNote ( int refNote )
2902 {
2903 m_pImpl->setTuningRefNote(refNote);
2904 }
2905
tuningRefNote(void) const2906 int samplv1::tuningRefNote (void) const
2907 {
2908 return m_pImpl->tuningRefNote();
2909 }
2910
2911
setTuningScaleFile(const char * pszScaleFile)2912 void samplv1::setTuningScaleFile ( const char *pszScaleFile )
2913 {
2914 m_pImpl->setTuningScaleFile(pszScaleFile);
2915 }
2916
tuningScaleFile(void) const2917 const char *samplv1::tuningScaleFile (void) const
2918 {
2919 return m_pImpl->tuningScaleFile();
2920 }
2921
2922
setTuningKeyMapFile(const char * pszKeyMapFile)2923 void samplv1::setTuningKeyMapFile ( const char *pszKeyMapFile )
2924 {
2925 m_pImpl->setTuningKeyMapFile(pszKeyMapFile);
2926 }
2927
tuningKeyMapFile(void) const2928 const char *samplv1::tuningKeyMapFile (void) const
2929 {
2930 return m_pImpl->tuningKeyMapFile();
2931 }
2932
2933
resetTuning(void)2934 void samplv1::resetTuning (void)
2935 {
2936 m_pImpl->resetTuning();
2937 }
2938
2939
2940 // end of samplv1.cpp
2941