1 /*
2 
3     SUBnote.cpp - The "subtractive" synthesizer
4 
5     Original ZynAddSubFX author Nasca Octavian Paul
6     Copyright (C) 2002-2009 Nasca Octavian Paul
7     Copyright 2009-2011, Alan Calvert
8     Copyright 2014-2019, Will Godfrey & others
9     Copyright 2020 Kristian Amlie & others
10 
11     This file is part of yoshimi, which is free software: you can redistribute
12     it and/or modify it under the terms of the GNU Library General Public
13     License as published by the Free Software Foundation; either version 2 of
14     the License, or (at your option) any later version.
15 
16     yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
17     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18     FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
19     later) for more details.
20 
21     You should have received a copy of the GNU General Public License along with
22     yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
23     Street, Fifth Floor, Boston, MA  02110-1301, USA.
24 
25     This file is derivative of ZynAddSubFX original code
26 
27 */
28 
29 #include <cmath>
30 #include <iostream>
31 
32 #include "DSP/FFTwrapper.h"
33 #include "Params/SUBnoteParameters.h"
34 #include "Params/Controller.h"
35 #include "Synth/SUBnote.h"
36 #include "Synth/Envelope.h"
37 #include "DSP/Filter.h"
38 #include "Misc/SynthEngine.h"
39 #include "Misc/SynthHelper.h"
40 #include "Misc/NumericFuncs.h"
41 
42 using func::power;
43 using func::powFrac;
44 using func::decibel;
45 using synth::velF;
46 using synth::getDetune;
47 using synth::interpolateAmplitude;
48 using synth::aboveAmplitudeThreshold;
49 
50 using func::setRandomPan;
51 
52 
53 
SUBnote(SUBnoteParameters * parameters,Controller * ctl_,float basefreq_,float velocity_,int portamento_,int midinote_,SynthEngine * _synth)54 SUBnote::SUBnote(SUBnoteParameters *parameters, Controller *ctl_, float basefreq_,
55                  float velocity_, int portamento_, int midinote_, SynthEngine *_synth) :
56     pars(parameters),
57     velocity(velocity_ > 1.0f ? 1.0f : velocity_),
58     portamento(portamento_),
59     midinote(midinote_),
60     GlobalFilterL(NULL),
61     GlobalFilterR(NULL),
62     GlobalFilterEnvelope(NULL),
63     ctl(ctl_),
64     subNoteChange(parameters),
65     synth(_synth),
66     filterStep(0)
67 {
68     // Initialise some legato-specific vars
69     legatoFade = 1.0f; // Full volume
70     legatoFadeStep = 0.0f; // Legato disabled
71 
72     NoteStatus = NOTE_ENABLED;
73 
74     numstages = pars->Pnumstages;
75     stereo = pars->Pstereo;
76     start = pars->Pstart;
77     firsttick = 1;
78 
79     setRandomPan(synth->numRandom(), randpanL, randpanR, synth->getRuntime().panLaw, pars->PPanning, pars->PWidth);
80 
81     numharmonics = 0;
82     lfilter = NULL;
83     rfilter = NULL;
84 
85     basefreq = basefreq_;
86     computeNoteFreq();
87 
88     oldpitchwheel = 0;
89     oldbandwidth = 64;
90 
91     if (pars->Pfixedfreq == 0)
92         initparameters(notefreq);
93     else
94         initparameters(notefreq / 440.0f * basefreq);
95 
96     computeNoteParameters();
97     computecurrentparameters();
98 
99     oldamplitude = newamplitude;
100 }
101 
102 
103 // Copy constructor, currently only exists for legato
SUBnote(const SUBnote & orig)104 SUBnote::SUBnote(const SUBnote &orig) :
105     pars(orig.pars),
106     stereo(orig.stereo),
107     numstages(orig.numstages),
108     numharmonics(orig.numharmonics),
109     start(orig.start),
110     basefreq(orig.basefreq),
111     notefreq(orig.notefreq),
112     velocity(orig.velocity),
113     portamento(orig.portamento),
114     midinote(orig.midinote),
115     BendAdjust(orig.BendAdjust),
116     OffsetHz(orig.OffsetHz),
117     randpanL(orig.randpanL),
118     randpanR(orig.randpanR),
119     FreqEnvelope(NULL),
120     BandWidthEnvelope(NULL),
121     GlobalFilterL(NULL),
122     GlobalFilterR(NULL),
123     GlobalFilterEnvelope(NULL),
124     // For legato. Move this somewhere else if copying
125     // notes gets used for another purpose
126     NoteStatus(NOTE_KEEPALIVE),
127     firsttick(orig.firsttick),
128     volume(orig.volume),
129     oldamplitude(orig.oldamplitude),
130     newamplitude(orig.newamplitude),
131     lfilter(NULL),
132     rfilter(NULL),
133     tmpsmp(NULL),
134     tmprnd(NULL),
135     ctl(orig.ctl),
136     oldpitchwheel(orig.oldpitchwheel),
137     oldbandwidth(orig.oldbandwidth),
138     legatoFade(0.0f), // Silent by default
139     legatoFadeStep(0.0f), // Legato disabled
140     subNoteChange(pars),
141     synth(orig.synth),
142     filterStep(orig.filterStep)
143 {
144     memcpy(pos, orig.pos, MAX_SUB_HARMONICS * sizeof(int));
145     memcpy(overtone_rolloff, orig.overtone_rolloff,
146         numharmonics * sizeof(float));
147     memcpy(overtone_freq, orig.overtone_freq,
148         numharmonics * sizeof(float));
149 
150     AmpEnvelope = new Envelope(*orig.AmpEnvelope);
151 
152     if (orig.FreqEnvelope != NULL)
153         FreqEnvelope = new Envelope(*orig.FreqEnvelope);
154     if (orig.BandWidthEnvelope != NULL)
155         BandWidthEnvelope = new Envelope(*orig.BandWidthEnvelope);
156     if (pars->PGlobalFilterEnabled != 0)
157     {
158         GlobalFilterL = new Filter(*orig.GlobalFilterL);
159         GlobalFilterR = new Filter(*orig.GlobalFilterR);
160         GlobalFilterEnvelope = new Envelope(*orig.GlobalFilterEnvelope);
161     }
162 
163     if (orig.lfilter != NULL)
164     {
165         lfilter = new bpfilter[numstages * numharmonics];
166         memcpy(lfilter, orig.lfilter,
167             numstages * numharmonics * sizeof(bpfilter));
168     }
169     if (orig.rfilter != NULL)
170     {
171         rfilter = new bpfilter[numstages * numharmonics];
172         memcpy(rfilter, orig.rfilter,
173             numstages * numharmonics * sizeof(bpfilter));
174     }
175 }
176 
177 
legatoFadeIn(float basefreq_,float velocity_,int portamento_,int midinote_)178 void SUBnote::legatoFadeIn(float basefreq_, float velocity_, int portamento_, int midinote_)
179 {
180     velocity = velocity_ > 1.0f ? 1.0f : velocity_;
181     portamento = portamento_;
182     midinote = midinote_;
183 
184     basefreq = basefreq_;
185     computeNoteFreq();
186 
187     if (!portamento) // Do not crossfade portamento
188     {
189         legatoFade = 0.0f; // Start silent
190         legatoFadeStep = synth->fadeStepShort; // Positive steps
191 
192         // I'm not sure if these are necessary or even beneficial
193         oldpitchwheel = 0;
194         oldbandwidth = 64;
195         oldamplitude = newamplitude;
196 
197     }
198 
199     computeNoteParameters();
200 }
201 
202 
legatoFadeOut(const SUBnote & orig)203 void SUBnote::legatoFadeOut(const SUBnote &orig)
204 {
205     velocity = orig.velocity;
206     portamento = orig.portamento;
207     midinote = orig.midinote;
208 
209     firsttick = orig.firsttick;
210     volume = orig.volume;
211 
212     basefreq = orig.basefreq;
213     notefreq = orig.notefreq;
214 
215     // Not sure if this is necessary
216     oldamplitude = orig.oldamplitude;
217     newamplitude = orig.newamplitude;
218 
219     // AmpEnvelope should never be null
220     *AmpEnvelope = *orig.AmpEnvelope;
221 
222     if (orig.FreqEnvelope != NULL)
223         *FreqEnvelope = *orig.FreqEnvelope;
224     if (orig.BandWidthEnvelope != NULL)
225         *BandWidthEnvelope = *orig.BandWidthEnvelope;
226     if (pars->PGlobalFilterEnabled)
227     {
228         *GlobalFilterEnvelope = *orig.GlobalFilterEnvelope;
229 
230         // Supporting virtual copy assignment would be hairy
231         // so we have to use the copy constructor here
232         delete GlobalFilterL;
233         GlobalFilterL = new Filter(*orig.GlobalFilterL);
234         delete GlobalFilterR;
235         GlobalFilterR = new Filter(*orig.GlobalFilterR);
236     }
237 
238     // This assumes that numstages and numharmonics don't change
239     // while notes exist, or if they do change, they change for
240     // all notes equally and simultaneously. If this is ever not
241     // the case, this code needs to be changed.
242     if (orig.lfilter != NULL)
243     {
244         memcpy(lfilter, orig.lfilter,
245             numstages * numharmonics * sizeof(bpfilter));
246     }
247     if (orig.rfilter != NULL)
248     {
249         memcpy(rfilter, orig.rfilter,
250             numstages * numharmonics * sizeof(bpfilter));
251     }
252 
253     memcpy(overtone_rolloff, orig.overtone_rolloff,
254         numharmonics * sizeof(float));
255     memcpy(overtone_freq, orig.overtone_freq,
256         numharmonics * sizeof(float));
257 
258     legatoFade = 1.0f; // Start at full volume
259     legatoFadeStep = -synth->fadeStepShort; // Negative steps
260 }
261 
262 
~SUBnote()263 SUBnote::~SUBnote()
264 {
265     KillNote();
266 }
267 
268 
269 // Kill the note
KillNote(void)270 void SUBnote::KillNote(void)
271 {
272     if (NoteStatus != NOTE_DISABLED)
273     {
274         delete [] lfilter;
275         lfilter = NULL;
276         if (stereo)
277             delete [] rfilter;
278         rfilter = NULL;
279         delete AmpEnvelope;
280         if (FreqEnvelope != NULL)
281             delete FreqEnvelope;
282         if (BandWidthEnvelope != NULL)
283             delete BandWidthEnvelope;
284         NoteStatus = NOTE_DISABLED;
285     }
286 }
287 
createNewFilters()288 int SUBnote::createNewFilters()
289 {
290     bool alreadyEnabled[MAX_SUB_HARMONICS];
291     memset(alreadyEnabled, 0, sizeof(alreadyEnabled));
292     for (int p = 0; p < numharmonics; ++p)
293         alreadyEnabled[pos[p]] = true;
294 
295     // select only harmonics that desire to compute
296     int origNumHarmonics = numharmonics;
297     for (int n = 0; n < MAX_SUB_HARMONICS; ++n)
298     {
299         if (pars->Phmag[n] == 0 || alreadyEnabled[n])
300             continue;
301         if (n * notefreq > synth->halfsamplerate_f)
302             break; // remove the freqs above the Nyquist freq
303         pos[numharmonics++] = n;
304         alreadyEnabled[n] = true;
305     }
306 
307     if (numharmonics == origNumHarmonics)
308         return 0;
309 
310     bpfilter *newFilter = new bpfilter[numstages * numharmonics];
311     if (lfilter != NULL)
312     {
313         memcpy(newFilter, lfilter, numstages * origNumHarmonics * sizeof(bpfilter));
314         delete [] lfilter;
315     }
316     lfilter = newFilter;
317     if (stereo != 0)
318     {
319         newFilter = new bpfilter[numstages * numharmonics];
320         if (rfilter != NULL)
321         {
322             memcpy(newFilter, rfilter, numstages * origNumHarmonics * sizeof(bpfilter));
323             delete [] rfilter;
324         }
325         rfilter = newFilter;
326     }
327 
328     return numharmonics - origNumHarmonics;
329 }
330 
computeNoteFreq()331 void SUBnote::computeNoteFreq()
332 {
333     if (pars->Pfixedfreq == 0)
334         notefreq = basefreq;
335     else
336     {
337         notefreq = 440.0f;
338         int fixedfreqET = pars->PfixedfreqET;
339         if (fixedfreqET)
340         {   // if the frequency varies according the keyboard note
341             float tmp =
342                 (midinote - 69.0f) / 12.0f * power<2>((((fixedfreqET - 1) / 63.0f) - 1.0f));
343             if (fixedfreqET <= 64)
344                 notefreq *= power<2>(tmp);
345             else
346                 notefreq *= power<3>(tmp);
347         }
348     }
349 
350     float detune = getDetune(pars->PDetuneType, pars->PCoarseDetune, pars->PDetune);
351     notefreq *= power<2>(detune / 1200.0f); // detune
352 }
353 
computeNoteParameters()354 void SUBnote::computeNoteParameters()
355 {
356     volume = 2.0f                                         // +6dB boost (note ADDnote and PADnote apply a +12dB boost)
357            * decibel<-60>(1.0f - pars->PVolume / 96.0f)   // -60 dB .. +19.375 dB
358            * velF(velocity, pars->PAmpVelocityScaleFunction);
359 
360     int BendAdj = pars->PBendAdjust - 64;
361     if (BendAdj % 24 == 0)
362         BendAdjust = BendAdj / 24;
363     else
364         BendAdjust = BendAdj / 24.0f;
365     float offset_val = (pars->POffsetHz - 64)/64.0f;
366     OffsetHz = 15.0f*(offset_val * sqrtf(fabsf(offset_val)));
367 
368     updatefilterbank();
369 }
370 
371 // Compute the filters coefficients
computefiltercoefs(bpfilter & filter,float freq,float bw,float gain)372 void SUBnote::computefiltercoefs(bpfilter &filter, float freq, float bw, float gain)
373 {
374     if (freq > synth->halfsamplerate_f - 200.0f)
375     {
376         freq = synth->halfsamplerate_f - 200.0f;
377     }
378 
379     float omega = TWOPI * freq / synth->samplerate_f;
380     float sn = sinf(omega);
381     float cs = cosf(omega);
382     float alpha = sn * sinhf(LOG_2 / 2.0f * bw * omega / sn);
383 
384     if (alpha > 1)
385         alpha = 1;
386     if (alpha > bw)
387         alpha = bw;
388 
389     filter.b0 = alpha / (1.0f + alpha) * filter.amp * gain;
390     filter.b2 = -alpha / (1.0f + alpha) * filter.amp * gain;
391     filter.a1 = -2.0f * cs / (1.0f + alpha);
392     filter.a2 = (1.0f - alpha) / (1.0f + alpha);
393 }
394 
395 
396 // Initialise the filters
initfilters(int startIndex)397 void SUBnote::initfilters(int startIndex)
398 {
399     for (int n = startIndex; n < numharmonics; ++n)
400     {
401         float hgain = getHgain(n);
402 
403         for (int nph = 0; nph < numstages; ++nph)
404         {
405             initfilter(lfilter[nph + n * numstages], hgain);
406             if (stereo)
407                 initfilter(rfilter[nph + n * numstages], hgain);
408         }
409     }
410 }
411 
initfilter(bpfilter & filter,float mag)412 void SUBnote::initfilter(bpfilter &filter, float mag)
413 {
414     filter.xn1 = 0.0f;
415     filter.xn2 = 0.0f;
416 
417     if (start == 0)
418     {
419         filter.yn1 = 0.0f;
420         filter.yn2 = 0.0f;
421     }
422     else
423     {
424         float a = 0.1f * mag; // empirically
425         float p = synth->numRandom() * TWOPI;
426         if (start == 1)
427             a *= synth->numRandom();
428         filter.yn1 = a * cosf(p);
429         filter.yn2 = a * cosf(p + filter.freq * TWOPI / synth->samplerate_f);
430 
431         // correct the error of computation the start amplitude
432         // at very high frequencies
433         if (filter.freq > synth->samplerate_f * 0.96f)
434         {
435             filter.yn1 = 0.0f;
436             filter.yn2 = 0.0f;
437         }
438     }
439 }
440 
441 
442 // Do the filtering
SubFilterA(const float coeff[4],float & src,float work[4])443 inline void SubFilterA(const float coeff[4], float &src, float work[4])
444 {
445     work[3] = src*coeff[0]+work[1]*coeff[1]+work[2]*coeff[2]+work[3]*coeff[3];
446     work[1] = src;
447     src     = work[3];
448 }
449 
450 
SubFilterB(const float coeff[4],float & src,float work[4])451 inline void SubFilterB(const float coeff[4], float &src, float work[4])
452 {
453     work[2] = src*coeff[0]+work[0]*coeff[1]+work[3]*coeff[2]+work[2]*coeff[3];
454     work[0] = src;
455     src     = work[2];
456 }
457 
458 
459 // ported from zynaddsubfx V 2.4.4
460 //This dance is designed to minimize unneeded memory operations which can result
461 //in quite a bit of wasted time
filter(bpfilter & filter,float * smps)462 void SUBnote::filter(bpfilter &filter, float *smps)
463 {
464     if (synth->getIsLV2Plugin()){
465         filterVarRun(filter, smps);
466         return;
467     }
468 
469     int remainder = synth->sent_buffersize % 8;
470     int blocksize = synth->sent_buffersize - remainder;
471     float coeff[4] = {filter.b0, filter.b2,  -filter.a1, -filter.a2};
472     float work[4]  = {filter.xn1, filter.xn2, filter.yn1, filter.yn2};
473 
474     for (int i = 0; i < blocksize; i += 8)
475     {
476         SubFilterA(coeff, smps[i + 0], work);
477         SubFilterB(coeff, smps[i + 1], work);
478         SubFilterA(coeff, smps[i + 2], work);
479         SubFilterB(coeff, smps[i + 3], work);
480         SubFilterA(coeff, smps[i + 4], work);
481         SubFilterB(coeff, smps[i + 5], work);
482         SubFilterA(coeff, smps[i + 6], work);
483         SubFilterB(coeff, smps[i + 7], work);
484     }
485     if (remainder > 0)
486     {
487         for (int i = blocksize; i < blocksize + remainder ; i += 2)
488         {
489             SubFilterA(coeff, smps[i + 0], work);
490             SubFilterB(coeff, smps[i + 1], work);
491         }
492     }
493     filter.xn1 = work[0];
494     filter.xn2 = work[1];
495     filter.yn1 = work[2];
496     filter.yn2 = work[3];
497 }
498 
499 
500 //Andrew Deryabin: support for variable-length runs
501 //currently only for lv2 plugin
filterVarRun(SUBnote::bpfilter & filter,float * smps)502 void SUBnote::filterVarRun(SUBnote::bpfilter &filter, float *smps)
503 {
504     float tmpout;
505     int runLength = synth->sent_buffersize;
506     int i = 0;
507     if (runLength >= 8){
508         float coeff[4] = {filter.b0, filter.b2,  -filter.a1, -filter.a2};
509         float work[4]  = {filter.xn1, filter.xn2, filter.yn1, filter.yn2};
510         while (runLength >= 8){
511             SubFilterA(coeff, smps[i + 0], work);
512             SubFilterB(coeff, smps[i + 1], work);
513             SubFilterA(coeff, smps[i + 2], work);
514             SubFilterB(coeff, smps[i + 3], work);
515             SubFilterA(coeff, smps[i + 4], work);
516             SubFilterB(coeff, smps[i + 5], work);
517             SubFilterA(coeff, smps[i + 6], work);
518             SubFilterB(coeff, smps[i + 7], work);
519             i += 8;
520             runLength -= 8;
521         }
522         filter.xn1 = work[0];
523         filter.xn2 = work[1];
524         filter.yn1 = work[2];
525         filter.yn2 = work[3];
526     }
527 
528     for (; i < synth->sent_buffersize; ++i){
529         tmpout=smps[i] * filter.b0 + filter.b2 * filter.xn2
530                -filter.a1 * filter.yn1 - filter.a2 * filter.yn2;
531         filter.xn2=filter.xn1;
532         filter.xn1=smps[i];
533         filter.yn2=filter.yn1;
534         filter.yn1=tmpout;
535         smps[i]=tmpout;
536     }
537 
538 }
539 
540 
541 // Init Parameters
initparameters(float freq)542 void SUBnote::initparameters(float freq)
543 {
544     AmpEnvelope = new Envelope(pars->AmpEnvelope, freq, synth);
545     if (pars->PFreqEnvelopeEnabled != 0)
546         FreqEnvelope = new Envelope(pars->FreqEnvelope, freq, synth);
547     else
548         FreqEnvelope = NULL;
549     if (pars->PBandWidthEnvelopeEnabled != 0)
550         BandWidthEnvelope = new Envelope(pars->BandWidthEnvelope, freq, synth);
551     else
552         BandWidthEnvelope = NULL;
553     if (pars->PGlobalFilterEnabled != 0)
554     {
555         GlobalFilterL = new Filter(pars->GlobalFilter, synth);
556         if (stereo != 0)
557             GlobalFilterR = new Filter(pars->GlobalFilter, synth);
558         GlobalFilterEnvelope = new Envelope(pars->GlobalFilterEnvelope, freq, synth);
559     }
560 }
561 //end of port
562 
563 
564 // Compute how much to reduce amplitude near nyquist or subaudible frequencies.
computerolloff(float freq)565 float SUBnote::computerolloff(float freq)
566 {
567     const float lower_limit = 10.0f;
568     const float lower_width = 10.0f;
569     const float upper_width = 200.0f;
570     float upper_limit = synth->samplerate / 2.0f;
571 
572     if (freq > lower_limit + lower_width &&
573             freq < upper_limit - upper_width)
574         return 1.0f;
575     if (freq <= lower_limit || freq >= upper_limit)
576         return 0.0f;
577     if (freq <= lower_limit + lower_width)
578         return (1.0f - cosf(PI * (freq - lower_limit) / lower_width)) / 2.0f;
579     return (1.0f - cosf(PI * (freq - upper_limit) / upper_width)) / 2.0f;
580 }
581 
computeallfiltercoefs()582 void SUBnote::computeallfiltercoefs()
583 {
584     float envfreq = 1.0f;
585     float envbw = 1.0f;
586     float gain = 1.0f;
587 
588     if (FreqEnvelope != NULL)
589     {
590         envfreq = FreqEnvelope->envout() / 1200;
591         envfreq = power<2>(envfreq);
592     }
593 
594     envfreq *= powf(ctl->pitchwheel.relfreq, BendAdjust); // pitch wheel
595 
596     if (portamento != 0)
597     {   // portamento is used
598         envfreq *= ctl->portamento.freqrap;
599         if (ctl->portamento.used == 0)
600         {   // the portamento has finished
601             portamento = 0; // this note is no longer "portamented"
602         }
603     }
604 
605     if (BandWidthEnvelope != NULL)
606     {
607         envbw = BandWidthEnvelope->envout();
608         envbw = power<2>(envbw);
609     }
610     envbw *= ctl->bandwidth.relbw; // bandwidth controller
611 
612     float tmpgain = 1.0f / sqrtf(envbw * envfreq);
613 
614     for (int n = 0; n < numharmonics; ++n)
615     {
616         for (int nph = 0; nph < numstages; ++nph)
617         {
618             if (nph == 0)
619                 gain = tmpgain;
620             else
621                 gain = 1.0f;
622             computefiltercoefs(lfilter[nph + n * numstages],
623                                lfilter[nph + n *numstages].freq * envfreq,
624                                lfilter[nph + n * numstages].bw * envbw, gain);
625         }
626     }
627     if (stereo)
628         for (int n = 0; n < numharmonics; ++n)
629         {
630             for (int nph = 0; nph < numstages; ++nph)
631             {
632                 if (nph == 0)
633                     gain = tmpgain;
634                 else
635                     gain = 1.0f;
636                 computefiltercoefs(rfilter[nph + n * numstages],
637                                    rfilter[nph + n * numstages].freq * envfreq,
638                                    rfilter[nph + n * numstages].bw * envbw, gain);
639             }
640         }
641     oldbandwidth = ctl->bandwidth.data;
642     oldpitchwheel = ctl->pitchwheel.data;
643 }
644 
645 // Compute Parameters of SUBnote for each tick
computecurrentparameters(void)646 void SUBnote::computecurrentparameters(void)
647 {
648     if (FreqEnvelope != NULL
649         || BandWidthEnvelope != NULL
650         || oldpitchwheel != ctl->pitchwheel.data
651         || oldbandwidth != ctl->bandwidth.data
652         || portamento != 0)
653         computeallfiltercoefs();
654 
655     // Envelope
656     newamplitude = volume * AmpEnvelope->envout_dB();
657 
658     // Filter
659     if (GlobalFilterL != NULL)
660     {
661         float filterCenterPitch =
662             pars->GlobalFilter->getfreq()
663             + // center freq
664             (pars->PGlobalFilterVelocityScale / 127.0f * 6.0f)
665             * // velocity sensing
666             (velF(velocity, pars->PGlobalFilterVelocityScaleFunction) - 1);
667         float filtercenterq = pars->GlobalFilter->getq();
668         float filterFreqTracking = pars->GlobalFilter->getfreqtracking(basefreq);
669         float globalfilterpitch = filterCenterPitch + GlobalFilterEnvelope->envout();
670         float filterfreq = globalfilterpitch + ctl->filtercutoff.relfreq + filterFreqTracking;
671         filterfreq = GlobalFilterL->getrealfreq(filterfreq);
672 
673         GlobalFilterL->setfreq_and_q(filterfreq, filtercenterq * ctl->filterq.relq);
674         if (GlobalFilterR != NULL)
675             GlobalFilterR->setfreq_and_q(filterfreq, filtercenterq * ctl->filterq.relq);
676     }
677 }
678 
679 
680 // Note Output
noteout(float * outl,float * outr)681 int SUBnote::noteout(float *outl, float *outr)
682 {
683     tmpsmp = synth->getRuntime().genTmp1;
684     tmprnd = synth->getRuntime().genTmp2;
685     memset(outl, 0, synth->sent_bufferbytes);
686     memset(outr, 0, synth->sent_bufferbytes);
687     if (NoteStatus == NOTE_DISABLED)
688         return 0;
689 
690     if (subNoteChange.checkUpdated())
691     {
692         computeNoteFreq();
693         computeNoteParameters();
694     }
695 
696     // left channel
697     for (int i = 0; i < synth->sent_buffersize; ++i)
698         tmprnd[i] = synth->numRandom() * 2.0f - 1.0f;
699     for (int n = 0; n < numharmonics; ++n)
700     {
701         float rolloff = overtone_rolloff[n];
702         memcpy(tmpsmp, tmprnd, synth->sent_bufferbytes);
703         for (int nph = 0; nph < numstages; ++nph)
704             filter(lfilter[nph + n * numstages], tmpsmp);
705         for (int i = 0; i < synth->sent_buffersize; ++i)
706             outl[i] += tmpsmp[i] * rolloff;
707     }
708 
709     if (GlobalFilterL != NULL)
710         GlobalFilterL->filterout(outl);
711 
712     // right channel
713     if (stereo)
714     {
715         for (int i = 0; i < synth->sent_buffersize; ++i)
716             tmprnd[i] = synth->numRandom() * 2.0f - 1.0f;
717         for (int n = 0; n < numharmonics; ++n)
718         {
719             float rolloff = overtone_rolloff[n];
720             memcpy(tmpsmp, tmprnd, synth->sent_bufferbytes);
721             for (int nph = 0; nph < numstages; ++nph)
722                 filter(rfilter[nph + n * numstages], tmpsmp);
723             for (int i = 0; i < synth->sent_buffersize; ++i)
724                 outr[i] += tmpsmp[i] * rolloff;
725         }
726         if (GlobalFilterR != NULL)
727             GlobalFilterR->filterout(outr);
728     }
729     else
730         memcpy(outr, outl, synth->sent_bufferbytes);
731 
732     if (firsttick)
733     {
734         int n = 10;
735         if (n > synth->sent_buffersize)
736             n = synth->sent_buffersize;
737         for (int i = 0; i < n; ++i)
738         {
739             float ampfadein = 0.5f - 0.5f * cosf((float)i / (float)n * PI);
740             outl[i] *= ampfadein;
741             outr[i] *= ampfadein;
742         }
743         firsttick = 0;
744     }
745 
746 
747     float pangainL = pars->pangainL; // assume non random pan
748     float pangainR = pars->pangainR;
749     if (pars->PRandom)
750     {
751         pangainL = randpanL;
752         pangainR = randpanR;
753     }
754 
755     if (aboveAmplitudeThreshold(oldamplitude, newamplitude))
756     {
757         // Amplitude interpolation
758         for (int i = 0; i < synth->sent_buffersize; ++i)
759         {
760             float tmpvol = interpolateAmplitude(oldamplitude, newamplitude, i,
761                                                 synth->sent_buffersize);
762             outl[i] *= tmpvol * pangainL;
763             outr[i] *= tmpvol * pangainR;
764         }
765     }
766     else
767     {
768         for (int i = 0; i < synth->sent_buffersize; ++i)
769         {
770             outl[i] *= newamplitude * pangainL;
771             outr[i] *= newamplitude * pangainR;
772         }
773     }
774     oldamplitude = newamplitude;
775     computecurrentparameters();
776 
777     // Apply legato fading if any
778     if (legatoFadeStep != 0.0f)
779     {
780         for (int i = 0; i < synth->sent_buffersize; ++i)
781         {
782             legatoFade += legatoFadeStep;
783             if (legatoFade <= 0.0f)
784             {
785                 legatoFade = 0.0f;
786                 legatoFadeStep = 0.0f;
787                 memset(outl + i, 0, (synth->sent_buffersize - i) * sizeof(float));
788                 memset(outr + i, 0, (synth->sent_buffersize - i) * sizeof(float));
789                 break;
790             }
791             else if (legatoFade >= 1.0f)
792             {
793                 legatoFade = 1.0f;
794                 legatoFadeStep = 0.0f;
795                 break;
796             }
797             outl[i] *= legatoFade;
798             outr[i] *= legatoFade;
799         }
800     }
801 
802     // Check if the note needs to be computed more
803     if (AmpEnvelope->finished() != 0)
804     {
805         for (int i = 0; i < synth->sent_buffersize; ++i)
806         {   // fade-out
807             float tmp = 1.0f - (float)i / synth->sent_buffersize_f;
808             outl[i] *= tmp;
809             outr[i] *= tmp;
810         }
811         KillNote();
812     }
813     return 1;
814 }
815 
816 
817 // Release Key (Note Off)
releasekey(void)818 void SUBnote::releasekey(void)
819 {
820     AmpEnvelope->releasekey();
821     if (FreqEnvelope != NULL)
822         FreqEnvelope->releasekey();
823     if (BandWidthEnvelope != NULL)
824         BandWidthEnvelope->releasekey();
825     if (GlobalFilterEnvelope != NULL)
826         GlobalFilterEnvelope->releasekey();
827     if (NoteStatus == NOTE_KEEPALIVE)
828         NoteStatus = NOTE_ENABLED;
829 }
830 
getHgain(int harmonic)831 float SUBnote::getHgain(int harmonic)
832 {
833     if (pars->Phmag[pos[harmonic]] == 0)
834         return 0.0f;
835 
836     float hmagnew = 1.0f - pars->Phmag[pos[harmonic]] / 127.0f;
837     float hgain;
838 
839     switch (pars->Phmagtype)
840     {
841         case 1:
842             hgain = powFrac<100>(hmagnew);
843             break;
844 
845         case 2:
846             hgain = powFrac<1000>(hmagnew);
847             break;
848 
849         case 3:
850             hgain = powFrac<10000>(hmagnew);
851             break;
852 
853         case 4:
854             hgain = powFrac<100000>(hmagnew);
855             break;
856 
857         default:
858             hgain = 1.0f - hmagnew;
859             break;
860     }
861 
862     return hgain;
863 }
864 
updatefilterbank(void)865 void SUBnote::updatefilterbank(void)
866 {
867     int createdFilters = createNewFilters();
868 
869     // moved from noteon
870     // how much the amplitude is normalised (because the harmonics)
871     float reduceamp = 0.0;
872 
873     for (int n = 0; n < numharmonics; ++n)
874     {
875         float freq =  notefreq * pars->POvertoneFreqMult[pos[n]];
876         overtone_freq[n] = freq;
877         overtone_rolloff[n] = computerolloff(freq);
878 
879         // the bandwidth is not absolute(Hz); it is relative to frequency
880         float bw = power<10>((pars->Pbandwidth - 127.0f) / 127.0f * 4.0f) * numstages;
881 
882         // Bandwidth Scale
883         bw *= powf(1000.0f / freq, (pars->Pbwscale - 64.0f) / 64.0f * 3.0f);
884 
885         // Relative BandWidth
886         bw *= power<100>((pars->Phrelbw[pos[n]] - 64.0f) / 64.0f);
887 
888         if (bw > 25.0f)
889             bw = 25.0f;
890 
891         // try to keep same amplitude on all freqs and bw. (empirically)
892         float gain = sqrtf(1500.0f / (bw * freq));
893 
894         float hgain = getHgain(n);
895 
896         gain *= hgain;
897         reduceamp += hgain;
898 
899         for (int nph = 0; nph < numstages; ++nph)
900         {
901             float amp = 1.0f;
902             if (nph == 0)
903                 amp = gain;
904             bpfilter *filter = &lfilter[nph + n * numstages];
905             filter->amp = amp;
906             filter->freq = freq + OffsetHz;
907             filter->bw = bw;
908             if (stereo)
909             {
910                 filter = &rfilter[nph + n * numstages];
911                 filter->amp = amp;
912                 filter->freq = freq + OffsetHz;
913                 filter->bw = bw;
914             }
915         }
916     }
917 
918     initfilters(numharmonics - createdFilters);
919     computeallfiltercoefs();
920 
921     if (reduceamp < 0.001f)
922         reduceamp = 1.0f;
923     volume /= reduceamp;
924 }
925