1 /*
2     ADnote.cpp - The "additive" synthesizer
3 
4     Original ZynAddSubFX author Nasca Octavian Paul
5     Copyright (C) 2002-2009 Nasca Octavian Paul
6     Copyright 2009-2011, Alan Calvert
7     Copyright 2014-2019, Will Godfrey & others
8     Copyright 2020-2021 Kristian Amlie & Will Godfrey
9 
10     This file is part of yoshimi, which is free software: you can redistribute
11     it and/or modify it under the terms of the GNU Library General Public
12     License as published by the Free Software Foundation; either version 2 of
13     the License, or (at your option) any later version.
14 
15     yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
16     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17     FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
18     later) for more details.
19 
20     You should have received a copy of the GNU General Public License along with
21     yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
22     Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 
24     This file is derivative of original ZynAddSubFX code.
25 
26 */
27 
28 #include <cmath>
29 #include <cassert>
30 #include <iostream>
31 
32 #include "DSP/FFTwrapper.h"
33 #include "Synth/Envelope.h"
34 #include "Synth/ADnote.h"
35 #include "Synth/LFO.h"
36 #include "DSP/Filter.h"
37 #include "Params/ADnoteParameters.h"
38 #include "Params/Controller.h"
39 #include "Misc/SynthEngine.h"
40 #include "Misc/SynthHelper.h"
41 #include "Misc/NumericFuncs.h"
42 
43 #include "globals.h"
44 
45 using func::power;
46 using func::decibel;
47 using synth::velF;
48 using synth::getDetune;
49 using synth::interpolateAmplitude;
50 using synth::aboveAmplitudeThreshold;
51 using func::setRandomPan;
52 
53 using std::isgreater;
54 
55 
ADnote(ADnoteParameters * adpars_,Controller * ctl_,float freq_,float velocity_,int portamento_,int midinote_,SynthEngine * _synth)56 ADnote::ADnote(ADnoteParameters *adpars_, Controller *ctl_, float freq_,
57                float velocity_, int portamento_, int midinote_, SynthEngine *_synth) :
58     adpars(adpars_),
59     stereo(adpars->GlobalPar.PStereo),
60     midinote(midinote_),
61     velocity(velocity_),
62     basefreq(freq_),
63     NoteStatus(NOTE_ENABLED),
64     ctl(ctl_),
65     time(0.0f),
66     Tspot(0),
67     forFM(false),
68     portamento(portamento_),
69     subVoiceNumber(-1),
70     topVoice(this),
71     parentFMmod(NULL),
72     paramsUpdate(adpars),
73     synth(_synth)
74 {
75     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
76         NoteVoicePar[nvoice].phase_offset = 0;
77 
78     construct();
79 }
80 
ADnote(ADnote * topVoice_,float freq_,int phase_offset_,int subVoiceNumber_,float * parentFMmod_,bool forFM_)81 ADnote::ADnote(ADnote *topVoice_, float freq_, int phase_offset_, int subVoiceNumber_,
82                float *parentFMmod_, bool forFM_) :
83     adpars(topVoice_->adpars),
84     stereo(adpars->GlobalPar.PStereo),
85     midinote(topVoice_->midinote),
86     velocity(topVoice_->velocity),
87     basefreq(freq_),
88     NoteStatus(NOTE_ENABLED),
89     ctl(topVoice_->ctl),
90     time(0.0f),
91     forFM(forFM_),
92     portamento(topVoice_->portamento),
93     subVoiceNumber(subVoiceNumber_),
94     topVoice(topVoice_),
95     parentFMmod(parentFMmod_),
96     paramsUpdate(adpars),
97     synth(topVoice_->synth)
98 {
99     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
100         // Start phase: Should be negative so that the zero phase in the first
101         // cycle will result in a positive phase change.
102         NoteVoicePar[nvoice].phase_offset = synth->oscilsize - phase_offset_;
103 
104     construct();
105 }
106 
107 // Copy constructor, currently only exists for legato
ADnote(const ADnote & orig,ADnote * topVoice_,float * parentFMmod_)108 ADnote::ADnote(const ADnote &orig, ADnote *topVoice_, float *parentFMmod_) :
109     adpars(orig.adpars), // Probably okay for legato?
110     stereo(orig.stereo),
111     midinote(orig.midinote),
112     velocity(orig.velocity),
113     basefreq(orig.basefreq),
114     // For legato. Move this somewhere else if copying
115     // notes gets used for another purpose
116     NoteStatus(NOTE_KEEPALIVE),
117     ctl(orig.ctl),
118     NoteGlobalPar(orig.NoteGlobalPar),
119     time(orig.time), // This is incremented, but never actually used for some reason
120     Tspot(orig.Tspot),
121     paramRNG(orig.paramRNG),
122     paramSeed(orig.paramSeed),
123     detuneFromParent(orig.detuneFromParent),
124     unisonDetuneFactorFromParent(orig.unisonDetuneFactorFromParent),
125     forFM(orig.forFM),
126     max_unison(orig.max_unison),
127     globaloldamplitude(orig.globaloldamplitude),
128     globalnewamplitude(orig.globalnewamplitude),
129     portamento(orig.portamento),
130     bandwidthDetuneMultiplier(orig.bandwidthDetuneMultiplier),
131     legatoFade(0.0f), // Silent by default
132     legatoFadeStep(0.0f), // Legato disabled
133     pangainL(orig.pangainL),
134     pangainR(orig.pangainR),
135     subVoiceNumber(orig.subVoiceNumber),
136     topVoice((topVoice_ != NULL) ? topVoice_ : this),
137     parentFMmod(parentFMmod_),
138     paramsUpdate(adpars),
139     synth(orig.synth)
140 {
141     auto &oldgpar = orig.NoteGlobalPar;
142     NoteGlobalPar.FreqEnvelope = new Envelope(*oldgpar.FreqEnvelope);
143     NoteGlobalPar.FreqLfo = new LFO(*oldgpar.FreqLfo);
144     NoteGlobalPar.AmpEnvelope = new Envelope(*oldgpar.AmpEnvelope);
145     NoteGlobalPar.AmpLfo = new LFO(*oldgpar.AmpLfo);
146     NoteGlobalPar.FilterEnvelope = new Envelope(*oldgpar.FilterEnvelope);
147     NoteGlobalPar.FilterLfo = new LFO(*oldgpar.FilterLfo);
148 
149     NoteGlobalPar.GlobalFilterL = new Filter(*oldgpar.GlobalFilterL);
150     if (stereo)
151         NoteGlobalPar.GlobalFilterR = new Filter(*oldgpar.GlobalFilterR);
152 
153     // These are all arrays, so sizeof is correct
154     memcpy(pinking, orig.pinking, sizeof(pinking));
155     memcpy(unison_size, orig.unison_size, sizeof(unison_size));
156     memcpy(unison_stereo_spread, orig.unison_stereo_spread,
157         sizeof(unison_stereo_spread));
158     memcpy(freqbasedmod, orig.freqbasedmod, sizeof(freqbasedmod));
159     memcpy(firsttick, orig.firsttick, sizeof(firsttick));
160 
161     tmpwave_unison = new float*[max_unison];
162     tmpmod_unison = new float*[max_unison];
163 
164     for (int i = 0; i < max_unison; ++i)
165     {
166         tmpwave_unison[i] = (float*)fftwf_malloc(synth->bufferbytes);
167         tmpmod_unison[i] = (float*)fftwf_malloc(synth->bufferbytes);
168     }
169 
170     for (int i = 0; i < NUM_VOICES; ++i)
171     {
172         auto &oldvpar = orig.NoteVoicePar[i];
173         auto &vpar = NoteVoicePar[i];
174 
175         vpar.OscilSmp = NULL;
176         vpar.FMSmp = NULL;
177         vpar.FMEnabled = oldvpar.FMEnabled;
178 
179         if (oldvpar.VoiceOut != NULL) {
180             vpar.VoiceOut = (float*)fftwf_malloc(synth->bufferbytes);
181             // Not sure the memcpy is necessary
182             memcpy(vpar.VoiceOut, oldvpar.VoiceOut, synth->bufferbytes);
183         } else
184             vpar.VoiceOut = NULL;
185 
186         // The above vars are checked in killNote() even when the voice is
187         // disabled, so short-circuit only after they are set
188         vpar.Enabled = oldvpar.Enabled;
189         if (!vpar.Enabled)
190             continue;
191 
192         // First, copy over everything that isn't behind a pointer
193         vpar.Voice = oldvpar.Voice;
194         vpar.noisetype = oldvpar.noisetype;
195         vpar.filterbypass = oldvpar.filterbypass;
196         vpar.DelayTicks = oldvpar.DelayTicks;
197         vpar.phase_offset = oldvpar.phase_offset;
198 
199         vpar.fixedfreq = oldvpar.fixedfreq;
200         vpar.fixedfreqET = oldvpar.fixedfreqET;
201 
202         vpar.Detune = oldvpar.Detune;
203         vpar.FineDetune = oldvpar.FineDetune;
204         vpar.BendAdjust = oldvpar.BendAdjust;
205         vpar.OffsetHz = oldvpar.OffsetHz;
206 
207         vpar.Volume = oldvpar.Volume;
208         vpar.Panning = oldvpar.Panning;
209         vpar.randpanL = oldvpar.randpanL;
210         vpar.randpanR = oldvpar.randpanR;
211 
212         vpar.Punch = oldvpar.Punch;
213 
214         vpar.FMFreqFixed = oldvpar.FMFreqFixed;
215         vpar.FMVoice = oldvpar.FMVoice;
216         vpar.FMphase_offset = oldvpar.FMphase_offset;
217         vpar.FMVolume = oldvpar.FMVolume;
218         vpar.FMDetuneFromBaseOsc = oldvpar.FMDetuneFromBaseOsc;
219         vpar.FMDetune = oldvpar.FMDetune;
220 
221         // Now handle allocations
222         if (subVoiceNumber == -1)
223         {
224             size_t size = synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES;
225 
226             if (oldvpar.OscilSmp != NULL)
227             {
228                 vpar.OscilSmp = new float[size];
229                 memcpy(vpar.OscilSmp, oldvpar.OscilSmp, size * sizeof(float));
230             }
231 
232             if (oldvpar.FMSmp != NULL)
233             {
234                 vpar.FMSmp = (float*)fftwf_malloc(size * sizeof(float));
235                 memcpy(vpar.FMSmp, oldvpar.FMSmp, size * sizeof(float));
236             }
237         } else {
238             vpar.OscilSmp = topVoice->NoteVoicePar[i].OscilSmp;
239             vpar.FMSmp = topVoice->NoteVoicePar[i].FMSmp;
240         }
241 
242         vpar.FreqEnvelope = oldvpar.FreqEnvelope != NULL ?
243             new Envelope(*oldvpar.FreqEnvelope) :
244             NULL;
245         vpar.FreqLfo = oldvpar.FreqLfo != NULL ?
246             new LFO(*oldvpar.FreqLfo) :
247             NULL;
248 
249         vpar.AmpEnvelope = oldvpar.AmpEnvelope != NULL ?
250             new Envelope(*oldvpar.AmpEnvelope) :
251             NULL;
252         vpar.AmpLfo = oldvpar.AmpLfo != NULL ?
253             new LFO(*oldvpar.AmpLfo) :
254             NULL;
255 
256         if (adpars->VoicePar[i].PFilterEnabled)
257         {
258             vpar.VoiceFilterL = new Filter(*oldvpar.VoiceFilterL);
259             vpar.VoiceFilterR = new Filter(*oldvpar.VoiceFilterR);
260         }
261         else
262         {
263             vpar.VoiceFilterL = NULL;
264             vpar.VoiceFilterR = NULL;
265         }
266 
267         vpar.FilterEnvelope = oldvpar.FilterEnvelope != NULL ?
268             new Envelope(*oldvpar.FilterEnvelope) :
269             NULL;
270         vpar.FilterLfo = oldvpar.FilterLfo != NULL ?
271             new LFO(*oldvpar.FilterLfo) :
272             NULL;
273 
274         vpar.FMFreqEnvelope = oldvpar.FMFreqEnvelope != NULL ?
275             new Envelope(*oldvpar.FMFreqEnvelope) :
276             NULL;
277         vpar.FMAmpEnvelope = oldvpar.FMAmpEnvelope != NULL ?
278             new Envelope(*oldvpar.FMAmpEnvelope) :
279             NULL;
280 
281         // NoteVoicePar done
282 
283         int unison = unison_size[i];
284 
285         oscfreqhi[i] = new int[unison];
286         memcpy(oscfreqhi[i], orig.oscfreqhi[i], unison * sizeof(int));
287 
288         oscfreqlo[i] = new float[unison];
289         memcpy(oscfreqlo[i], orig.oscfreqlo[i], unison * sizeof(float));
290 
291         oscfreqhiFM[i] = new int[unison];
292         memcpy(oscfreqhiFM[i], orig.oscfreqhiFM[i], unison * sizeof(unsigned int));
293 
294         oscfreqloFM[i] = new float[unison];
295         memcpy(oscfreqloFM[i], orig.oscfreqloFM[i], unison * sizeof(float));
296 
297         oscposhi[i] = new int[unison];
298         memcpy(oscposhi[i], orig.oscposhi[i], unison * sizeof(int));
299 
300         oscposlo[i] = new float[unison];
301         memcpy(oscposlo[i], orig.oscposlo[i], unison * sizeof(float));
302 
303         oscposhiFM[i] = new int[unison];
304         memcpy(oscposhiFM[i], orig.oscposhiFM[i], unison * sizeof(unsigned int));
305 
306         oscposloFM[i] = new float[unison];
307         memcpy(oscposloFM[i], orig.oscposloFM[i], unison * sizeof(float));
308 
309 
310         unison_base_freq_rap[i] = new float[unison];
311         memcpy(unison_base_freq_rap[i], orig.unison_base_freq_rap[i],
312             unison * sizeof(float));
313 
314         unison_freq_rap[i] = new float[unison];
315         memcpy(unison_freq_rap[i], orig.unison_freq_rap[i],
316             unison * sizeof(float));
317 
318         unison_invert_phase[i] = new bool[unison];
319         memcpy(unison_invert_phase[i], orig.unison_invert_phase[i],
320             unison * sizeof(bool));
321 
322         unison_vibratto[i].amplitude = orig.unison_vibratto[i].amplitude;
323 
324         unison_vibratto[i].step = new float[unison];
325         memcpy(unison_vibratto[i].step,
326             orig.unison_vibratto[i].step, unison * sizeof(float));
327 
328         unison_vibratto[i].position = new float[unison];
329         memcpy(unison_vibratto[i].position,
330             orig.unison_vibratto[i].position, unison * sizeof(float));
331 
332 
333         FMoldsmp[i] = new float[unison];
334         memcpy(FMoldsmp[i], orig.unison_vibratto[i].position,
335             unison * sizeof(float));
336 
337         if (parentFMmod != NULL)
338         {
339             if (NoteVoicePar[i].FMEnabled == FREQ_MOD)
340             {
341                 FMFMoldPhase[i] = new float[unison];
342                 memcpy(FMFMoldPhase[i], orig.FMFMoldPhase[i],
343                     unison * sizeof(float));
344 
345                 FMFMoldInterpPhase[i] = new float[unison];
346                 memcpy(FMFMoldInterpPhase[i], orig.FMFMoldInterpPhase[i],
347                     unison * sizeof(float));
348 
349                 FMFMoldPMod[i] = new float[unison];
350                 memcpy(FMFMoldPMod[i], orig.FMFMoldPMod[i],
351                     unison * sizeof(float));
352             }
353 
354             if (forFM)
355             {
356                 oscFMoldPhase[i] = new float[unison];
357                 memcpy(oscFMoldPhase[i], orig.oscFMoldPhase[i],
358                     unison * sizeof(float));
359 
360                 oscFMoldInterpPhase[i] = new float[unison];
361                 memcpy(oscFMoldInterpPhase[i], orig.oscFMoldInterpPhase[i],
362                     unison * sizeof(float));
363 
364                 oscFMoldPMod[i] = new float[unison];
365                 memcpy(oscFMoldPMod[i], orig.oscFMoldPMod[i],
366                     unison * sizeof(float));
367             }
368         }
369 
370         oldamplitude[i] = orig.oldamplitude[i];
371         newamplitude[i] = orig.newamplitude[i];
372         FMoldamplitude[i] = orig.FMoldamplitude[i];
373         FMnewamplitude[i] = orig.FMnewamplitude[i];
374 
375         if (orig.subVoice[i] != NULL)
376         {
377             subVoice[i] = new ADnote*[orig.unison_size[i]];
378             for (int k = 0; k < orig.unison_size[i]; ++k)
379             {
380                 subVoice[i][k] = new ADnote(*orig.subVoice[i][k], topVoice, freqbasedmod[i] ? tmpmod_unison[k] : parentFMmod);
381             }
382         }
383         else
384             subVoice[i] = NULL;
385 
386         if (orig.subFMVoice[i] != NULL)
387         {
388             subFMVoice[i] = new ADnote*[orig.unison_size[i]];
389             for (int k = 0; k < orig.unison_size[i]; ++k)
390             {
391                 subFMVoice[i][k] = new ADnote(*orig.subFMVoice[i][k], topVoice, parentFMmod);
392             }
393         }
394         else
395             subFMVoice[i] = NULL;
396     }
397 }
398 
construct()399 void ADnote::construct()
400 {
401     if (velocity > 1.0f)
402         velocity = 1.0f;
403 
404     // Initialise some legato-specific vars
405     legatoFade = 1.0f; // Full volume
406     legatoFadeStep = 0.0f; // Legato disabled
407 
408     paramSeed = synth->randomINT();
409 
410     setRandomPan(synth->numRandom(), NoteGlobalPar.randpanL, NoteGlobalPar.randpanR, synth->getRuntime().panLaw, adpars->GlobalPar.PPanning, adpars->GlobalPar.PWidth);
411 
412     NoteGlobalPar.Fadein_adjustment =
413         adpars->GlobalPar.Fadein_adjustment / (float)FADEIN_ADJUSTMENT_SCALE;
414     NoteGlobalPar.Fadein_adjustment *= NoteGlobalPar.Fadein_adjustment;
415     if (adpars->GlobalPar.PPunchStrength)
416     {
417         NoteGlobalPar.Punch.Enabled = 1;
418         NoteGlobalPar.Punch.t = 1.0f; //start from 1.0 and to 0.0
419         NoteGlobalPar.Punch.initialvalue =
420             ((power<10>(1.5f * adpars->GlobalPar.PPunchStrength / 127.0f) - 1.0f)
421              * velF(velocity, adpars->GlobalPar.PPunchVelocitySensing));
422         float time = power<10>(3.0f * adpars->GlobalPar.PPunchTime / 127.0f) / 10000.0f; // 0.1 .. 100 ms
423         float stretch = powf(440.0f / basefreq, adpars->GlobalPar.PPunchStretch / 64.0f);
424         NoteGlobalPar.Punch.dt = 1.0f / (time * synth->samplerate_f * stretch);
425     }
426     else
427         NoteGlobalPar.Punch.Enabled = 0;
428 
429     detuneFromParent = 0.0;
430     unisonDetuneFactorFromParent = 1.0;
431 
432     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
433     {
434         for (int i = 0; i < 14; i++)
435             pinking[nvoice][i] = 0.0;
436 
437         NoteVoicePar[nvoice].OscilSmp = NULL;
438         NoteVoicePar[nvoice].FMSmp = NULL;
439         NoteVoicePar[nvoice].VoiceOut = NULL;
440 
441         NoteVoicePar[nvoice].FMEnabled = NONE;
442         NoteVoicePar[nvoice].FMringToSide = false;
443         NoteVoicePar[nvoice].FMVoice = -1;
444         unison_size[nvoice] = 1;
445 
446         subVoice[nvoice] = NULL;
447         subFMVoice[nvoice] = NULL;
448 
449         // If used as a sub voice, enable exactly one voice, the requested
450         // one. If not, enable voices that are enabled in settings.
451         if (!(adpars->VoicePar[nvoice].Enabled
452               && (subVoiceNumber == -1 || nvoice == subVoiceNumber)))
453         {
454             NoteVoicePar[nvoice].Enabled = false;
455             continue; // the voice is disabled
456         }
457 
458         int unison = adpars->VoicePar[nvoice].Unison_size;
459         if (unison < 1)
460             unison = 1;
461 
462         bool is_pwm = adpars->VoicePar[nvoice].PFMEnabled == PW_MOD;
463 
464         if (adpars->VoicePar[nvoice].Type != 0)
465         {
466             // Since noise unison of greater than two is touch goofy...
467             if (unison > 2)
468                 unison = 2;
469         }
470         else if (is_pwm)
471         {
472             /* Pulse width mod uses pairs of subvoices. */
473             unison *= 2;
474             // This many is likely to sound like noise anyhow.
475             if (unison > 64)
476                 unison = 64;
477         }
478 
479         // compute unison
480         unison_size[nvoice] = unison;
481 
482         unison_base_freq_rap[nvoice] = new float[unison];
483         unison_freq_rap[nvoice] = new float[unison];
484         unison_invert_phase[nvoice] = new bool[unison];
485         unison_vibratto[nvoice].step = new float[unison];
486         unison_vibratto[nvoice].position = new float[unison];
487 
488         if (unison >> is_pwm > 1)
489         {
490             for (int k = 0; k < unison; ++k)
491             {
492                 unison_vibratto[nvoice].position[k] = synth->numRandom() * 1.8f - 0.9f;
493 
494                 // Give step a random direction. The amplitude doesn't matter right
495                 // now, only the sign, which will be preserved in
496                 // computeNoteParameters().
497                 if (synth->numRandom() < 0.5f)
498                     unison_vibratto[nvoice].step[k] = -1.0f;
499                 else
500                     unison_vibratto[nvoice].step[k] = 1.0f;
501 
502                 if (is_pwm)
503                 {
504                     // Set the next position the same as this one.
505                     unison_vibratto[nvoice].position[k+1] =
506                         unison_vibratto[nvoice].position[k];
507                     ++k; // Skip an iteration.
508                     // step and amplitude are handled in computeNoteParameters.
509                 }
510             }
511         }
512         else // No vibrato for a single voice
513         {
514             if (is_pwm)
515             {
516                 unison_vibratto[nvoice].position[1] = 0.0f;
517             }
518             if (is_pwm || unison == 1)
519             {
520                 unison_vibratto[nvoice].position[0] = 0.0f;
521             }
522         }
523 
524         oscfreqhi[nvoice] = new int[unison];
525         oscfreqlo[nvoice] = new float[unison];
526         oscfreqhiFM[nvoice] = new int[unison];
527         oscfreqloFM[nvoice] = new float[unison];
528         oscposhi[nvoice] = new int[unison];
529         oscposlo[nvoice] = new float[unison];
530         oscposhiFM[nvoice] = new int[unison];
531         oscposloFM[nvoice] = new float[unison];
532 
533         NoteVoicePar[nvoice].Enabled = true;
534         memset(oscposhi[nvoice], 0, unison * sizeof(int));
535         memset(oscposlo[nvoice], 0, unison * sizeof(float));
536         memset(oscposhiFM[nvoice], 0, unison * sizeof(int));
537         memset(oscposloFM[nvoice], 0, unison * sizeof(float));
538 
539         NoteVoicePar[nvoice].Voice = adpars->VoicePar[nvoice].PVoice;
540 
541         int vc = nvoice;
542         if (adpars->VoicePar[nvoice].Pextoscil != -1)
543             vc = adpars->VoicePar[nvoice].Pextoscil;
544         if (subVoiceNumber == -1) {
545             // Draw new seed for randomisation of harmonics
546             // Since NoteON happens at random times, this actually injects entropy
547             adpars->VoicePar[nvoice].OscilSmp->newrandseed();
548 
549             NoteVoicePar[nvoice].OscilSmp = // the extra points contains the first point
550                 new float[synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES];
551 
552             // Get the voice's oscil or external's voice oscil
553             if (!adpars->GlobalPar.Hrandgrouping)
554                 adpars->VoicePar[vc].OscilSmp->newrandseed();
555 
556             // Actual OscilSmp rendering done later.
557         } else {
558             // If subvoice, use oscillator from original voice.
559             NoteVoicePar[nvoice].OscilSmp = topVoice->NoteVoicePar[nvoice].OscilSmp;
560         }
561 
562         int oscposhi_start;
563         if (NoteVoicePar[nvoice].Voice == -1)
564             oscposhi_start = adpars->VoicePar[vc].OscilSmp->getPhase();
565         else
566             oscposhi_start = 0;
567         int kth_start = oscposhi_start;
568         for (int k = 0; k < unison; ++k)
569         {
570             oscposhi[nvoice][k] = kth_start % synth->oscilsize;
571             // put random starting point for other subvoices
572             kth_start = oscposhi_start + (int)(synth->numRandom() * adpars->VoicePar[nvoice].Unison_phase_randomness
573                                         / 127.0f * (synth->oscilsize - 1));
574         }
575 
576         NoteVoicePar[nvoice].FreqLfo = NULL;
577         NoteVoicePar[nvoice].FreqEnvelope = NULL;
578 
579         NoteVoicePar[nvoice].AmpLfo = NULL;
580         NoteVoicePar[nvoice].AmpEnvelope = NULL;
581 
582         NoteVoicePar[nvoice].VoiceFilterL = NULL;
583         NoteVoicePar[nvoice].VoiceFilterR = NULL;
584         NoteVoicePar[nvoice].FilterEnvelope = NULL;
585         NoteVoicePar[nvoice].FilterLfo = NULL;
586 
587         if (adpars->VoicePar[nvoice].Type != 0)
588             NoteVoicePar[nvoice].FMEnabled = NONE;
589         else
590             switch (adpars->VoicePar[nvoice].PFMEnabled)
591             {
592                 case 1:
593                     NoteVoicePar[nvoice].FMEnabled = MORPH;
594                     freqbasedmod[nvoice] = false;
595                     break;
596                 case 2:
597                     NoteVoicePar[nvoice].FMEnabled = RING_MOD;
598                     freqbasedmod[nvoice] = false;
599                     break;
600                 case 3:
601                     NoteVoicePar[nvoice].FMEnabled = PHASE_MOD;
602                     freqbasedmod[nvoice] = true;
603                     break;
604                 case 4:
605                     NoteVoicePar[nvoice].FMEnabled = FREQ_MOD;
606                     freqbasedmod[nvoice] = true;
607                     break;
608                 case 5:
609                     NoteVoicePar[nvoice].FMEnabled = PW_MOD;
610                     freqbasedmod[nvoice] = true;
611                     break;
612                 default:
613                     NoteVoicePar[nvoice].FMEnabled = NONE;
614                     freqbasedmod[nvoice] = false;
615                     break;
616             }
617         NoteVoicePar[nvoice].FMringToSide = adpars->VoicePar[nvoice].PFMringToSide;
618         NoteVoicePar[nvoice].FMVoice = adpars->VoicePar[nvoice].PFMVoice;
619         NoteVoicePar[nvoice].FMFreqEnvelope = NULL;
620         NoteVoicePar[nvoice].FMAmpEnvelope = NULL;
621 
622         FMoldsmp[nvoice] = new float [unison];
623         memset(FMoldsmp[nvoice], 0, unison * sizeof(float));
624 
625         firsttick[nvoice] = 1;
626         NoteVoicePar[nvoice].DelayTicks =
627             (int)((expf(adpars->VoicePar[nvoice].PDelay / 127.0f
628             * logf(50.0f)) - 1.0f) / synth->fixed_sample_step_f / 10.0f);
629 
630         if (parentFMmod != NULL && NoteVoicePar[nvoice].FMEnabled == FREQ_MOD) {
631             FMFMoldPhase[nvoice] = new float [unison];
632             memset(FMFMoldPhase[nvoice], 0, unison * sizeof(*FMFMoldPhase[nvoice]));
633             FMFMoldInterpPhase[nvoice] = new float [unison];
634             memset(FMFMoldInterpPhase[nvoice], 0, unison * sizeof(*FMFMoldInterpPhase[nvoice]));
635             FMFMoldPMod[nvoice] = new float [unison];
636             memset(FMFMoldPMod[nvoice], 0, unison * sizeof(*FMFMoldPMod[nvoice]));
637         }
638         if (parentFMmod != NULL && forFM) {
639             oscFMoldPhase[nvoice] = new float [unison];
640             memset(oscFMoldPhase[nvoice], 0, unison * sizeof(*oscFMoldPhase[nvoice]));
641             oscFMoldInterpPhase[nvoice] = new float [unison];
642             memset(oscFMoldInterpPhase[nvoice], 0, unison * sizeof(*oscFMoldInterpPhase[nvoice]));
643             oscFMoldPMod[nvoice] = new float [unison];
644             memset(oscFMoldPMod[nvoice], 0, unison * sizeof(*oscFMoldPMod[nvoice]));
645         }
646     }
647 
648     max_unison = 1;
649     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
650         if (unison_size[nvoice] > max_unison)
651             max_unison = unison_size[nvoice];
652 
653     tmpwave_unison = new float*[max_unison];
654     tmpmod_unison = new float*[max_unison];
655     for (int k = 0; k < max_unison; ++k)
656     {
657         tmpwave_unison[k] = (float*)fftwf_malloc(synth->bufferbytes);
658         memset(tmpwave_unison[k], 0, synth->bufferbytes);
659         tmpmod_unison[k] = (float*)fftwf_malloc(synth->bufferbytes);
660         memset(tmpmod_unison[k], 0, synth->bufferbytes);
661     }
662 
663     initParameters();
664     initSubVoices();
665 
666     globalnewamplitude = NoteGlobalPar.Volume
667                          * NoteGlobalPar.AmpEnvelope->envout_dB()
668                          * NoteGlobalPar.AmpLfo->amplfoout();
669 }
670 
initSubVoices(void)671 void ADnote::initSubVoices(void)
672 {
673     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
674     {
675         if (!NoteVoicePar[nvoice].Enabled)
676             continue;
677 
678         if (NoteVoicePar[nvoice].Voice != -1)
679         {
680             subVoice[nvoice] = new ADnote*[unison_size[nvoice]];
681             for (int k = 0; k < unison_size[nvoice]; ++k) {
682                 float *freqmod = freqbasedmod[nvoice] ? tmpmod_unison[k] : parentFMmod;
683                 subVoice[nvoice][k] = new ADnote(topVoice,
684                                                  getVoiceBaseFreq(nvoice),
685                                                  oscposhi[nvoice][k],
686                                                  NoteVoicePar[nvoice].Voice,
687                                                  freqmod, forFM);
688             }
689         }
690 
691         if (NoteVoicePar[nvoice].FMVoice != -1)
692         {
693             bool voiceForFM = NoteVoicePar[nvoice].FMEnabled == FREQ_MOD;
694             subFMVoice[nvoice] = new ADnote*[unison_size[nvoice]];
695             for (int k = 0; k < unison_size[nvoice]; ++k) {
696                 subFMVoice[nvoice][k] = new ADnote(topVoice,
697                                                    getFMVoiceBaseFreq(nvoice),
698                                                    oscposhiFM[nvoice][k],
699                                                    NoteVoicePar[nvoice].FMVoice,
700                                                    parentFMmod, voiceForFM);
701             }
702         }
703     }
704 }
705 
legatoFadeIn(float freq_,float velocity_,int portamento_,int midinote_)706 void ADnote::legatoFadeIn(float freq_, float velocity_, int portamento_, int midinote_)
707 {
708     basefreq = freq_;
709     velocity = velocity_;
710     if (velocity > 1.0)
711         velocity = 1.0;
712     portamento = portamento_;
713     midinote = midinote_;
714 
715     if (!portamento) // Do not crossfade portamento
716     {
717         legatoFade = 0.0f; // Start silent
718         legatoFadeStep = synth->fadeStepShort; // Positive steps
719 
720         // Re-randomize harmonics, but only if we're not doing portamento
721         if (subVoiceNumber == -1)
722             for (int i = 0; i < NUM_VOICES; ++i)
723             {
724                 adpars->VoicePar[i].OscilSmp->newrandseed();
725                 auto &extoscil = adpars->VoicePar[i].Pextoscil;
726                 if (extoscil != -1 && !adpars->GlobalPar.Hrandgrouping)
727                     adpars->VoicePar[extoscil].OscilSmp->newrandseed();
728             }
729 
730         // This recalculates certain things like harmonic phase/amplitude randomness,
731         // which we probably don't want with portamento. This may not even be
732         // desirable with plain legato, but it at least makes some sense in that
733         // case. Portamento should be a smooth change in pitch, with no change in
734         // timbre, or at least a gradual one. It may be desirable to have base
735         // frequency sensitive things like filter scaling and envelope stretching
736         // take portamento into account, but to do this properly would require more
737         // than just recalculating based on basefreq.
738         computeNoteParameters();
739     }
740 
741     for (int i = 0; i < NUM_VOICES; ++i)
742     {
743         auto &vpar = NoteVoicePar[i];
744 
745         if (!vpar.Enabled)
746             continue;
747 
748         if (subVoice[i] != NULL)
749             for (int k = 0; k < unison_size[i]; ++k)
750                 subVoice[i][k]->legatoFadeIn(getVoiceBaseFreq(i), velocity_, portamento_, midinote_);
751         if (subFMVoice[i] != NULL)
752             for (int k = 0; k < unison_size[i]; ++k)
753                 subFMVoice[i][k]->legatoFadeIn(getFMVoiceBaseFreq(i), velocity_, portamento_, midinote_);
754     }
755 }
756 
757 // This exists purely to avoid boilerplate. It might be useful
758 // elsewhere, but converting the relevant code to be more
759 // RAII-friendly would probably be more worthwhile.
copyOrAssign(T * lhs,const T * rhs)760 template<class T> inline void copyOrAssign(T *lhs, const T *rhs)
761 {
762         if (rhs != NULL)
763         {
764             if (lhs != NULL)
765                 *lhs = *rhs;
766             else
767                 lhs = new T(*rhs);
768         }
769         else
770         {
771             delete lhs;
772             lhs = NULL;
773         }
774 }
775 
legatoFadeOut(const ADnote & orig)776 void ADnote::legatoFadeOut(const ADnote &orig)
777 {
778     basefreq = orig.basefreq;
779     velocity = orig.velocity;
780     portamento = orig.portamento;
781     midinote = orig.midinote;
782 
783     auto &gpar = NoteGlobalPar;
784     auto &oldgpar = orig.NoteGlobalPar;
785 
786     // These should never be null
787     *gpar.FreqEnvelope = *oldgpar.FreqEnvelope;
788     *gpar.FreqLfo = *oldgpar.FreqLfo;
789     *gpar.AmpEnvelope = *oldgpar.AmpEnvelope;
790     *gpar.AmpLfo = *oldgpar.AmpLfo;
791     *gpar.FilterEnvelope = *oldgpar.FilterEnvelope;
792     *gpar.FilterLfo = *oldgpar.FilterLfo;
793 
794     gpar.Fadein_adjustment = oldgpar.Fadein_adjustment;
795     gpar.Punch = oldgpar.Punch;
796 
797     paramSeed = orig.paramSeed;
798 
799     globalnewamplitude = orig.globalnewamplitude;
800     globaloldamplitude = orig.globaloldamplitude;
801 
802     // Supporting virtual copy assignment would be hairy
803     // so we have to use the copy constructor here
804     delete gpar.GlobalFilterL;
805     gpar.GlobalFilterL = new Filter(*oldgpar.GlobalFilterL);
806     if (stereo)
807     {
808         delete gpar.GlobalFilterR;
809         gpar.GlobalFilterR = new Filter(*oldgpar.GlobalFilterR);
810     }
811 
812     memcpy(pinking, orig.pinking, sizeof(pinking));
813     memcpy(firsttick, orig.firsttick, sizeof(firsttick));
814 
815     memcpy(oldamplitude, orig.oldamplitude, sizeof(oldamplitude));
816     memcpy(newamplitude, orig.newamplitude, sizeof(newamplitude));
817     memcpy(FMoldamplitude, orig.FMoldamplitude, sizeof(FMoldamplitude));
818     memcpy(FMnewamplitude, orig.FMnewamplitude, sizeof(FMnewamplitude));
819 
820     for (int i = 0; i < NUM_VOICES; ++i)
821     {
822         auto &vpar = NoteVoicePar[i];
823         auto &oldvpar = orig.NoteVoicePar[i];
824 
825         vpar.Enabled = oldvpar.Enabled;
826         if (!vpar.Enabled)
827             continue;
828 
829         vpar.DelayTicks = oldvpar.DelayTicks;
830         vpar.Punch = oldvpar.Punch;
831         vpar.phase_offset = oldvpar.phase_offset;
832 
833         int unison = adpars->VoicePar[i].Unison_size;
834         memcpy(oscposhi[i], orig.oscposhi[i], unison * sizeof(int));
835         memcpy(oscposlo[i], orig.oscposlo[i], unison * sizeof(float));
836         memcpy(oscposhiFM[i], orig.oscposhiFM[i], unison * sizeof(int));
837         memcpy(oscposloFM[i], orig.oscposloFM[i], unison * sizeof(float));
838 
839         copyOrAssign(vpar.FreqLfo, oldvpar.FreqLfo);
840         copyOrAssign(vpar.FreqEnvelope, oldvpar.FreqEnvelope);
841 
842         copyOrAssign(vpar.AmpLfo, oldvpar.AmpLfo);
843         copyOrAssign(vpar.AmpEnvelope, oldvpar.AmpEnvelope);
844 
845         delete vpar.VoiceFilterL;
846         vpar.VoiceFilterL = NULL;
847         if (oldvpar.VoiceFilterL != NULL)
848             vpar.VoiceFilterL = new Filter(*oldvpar.VoiceFilterL);
849         delete vpar.VoiceFilterR;
850         vpar.VoiceFilterR = NULL;
851         if (oldvpar.VoiceFilterR != NULL)
852             vpar.VoiceFilterR = new Filter(*oldvpar.VoiceFilterR);
853 
854         copyOrAssign(vpar.FilterLfo, oldvpar.FilterLfo);
855         copyOrAssign(vpar.FilterEnvelope, oldvpar.FilterEnvelope);
856 
857         copyOrAssign(vpar.FMFreqEnvelope, oldvpar.FMFreqEnvelope);
858         copyOrAssign(vpar.FMAmpEnvelope, oldvpar.FMAmpEnvelope);
859 
860         if (subVoice[i] != NULL)
861             for (int k = 0; k < unison_size[i]; ++k)
862                 subVoice[i][k]->legatoFadeOut(*orig.subVoice[i][k]);
863         if (subFMVoice[i] != NULL)
864             for (int k = 0; k < unison_size[i]; ++k)
865                 subFMVoice[i][k]->legatoFadeOut(*orig.subFMVoice[i][k]);
866     }
867 
868     legatoFade = 1.0f; // Start at full volume
869     legatoFadeStep = -synth->fadeStepShort; // Negative steps
870 }
871 
872 
873 // Kill a voice of ADnote
killVoice(int nvoice)874 void ADnote::killVoice(int nvoice)
875 {
876     delete [] oscfreqhi[nvoice];
877     delete [] oscfreqlo[nvoice];
878     delete [] oscfreqhiFM[nvoice];
879     delete [] oscfreqloFM[nvoice];
880     delete [] oscposhi[nvoice];
881     delete [] oscposlo[nvoice];
882     delete [] oscposhiFM[nvoice];
883     delete [] oscposloFM[nvoice];
884 
885     delete [] unison_base_freq_rap[nvoice];
886     delete [] unison_freq_rap[nvoice];
887     delete [] unison_invert_phase[nvoice];
888     delete [] FMoldsmp[nvoice];
889     delete [] unison_vibratto[nvoice].step;
890     delete [] unison_vibratto[nvoice].position;
891 
892     if (subVoice[nvoice] != NULL) {
893         for (int k = 0; k < unison_size[nvoice]; ++k)
894             delete subVoice[nvoice][k];
895         delete [] subVoice[nvoice];
896     }
897     subVoice[nvoice] = NULL;
898 
899     if (subFMVoice[nvoice] != NULL) {
900         for (int k = 0; k < unison_size[nvoice]; ++k)
901             delete subFMVoice[nvoice][k];
902         delete [] subFMVoice[nvoice];
903     }
904     subFMVoice[nvoice] = NULL;
905 
906     if (NoteVoicePar[nvoice].FreqEnvelope != NULL)
907         delete NoteVoicePar[nvoice].FreqEnvelope;
908     NoteVoicePar[nvoice].FreqEnvelope = NULL;
909 
910     if (NoteVoicePar[nvoice].FreqLfo != NULL)
911         delete NoteVoicePar[nvoice].FreqLfo;
912     NoteVoicePar[nvoice].FreqLfo = NULL;
913 
914     if (NoteVoicePar[nvoice].AmpEnvelope != NULL)
915         delete NoteVoicePar[nvoice].AmpEnvelope;
916     NoteVoicePar[nvoice].AmpEnvelope = NULL;
917 
918     if (NoteVoicePar[nvoice].AmpLfo != NULL)
919         delete NoteVoicePar[nvoice].AmpLfo;
920     NoteVoicePar[nvoice].AmpLfo = NULL;
921 
922     if (NoteVoicePar[nvoice].VoiceFilterL != NULL)
923         delete NoteVoicePar[nvoice].VoiceFilterL;
924     NoteVoicePar[nvoice].VoiceFilterL = NULL;
925 
926     if (NoteVoicePar[nvoice].VoiceFilterR != NULL)
927         delete NoteVoicePar[nvoice].VoiceFilterR;
928     NoteVoicePar[nvoice].VoiceFilterR = NULL;
929 
930     if (NoteVoicePar[nvoice].FilterEnvelope != NULL)
931         delete NoteVoicePar[nvoice].FilterEnvelope;
932     NoteVoicePar[nvoice].FilterEnvelope = NULL;
933 
934     if (NoteVoicePar[nvoice].FilterLfo != NULL)
935         delete NoteVoicePar[nvoice].FilterLfo;
936     NoteVoicePar[nvoice].FilterLfo = NULL;
937 
938     if (NoteVoicePar[nvoice].FMFreqEnvelope != NULL)
939         delete NoteVoicePar[nvoice].FMFreqEnvelope;
940     NoteVoicePar[nvoice].FMFreqEnvelope = NULL;
941 
942     if (NoteVoicePar[nvoice].FMAmpEnvelope != NULL)
943         delete NoteVoicePar[nvoice].FMAmpEnvelope;
944     NoteVoicePar[nvoice].FMAmpEnvelope = NULL;
945 
946     if (NoteVoicePar[nvoice].VoiceOut)
947         memset(NoteVoicePar[nvoice].VoiceOut, 0, synth->bufferbytes);
948         // do not delete, yet: perhaps is used by another voice
949 
950     if (parentFMmod != NULL && NoteVoicePar[nvoice].FMEnabled == FREQ_MOD) {
951         delete [] FMFMoldPhase[nvoice];
952         delete [] FMFMoldInterpPhase[nvoice];
953         delete [] FMFMoldPMod[nvoice];
954     }
955     if (parentFMmod != NULL && forFM) {
956         delete [] oscFMoldPhase[nvoice];
957         delete [] oscFMoldInterpPhase[nvoice];
958         delete [] oscFMoldPMod[nvoice];
959     }
960 
961     NoteVoicePar[nvoice].Enabled = false;
962 }
963 
964 
965 // Kill the note
killNote()966 void ADnote::killNote()
967 {
968     int nvoice;
969     for (nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
970     {
971         if (NoteVoicePar[nvoice].Enabled)
972             killVoice(nvoice);
973 
974         // Parent deletes oscillator samples.
975         if (subVoiceNumber == -1)
976             delete [] NoteVoicePar[nvoice].OscilSmp;
977         if ((NoteVoicePar[nvoice].FMEnabled != NONE)
978             && (NoteVoicePar[nvoice].FMVoice < 0)
979             && (subVoiceNumber == -1))
980             fftwf_free(NoteVoicePar[nvoice].FMSmp);
981     }
982 
983 
984     delete NoteGlobalPar.FreqEnvelope;
985     delete NoteGlobalPar.FreqLfo;
986     delete NoteGlobalPar.AmpEnvelope;
987     delete NoteGlobalPar.AmpLfo;
988     delete NoteGlobalPar.GlobalFilterL;
989     if (stereo)
990         delete NoteGlobalPar.GlobalFilterR;
991     delete NoteGlobalPar.FilterEnvelope;
992     delete NoteGlobalPar.FilterLfo;
993 
994     NoteStatus = NOTE_DISABLED;
995 }
996 
997 
~ADnote()998 ADnote::~ADnote()
999 {
1000     if (NoteStatus != NOTE_DISABLED)
1001         killNote();
1002 
1003     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
1004     {
1005         if (NoteVoicePar[nvoice].VoiceOut)
1006         {
1007             fftwf_free(NoteVoicePar[nvoice].VoiceOut);
1008             NoteVoicePar[nvoice].VoiceOut = NULL;
1009         }
1010     }
1011     for (int k = 0; k < max_unison; ++k) {
1012         fftwf_free(tmpwave_unison[k]);
1013         fftwf_free(tmpmod_unison[k]);
1014     }
1015     delete [] tmpwave_unison;
1016     delete [] tmpmod_unison;
1017 }
1018 
1019 
1020 // Init the parameters
initParameters(void)1021 void ADnote::initParameters(void)
1022 {
1023     int nvoice, i;
1024 
1025     // Global Parameters
1026     NoteGlobalPar.FreqEnvelope = new Envelope(adpars->GlobalPar.FreqEnvelope, basefreq, synth);
1027     NoteGlobalPar.FreqLfo = new LFO(adpars->GlobalPar.FreqLfo, basefreq, synth);
1028     NoteGlobalPar.AmpEnvelope = new Envelope(adpars->GlobalPar.AmpEnvelope, basefreq, synth);
1029     NoteGlobalPar.AmpLfo = new LFO(adpars->GlobalPar.AmpLfo, basefreq, synth);
1030 
1031     NoteGlobalPar.AmpEnvelope->envout_dB(); // discard the first envelope output
1032     NoteGlobalPar.GlobalFilterL = new Filter(adpars->GlobalPar.GlobalFilter, synth);
1033     if (stereo)
1034         NoteGlobalPar.GlobalFilterR = new Filter(adpars->GlobalPar.GlobalFilter, synth);
1035     NoteGlobalPar.FilterEnvelope =
1036         new Envelope(adpars->GlobalPar.FilterEnvelope, basefreq, synth);
1037     NoteGlobalPar.FilterLfo = new LFO(adpars->GlobalPar.FilterLfo, basefreq, synth);
1038 
1039     // Forbids the Modulation Voice to be greater or equal than voice
1040     for (i = 0; i < NUM_VOICES; ++i)
1041         if (NoteVoicePar[i].FMVoice >= i)
1042             NoteVoicePar[i].FMVoice = -1;
1043 
1044     // Voice Parameter init
1045     for (nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
1046     {
1047         if (!NoteVoicePar[nvoice].Enabled)
1048             continue;
1049 
1050         NoteVoicePar[nvoice].noisetype = adpars->VoicePar[nvoice].Type;
1051 
1052         setRandomPan(synth->numRandom(), NoteVoicePar[nvoice].randpanL, NoteVoicePar[nvoice].randpanR, synth->getRuntime().panLaw, adpars->VoicePar[nvoice].PPanning, adpars->VoicePar[nvoice].PWidth);
1053 
1054         newamplitude[nvoice] = 1.0f;
1055         if (adpars->VoicePar[nvoice].PAmpEnvelopeEnabled)
1056         {
1057             NoteVoicePar[nvoice].AmpEnvelope =
1058                 new Envelope(adpars->VoicePar[nvoice].AmpEnvelope, basefreq, synth);
1059             NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); // discard the first envelope sample
1060             newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
1061         }
1062 
1063         if (adpars->VoicePar[nvoice].PAmpLfoEnabled)
1064         {
1065             NoteVoicePar[nvoice].AmpLfo =
1066                 new LFO(adpars->VoicePar[nvoice].AmpLfo, basefreq, synth);
1067             newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout();
1068         }
1069 
1070         // Voice Frequency Parameters Init
1071         if (adpars->VoicePar[nvoice].PFreqEnvelopeEnabled)
1072             NoteVoicePar[nvoice].FreqEnvelope =
1073                 new Envelope(adpars->VoicePar[nvoice].FreqEnvelope, basefreq, synth);
1074 
1075         if (adpars->VoicePar[nvoice].PFreqLfoEnabled)
1076             NoteVoicePar[nvoice].FreqLfo =
1077                 new LFO(adpars->VoicePar[nvoice].FreqLfo, basefreq, synth);
1078 
1079         // Voice Filter Parameters Init
1080         if (adpars->VoicePar[nvoice].PFilterEnabled)
1081         {
1082             NoteVoicePar[nvoice].VoiceFilterL =
1083                 new Filter(adpars->VoicePar[nvoice].VoiceFilter, synth);
1084             NoteVoicePar[nvoice].VoiceFilterR =
1085                 new Filter(adpars->VoicePar[nvoice].VoiceFilter, synth);
1086         }
1087 
1088         if (adpars->VoicePar[nvoice].PFilterEnvelopeEnabled)
1089             NoteVoicePar[nvoice].FilterEnvelope =
1090                 new Envelope(adpars->VoicePar[nvoice].FilterEnvelope,
1091                              basefreq, synth);
1092 
1093         if (adpars->VoicePar[nvoice].PFilterLfoEnabled)
1094             NoteVoicePar[nvoice].FilterLfo =
1095                 new LFO(adpars->VoicePar[nvoice].FilterLfo, basefreq, synth);
1096 
1097         // Voice Modulation Parameters Init
1098         if (NoteVoicePar[nvoice].FMEnabled != NONE
1099            && NoteVoicePar[nvoice].FMVoice < 0)
1100         {
1101             // Perform Anti-aliasing only on MORPH or RING MODULATION
1102 
1103             int vc = nvoice;
1104             if (adpars->VoicePar[nvoice].PextFMoscil != -1)
1105                 vc = adpars->VoicePar[nvoice].PextFMoscil;
1106 
1107             if (subVoiceNumber == -1) {
1108                 adpars->VoicePar[nvoice].FMSmp->newrandseed();
1109                 NoteVoicePar[nvoice].FMSmp =
1110                     (float*)fftwf_malloc((synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES) * sizeof(float));
1111 
1112                 if (!adpars->GlobalPar.Hrandgrouping)
1113                     adpars->VoicePar[vc].FMSmp->newrandseed();
1114             } else {
1115                 // If subvoice use oscillator from original voice.
1116                 NoteVoicePar[nvoice].FMSmp = topVoice->NoteVoicePar[nvoice].FMSmp;
1117             }
1118 
1119             for (int k = 0; k < unison_size[nvoice]; ++k)
1120                 oscposhiFM[nvoice][k] =
1121                     (oscposhi[nvoice][k] + adpars->VoicePar[vc].FMSmp->
1122                      getPhase()) % synth->oscilsize;
1123 
1124             NoteVoicePar[nvoice].FMphase_offset = 0;
1125         }
1126 
1127         if (adpars->VoicePar[nvoice].PFMFreqEnvelopeEnabled != 0)
1128             NoteVoicePar[nvoice].FMFreqEnvelope =
1129                 new Envelope(adpars->VoicePar[nvoice].FMFreqEnvelope,
1130                              basefreq, synth);
1131 
1132         if (adpars->VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0)
1133             NoteVoicePar[nvoice].FMAmpEnvelope =
1134                 new Envelope(adpars->VoicePar[nvoice].FMAmpEnvelope,
1135                              basefreq, synth);
1136     }
1137 
1138     computeNoteParameters();
1139 
1140     for (nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
1141     {
1142         if (!NoteVoicePar[nvoice].Enabled)
1143             continue;
1144 
1145         FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume
1146                                  * ctl->fmamp.relamp;
1147 
1148         if (NoteVoicePar[nvoice].FMAmpEnvelope != NULL)
1149         {
1150             FMnewamplitude[nvoice] *=
1151                 NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
1152         }
1153     }
1154 
1155     if (subVoiceNumber != -1)
1156     {
1157         NoteVoicePar[subVoiceNumber].VoiceOut = (float*)fftwf_malloc(synth->bufferbytes);
1158         memset(NoteVoicePar[subVoiceNumber].VoiceOut, 0, synth->bufferbytes);
1159     }
1160 }
1161 
computeNoteParameters(void)1162 void ADnote::computeNoteParameters(void)
1163 {
1164     paramRNG.init(paramSeed);
1165 
1166     NoteGlobalPar.Detune = getDetune(adpars->GlobalPar.PDetuneType,
1167                                      adpars->GlobalPar.PCoarseDetune,
1168                                      adpars->GlobalPar.PDetune);
1169     bandwidthDetuneMultiplier = adpars->getBandwidthDetuneMultiplier();
1170 
1171     NoteGlobalPar.Volume =
1172         4.0f                                                           // +12dB boost (similar on PADnote, while SUBnote only boosts +6dB)
1173         * decibel<-60>(1.0f - adpars->GlobalPar.PVolume / 96.0f)       // -60 dB .. +19.375 dB
1174         * velF(velocity, adpars->GlobalPar.PAmpVelocityScaleFunction); // velocity sensing
1175 
1176     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
1177     {
1178         if (!NoteVoicePar[nvoice].Enabled)
1179             continue;
1180 
1181         if (subVoiceNumber == -1) {
1182             int BendAdj = adpars->VoicePar[nvoice].PBendAdjust - 64;
1183             if (BendAdj % 24 == 0)
1184                 NoteVoicePar[nvoice].BendAdjust = BendAdj / 24;
1185             else
1186                 NoteVoicePar[nvoice].BendAdjust = BendAdj / 24.0f;
1187         } else {
1188             // No bend adjustments for sub voices. Take from parent via
1189             // detuneFromParent.
1190             NoteVoicePar[nvoice].BendAdjust = 0.0f;
1191         }
1192 
1193         float offset_val = (adpars->VoicePar[nvoice].POffsetHz - 64)/64.0f;
1194         NoteVoicePar[nvoice].OffsetHz =
1195             15.0f*(offset_val * sqrtf(fabsf(offset_val)));
1196 
1197         NoteVoicePar[nvoice].fixedfreq = adpars->VoicePar[nvoice].Pfixedfreq;
1198         NoteVoicePar[nvoice].fixedfreqET = adpars->VoicePar[nvoice].PfixedfreqET;
1199 
1200         // use the Globalpars.detunetype if the detunetype is 0
1201         if (adpars->VoicePar[nvoice].PDetuneType)
1202         {
1203             NoteVoicePar[nvoice].Detune =
1204                 getDetune(adpars->VoicePar[nvoice].PDetuneType,
1205                           adpars->VoicePar[nvoice].PCoarseDetune, 8192); // coarse detune
1206             NoteVoicePar[nvoice].FineDetune =
1207                 getDetune(adpars->VoicePar[nvoice].PDetuneType, 0,
1208                           adpars->VoicePar[nvoice].PDetune); // fine detune
1209         }
1210         else
1211         {
1212             NoteVoicePar[nvoice].Detune =
1213                 getDetune(adpars->GlobalPar.PDetuneType,
1214                           adpars->VoicePar[nvoice].PCoarseDetune, 8192); // coarse detune
1215             NoteVoicePar[nvoice].FineDetune =
1216                 getDetune(adpars->GlobalPar.PDetuneType, 0,
1217                           adpars->VoicePar[nvoice].PDetune); // fine detune
1218         }
1219         if (adpars->VoicePar[nvoice].PFMDetuneType != 0)
1220             NoteVoicePar[nvoice].FMDetune =
1221                 getDetune(adpars->VoicePar[nvoice].PFMDetuneType,
1222                           adpars->VoicePar[nvoice].PFMCoarseDetune,
1223                           adpars->VoicePar[nvoice].PFMDetune);
1224         else
1225             NoteVoicePar[nvoice].FMDetune =
1226                 getDetune(adpars->GlobalPar.PDetuneType, adpars->VoicePar[nvoice].
1227                           PFMCoarseDetune, adpars->VoicePar[nvoice].PFMDetune);
1228 
1229         NoteVoicePar[nvoice].filterbypass = adpars->VoicePar[nvoice].Pfilterbypass;
1230 
1231         NoteVoicePar[nvoice].FMDetuneFromBaseOsc =
1232             (adpars->VoicePar[nvoice].PFMDetuneFromBaseOsc != 0);
1233         NoteVoicePar[nvoice].FMFreqFixed  = adpars->VoicePar[nvoice].PFMFixedFreq;
1234 
1235         if (subVoice[nvoice] != NULL)
1236         {
1237             float basefreq = getVoiceBaseFreq(nvoice);
1238             if (basefreq != subVoice[nvoice][0]->basefreq)
1239                 for (int k = 0; k < unison_size[nvoice]; ++k)
1240                     subVoice[nvoice][k]->basefreq = basefreq;
1241         }
1242         if (subFMVoice[nvoice] != NULL)
1243         {
1244             float basefreq = getFMVoiceBaseFreq(nvoice);
1245             if (basefreq != subFMVoice[nvoice][0]->basefreq)
1246                 for (int k = 0; k < unison_size[nvoice]; ++k)
1247                     subFMVoice[nvoice][k]->basefreq = basefreq;
1248         }
1249 
1250         // Compute the Voice's modulator volume (incl. damping)
1251         float fmvoldamp = powf(440.0f / getVoiceBaseFreq(nvoice),
1252                                adpars->VoicePar[nvoice].PFMVolumeDamp
1253                                / 64.0f - 1.0f);
1254         switch (NoteVoicePar[nvoice].FMEnabled)
1255         {
1256             case PHASE_MOD:
1257             case PW_MOD:
1258                 fmvoldamp = powf(440.0f / getVoiceBaseFreq(nvoice),
1259                                  adpars->VoicePar[nvoice].PFMVolumeDamp / 64.0f);
1260                 NoteVoicePar[nvoice].FMVolume =
1261                     (expf(adpars->VoicePar[nvoice].PFMVolume / 127.0f
1262                           * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
1263                 break;
1264 
1265             case FREQ_MOD:
1266                 NoteVoicePar[nvoice].FMVolume =
1267                     (expf(adpars->VoicePar[nvoice].PFMVolume / 127.0f
1268                           * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
1269                 break;
1270 
1271             default:
1272                 if (fmvoldamp > 1.0f)
1273                     fmvoldamp = 1.0f;
1274                 NoteVoicePar[nvoice].FMVolume =
1275                     adpars->VoicePar[nvoice].PFMVolume / 127.0f * fmvoldamp;
1276                 break;
1277         }
1278 
1279         // Voice's modulator velocity sensing
1280         NoteVoicePar[nvoice].FMVolume *=
1281             velF(velocity, adpars->VoicePar[nvoice].PFMVelocityScaleFunction);
1282 
1283         // Voice Amplitude Parameters Init
1284         if (adpars->VoicePar[nvoice].PVolume == 0)
1285             NoteVoicePar[nvoice].Volume = 0.0f;
1286         else
1287             NoteVoicePar[nvoice].Volume =
1288                 decibel<-60>(1.0f - adpars->VoicePar[nvoice].PVolume / 127.0f)        // -60 dB .. 0 dB
1289                 * velF(velocity, adpars->VoicePar[nvoice].PAmpVelocityScaleFunction); // velocity
1290 
1291         if (adpars->VoicePar[nvoice].PVolumeminus)
1292             NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume;
1293 
1294         int unison = unison_size[nvoice];
1295 
1296         if (subVoiceNumber == -1) {
1297             int vc = nvoice;
1298             if (adpars->VoicePar[nvoice].Pextoscil != -1)
1299                 vc = adpars->VoicePar[nvoice].Pextoscil;
1300             adpars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
1301                                                getVoiceBaseFreq(nvoice),
1302                                                adpars->VoicePar[nvoice].Presonance);
1303 
1304             // I store the first elements to the last position for speedups
1305             for (int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
1306                 NoteVoicePar[nvoice].OscilSmp[synth->oscilsize + i] = NoteVoicePar[nvoice].OscilSmp[i];
1307 
1308         }
1309 
1310         int new_phase_offset = (int)((adpars->VoicePar[nvoice].Poscilphase - 64.0f)
1311                                     / 128.0f * synth->oscilsize + synth->oscilsize * 4);
1312         int phase_offset_diff = new_phase_offset - NoteVoicePar[nvoice].phase_offset;
1313         for (int k = 0; k < unison; ++k) {
1314             oscposhi[nvoice][k] = (oscposhi[nvoice][k] + phase_offset_diff) % synth->oscilsize;
1315             if (oscposhi[nvoice][k] < 0)
1316                 // This is necessary, because C '%' operator does not always
1317                 // return a positive result.
1318                 oscposhi[nvoice][k] += synth->oscilsize;
1319         }
1320         NoteVoicePar[nvoice].phase_offset = new_phase_offset;
1321 
1322         if (NoteVoicePar[nvoice].FMEnabled != NONE
1323             && NoteVoicePar[nvoice].FMVoice < 0)
1324         {
1325             if (subVoiceNumber == -1) {
1326                 int vc = nvoice;
1327                 if (adpars->VoicePar[nvoice].PextFMoscil != -1)
1328                     vc = adpars->VoicePar[nvoice].PextFMoscil;
1329 
1330                 float freqtmp = 1.0f;
1331                 if (adpars->VoicePar[vc].POscilFM->Padaptiveharmonics != 0
1332                     || (NoteVoicePar[nvoice].FMEnabled == MORPH)
1333                     || (NoteVoicePar[nvoice].FMEnabled == RING_MOD))
1334                     freqtmp = getFMVoiceBaseFreq(nvoice);
1335 
1336                 adpars->VoicePar[vc].FMSmp->
1337                          get(NoteVoicePar[nvoice].FMSmp, freqtmp);
1338 
1339                 for (int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
1340                     NoteVoicePar[nvoice].FMSmp[synth->oscilsize + i] =
1341                         NoteVoicePar[nvoice].FMSmp[i];
1342             }
1343 
1344             int new_FMphase_offset = (int)((adpars->VoicePar[nvoice].PFMoscilphase - 64.0f)
1345                                          / 128.0f * synth->oscilsize_f
1346                                          + synth->oscilsize_f * 4.0f);
1347             int FMphase_offset_diff = new_FMphase_offset - NoteVoicePar[nvoice].FMphase_offset;
1348             for (int k = 0; k < unison_size[nvoice]; ++k)
1349             {
1350                 oscposhiFM[nvoice][k] += FMphase_offset_diff;
1351                 oscposhiFM[nvoice][k] %= synth->oscilsize;
1352                 if (oscposhiFM[nvoice][k] < 0)
1353                     // This is necessary, because C '%' operator does not always
1354                     // return a positive result.
1355                     oscposhiFM[nvoice][k] += synth->oscilsize;
1356             }
1357             NoteVoicePar[nvoice].FMphase_offset = new_FMphase_offset;
1358         }
1359 
1360         bool is_pwm = NoteVoicePar[nvoice].FMEnabled == PW_MOD;
1361 
1362         unison_stereo_spread[nvoice] =
1363             adpars->VoicePar[nvoice].Unison_stereo_spread / 127.0f;
1364         float unison_spread = adpars->getUnisonFrequencySpreadCents(nvoice);
1365         float unison_real_spread = power<2>((unison_spread * 0.5f) / 1200.0f);
1366         float unison_vibratto_a = adpars->VoicePar[nvoice].Unison_vibratto / 127.0f;                                  //0.0 .. 1.0
1367 
1368         int true_unison = unison >> is_pwm;
1369         switch (true_unison)
1370         {
1371             case 1: // if no unison, set the subvoice to the default note
1372                 unison_base_freq_rap[nvoice][0] = 1.0f;
1373                 break;
1374 
1375             case 2:  // unison for 2 subvoices
1376                 {
1377                     unison_base_freq_rap[nvoice][0] = 1.0f / unison_real_spread;
1378                     unison_base_freq_rap[nvoice][1] = unison_real_spread;
1379                 }
1380                 break;
1381 
1382             default: // unison for more than 2 subvoices
1383                 {
1384                     float unison_values[unison];
1385                     float min = -1e-6f, max = 1e-6f;
1386                     for (int k = 0; k < true_unison; ++k)
1387                     {
1388                         float step = (k / (float) (true_unison - 1)) * 2.0f - 1.0f;  //this makes the unison spread more uniform
1389                         float val  = step + (paramRNG.numRandom() * 2.0f - 1.0f) / (true_unison - 1);
1390                         unison_values[k] = val;
1391                         if (val > max)
1392                             max = val;
1393                         if (val < min)
1394                             min = val;
1395                     }
1396                     float diff = max - min;
1397                     for (int k = 0; k < true_unison; ++k)
1398                     {
1399                         unison_values[k] =
1400                             (unison_values[k] - (max + min) * 0.5f) / diff;
1401                             // the lowest value will be -1 and the highest will be 1
1402                         unison_base_freq_rap[nvoice][k] =
1403                             power<2>((unison_spread * unison_values[k]) / 1200.0f);
1404                     }
1405                 }
1406                 break;
1407         }
1408         if (is_pwm)
1409             for (int i = true_unison - 1; i >= 0; i--)
1410             {
1411                 unison_base_freq_rap[nvoice][2*i + 1] =
1412                     unison_base_freq_rap[nvoice][i];
1413                 unison_base_freq_rap[nvoice][2*i] =
1414                     unison_base_freq_rap[nvoice][i];
1415             }
1416 
1417         // unison vibrattos
1418         if (true_unison > 1)
1419         {
1420             for (int k = 0; k < unison; ++k) // reduce the frequency difference
1421                                              // for larger vibrattos
1422                 unison_base_freq_rap[nvoice][k] =
1423                     1.0f + (unison_base_freq_rap[nvoice][k] - 1.0f)
1424                     * (1.0f - unison_vibratto_a);
1425 
1426             unison_vibratto[nvoice].amplitude = (unison_real_spread - 1.0f) * unison_vibratto_a;
1427 
1428             float increments_per_second = 1 / synth->fixed_sample_step_f;
1429             const float vib_speed = adpars->VoicePar[nvoice].Unison_vibratto_speed / 127.0f;
1430             float vibratto_base_period  = 0.25f * power<2>((1.0f - vib_speed) * 4.0f);
1431             for (int k = 0; k < unison; ++k)
1432             {
1433                 // make period to vary randomly from 50% to 200% vibratto base period
1434                 float vibratto_period = vibratto_base_period * power<2>(paramRNG.numRandom() * 2.0f - 1.0f);
1435                 float m = 4.0f / (vibratto_period * increments_per_second);
1436                 if (unison_vibratto[nvoice].step[k] < 0.0f)
1437                     m = -m;
1438                 unison_vibratto[nvoice].step[k] = m;
1439 
1440                 if (is_pwm)
1441                 {
1442                     // Set the next position the same as this one.
1443                     unison_vibratto[nvoice].step[k+1] =
1444                         unison_vibratto[nvoice].step[k];
1445                     ++k; // Skip an iteration.
1446                 }
1447             }
1448         }
1449         else // No vibrato for a single voice
1450         {
1451             unison_vibratto[nvoice].step[0] = 0.0f;
1452             unison_vibratto[nvoice].amplitude = 0.0f;
1453 
1454             if (is_pwm)
1455             {
1456                 unison_vibratto[nvoice].step[1]     = 0.0f;
1457             }
1458         }
1459 
1460         // phase invert for unison
1461         unison_invert_phase[nvoice][0] = false;
1462         if (unison != 1)
1463         {
1464             int inv = adpars->VoicePar[nvoice].Unison_invert_phase;
1465             switch(inv)
1466             {
1467                 case 0:
1468                     for (int k = 0; k < unison; ++k)
1469                         unison_invert_phase[nvoice][k] = false;
1470                     break;
1471 
1472                 case 1:
1473                     for (int k = 0; k < unison; ++k)
1474                         unison_invert_phase[nvoice][k] = _SYS_::F2B(paramRNG.numRandom());
1475                     break;
1476 
1477                 default:
1478                     for (int k = 0; k < unison; ++k)
1479                         unison_invert_phase[nvoice][k] = (k % inv == 0) ? true : false;
1480                     break;
1481             }
1482         }
1483     }
1484 }
1485 
1486 // Get Voice's Modullator base frequency
getFMVoiceBaseFreq(int nvoice)1487 float ADnote::getFMVoiceBaseFreq(int nvoice)
1488 {
1489     float detune = NoteVoicePar[nvoice].FMDetune / 100.0f;
1490     float freq;
1491 
1492     if (NoteVoicePar[nvoice].FMFreqFixed)
1493         return 440.0f * power<2>(detune / 12.0f);
1494 
1495     if (NoteVoicePar[nvoice].FMDetuneFromBaseOsc)
1496         freq = getVoiceBaseFreq(nvoice);
1497     else {
1498         freq = basefreq;
1499         // To avoid applying global detuning twice: Only detune in main voice
1500         if (subVoiceNumber == -1)
1501             detune += NoteGlobalPar.Detune / 100.0f;
1502     }
1503 
1504     return freq * power<2>(detune / 12.0f);
1505 }
1506 
1507 
1508 // Computes the relative frequency of each unison voice and it's vibratto
1509 // This must be called before setfreq* functions
computeUnisonFreqRap(int nvoice)1510 void ADnote::computeUnisonFreqRap(int nvoice)
1511 {
1512     if (unison_size[nvoice] == 1) // no unison
1513     {
1514         unison_freq_rap[nvoice][0] = 1.0f;
1515         return;
1516     }
1517     float relbw = ctl->bandwidth.relbw * bandwidthDetuneMultiplier;
1518     for (int k = 0; k < unison_size[nvoice]; ++k)
1519     {
1520         float pos  = unison_vibratto[nvoice].position[k];
1521         float step = unison_vibratto[nvoice].step[k];
1522         pos += step;
1523         if (pos <= -1.0f)
1524         {
1525             pos  = -1.0f;
1526             step = -step;
1527         }
1528         else if (pos >= 1.0f)
1529         {
1530             pos  = 1.0f;
1531             step = -step;
1532         }
1533         float vibratto_val =
1534             (pos - 0.333333333f * pos * pos * pos) * 1.5f; // make the vibratto lfo smoother
1535         unison_freq_rap[nvoice][k] =
1536             1.0f + ((unison_base_freq_rap[nvoice][k] - 1.0f)
1537             + vibratto_val * unison_vibratto[nvoice].amplitude) * relbw;
1538 
1539         unison_vibratto[nvoice].position[k] = pos;
1540         step = unison_vibratto[nvoice].step[k] = step;
1541     }
1542 }
1543 
1544 
1545 // Computes the frequency of an oscillator
setfreq(int nvoice,float in_freq,float pitchdetune)1546 void ADnote::setfreq(int nvoice, float in_freq, float pitchdetune)
1547 {
1548     for (int k = 0; k < unison_size[nvoice]; ++k)
1549     {
1550         float detunefactor = unison_freq_rap[nvoice][k] * unisonDetuneFactorFromParent;
1551         float freq  = fabsf(in_freq) * detunefactor;
1552         if (subVoice[nvoice] != NULL) {
1553             subVoice[nvoice][k]->setPitchDetuneFromParent(pitchdetune);
1554             subVoice[nvoice][k]->setUnisonDetuneFromParent(detunefactor);
1555         }
1556         float speed = freq * synth->oscil_sample_step_f;
1557         if (isgreater(speed, synth->oscilsize_f))
1558             speed = synth->oscilsize_f;
1559         int tmp = int(speed);
1560         oscfreqhi[nvoice][k] = tmp;
1561         oscfreqlo[nvoice][k] = speed - float(tmp);
1562     }
1563 }
1564 
1565 
1566 // Computes the frequency of an modulator oscillator
setfreqFM(int nvoice,float in_freq,float pitchdetune)1567 void ADnote::setfreqFM(int nvoice, float in_freq, float pitchdetune)
1568 {
1569     for (int k = 0; k < unison_size[nvoice]; ++k)
1570     {
1571         float detunefactor = unisonDetuneFactorFromParent;
1572         if (NoteVoicePar[nvoice].FMDetuneFromBaseOsc)
1573             detunefactor *= unison_freq_rap[nvoice][k];
1574         float freq = fabsf(in_freq) * detunefactor;
1575         if (subFMVoice[nvoice] != NULL) {
1576             subFMVoice[nvoice][k]->setPitchDetuneFromParent(pitchdetune);
1577             subFMVoice[nvoice][k]->setUnisonDetuneFromParent(detunefactor);
1578         }
1579         float speed = freq * synth->oscil_sample_step_f;
1580         if (isgreater(speed, synth->oscilsize_f))
1581             speed = synth->oscilsize_f;
1582         int tmp = int(speed);
1583         oscfreqhiFM[nvoice][k] = tmp;
1584         oscfreqloFM[nvoice][k] = speed - float(tmp);
1585     }
1586 }
1587 
1588 
1589 // Get Voice base frequency
getVoiceBaseFreq(int nvoice)1590 float ADnote::getVoiceBaseFreq(int nvoice)
1591 {
1592     float detune =
1593         NoteVoicePar[nvoice].Detune / 100.0f + NoteVoicePar[nvoice].FineDetune /
1594         100.0f * ctl->bandwidth.relbw * bandwidthDetuneMultiplier;
1595 
1596     // To avoid applying global detuning twice: Only detune in main voice
1597     if (subVoiceNumber == -1)
1598         detune += NoteGlobalPar.Detune / 100.0f;
1599 
1600     if (!NoteVoicePar[nvoice].fixedfreq)
1601         return basefreq * power<2>(detune / 12.0f);
1602     else // fixed freq is enabled
1603     {
1604         float fixedfreq;
1605         if (subVoiceNumber != -1)
1606             // Fixed frequency is not used in sub voices. We get the basefreq
1607             // from the parent.
1608             fixedfreq = basefreq;
1609         else
1610             fixedfreq = 440.0f;
1611         int fixedfreqET = NoteVoicePar[nvoice].fixedfreqET;
1612         if (fixedfreqET)
1613         {   // if the frequency varies according the keyboard note
1614             float tmp = (midinote - 69.0f) / 12.0f * (power<2>((fixedfreqET - 1) / 63.0f) - 1.0f);
1615             if (fixedfreqET <= 64)
1616                 fixedfreq *= power<2>(tmp);
1617             else
1618                 fixedfreq *= power<3>(tmp);
1619         }
1620         return fixedfreq * power<2>(detune / 12.0f);
1621     }
1622 }
1623 
1624 
1625 // Computes all the parameters for each tick
computeWorkingParameters(void)1626 void ADnote::computeWorkingParameters(void)
1627 {
1628     float filterCenterPitch =
1629         adpars->GlobalPar.GlobalFilter->getfreq() // center freq
1630         + adpars->GlobalPar.PFilterVelocityScale / 127.0f * 6.0f
1631         * (velF(velocity, adpars->GlobalPar.PFilterVelocityScaleFunction) - 1);
1632 
1633     float filterQ = adpars->GlobalPar.GlobalFilter->getq();
1634     float filterFreqTracking =
1635         adpars->GlobalPar.GlobalFilter->getfreqtracking(basefreq);
1636 
1637     float filterpitch, filterfreq;
1638     float globalpitch = 0.01f * (NoteGlobalPar.FreqEnvelope->envout()
1639                        + NoteGlobalPar.FreqLfo->lfoout() * ctl->modwheel.relmod);
1640     globaloldamplitude = globalnewamplitude;
1641     globalnewamplitude = NoteGlobalPar.Volume
1642                          * NoteGlobalPar.AmpEnvelope->envout_dB()
1643                          * NoteGlobalPar.AmpLfo->amplfoout();
1644     float globalfilterpitch = NoteGlobalPar.FilterEnvelope->envout()
1645                               + NoteGlobalPar.FilterLfo->lfoout()
1646                               + filterCenterPitch;
1647 
1648     float tmpfilterfreq = globalfilterpitch + ctl->filtercutoff.relfreq
1649           + filterFreqTracking;
1650 
1651     tmpfilterfreq = NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq);
1652     float globalfilterq = filterQ * ctl->filterq.relq;
1653     NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq, globalfilterq);
1654     if (stereo)
1655         NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq, globalfilterq);
1656 
1657     // compute the portamento, if it is used by this note
1658     float portamentofreqrap = 1.0f;
1659     if (portamento) // this voice use portamento
1660     {
1661         portamentofreqrap = ctl->portamento.freqrap;
1662         if (!ctl->portamento.used) // the portamento has finished
1663             portamento = 0;        // this note is no longer "portamented"
1664 
1665     }
1666 
1667     // compute parameters for all voices
1668     for (int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
1669     {
1670         if (!NoteVoicePar[nvoice].Enabled)
1671             continue;
1672         NoteVoicePar[nvoice].DelayTicks -= 1;
1673         if (NoteVoicePar[nvoice].DelayTicks > 0)
1674             continue;
1675 
1676         computeUnisonFreqRap(nvoice);
1677 
1678         // Voice Amplitude
1679         oldamplitude[nvoice] = newamplitude[nvoice];
1680         newamplitude[nvoice] = 1.0f;
1681 
1682         if (NoteVoicePar[nvoice].AmpEnvelope != NULL)
1683             newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
1684 
1685         if (NoteVoicePar[nvoice].AmpLfo != NULL)
1686             newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout();
1687 
1688         // Voice Filter
1689         if (NoteVoicePar[nvoice].VoiceFilterL != NULL)
1690         {
1691             filterpitch =
1692                 adpars->VoicePar[nvoice].VoiceFilter->getfreq()
1693                 + adpars->VoicePar[nvoice].PFilterVelocityScale
1694                 / 127.0f * 6.0f       //velocity sensing
1695                 * (velF(velocity,
1696                         adpars->VoicePar[nvoice].PFilterVelocityScaleFunction) - 1);
1697             filterQ = adpars->VoicePar[nvoice].VoiceFilter->getq();
1698             if (NoteVoicePar[nvoice].FilterEnvelope != NULL)
1699                 filterpitch += NoteVoicePar[nvoice].FilterEnvelope->envout();
1700             if (NoteVoicePar[nvoice].FilterLfo != NULL)
1701                 filterpitch += NoteVoicePar[nvoice].FilterLfo->lfoout();
1702             filterfreq = filterpitch + adpars->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq);
1703             filterfreq = NoteVoicePar[nvoice].VoiceFilterL->getrealfreq(filterfreq);
1704             NoteVoicePar[nvoice].VoiceFilterL->setfreq_and_q(filterfreq, filterQ);
1705             if (stereo && NoteVoicePar[nvoice].VoiceFilterR)
1706                 NoteVoicePar[nvoice].VoiceFilterR->setfreq_and_q(filterfreq, filterQ);
1707 
1708         }
1709         if (!NoteVoicePar[nvoice].noisetype) // voice is not noise
1710         {
1711             // Voice Frequency
1712             float basevoicepitch = 0.0f;
1713             basevoicepitch += detuneFromParent;
1714 
1715             basevoicepitch += 12.0f * NoteVoicePar[nvoice].BendAdjust *
1716                 log2f(ctl->pitchwheel.relfreq); //change the frequency by the controller
1717 
1718             float voicepitch = basevoicepitch;
1719             if (NoteVoicePar[nvoice].FreqLfo != NULL)
1720             {
1721                 voicepitch += NoteVoicePar[nvoice].FreqLfo->lfoout() / 100.0f
1722                               * ctl->bandwidth.relbw;
1723             }
1724 
1725             if (NoteVoicePar[nvoice].FreqEnvelope != NULL)
1726             {
1727                 voicepitch += NoteVoicePar[nvoice].FreqEnvelope->envout() / 100.0f;
1728             }
1729 
1730             float nonoffsetfreq = getVoiceBaseFreq(nvoice)
1731                               * power<2>((voicepitch + globalpitch) / 12.0f);
1732             nonoffsetfreq *= portamentofreqrap;
1733             float voicefreq = nonoffsetfreq + NoteVoicePar[nvoice].OffsetHz;
1734             voicepitch += log2f(voicefreq / nonoffsetfreq) * 12.0f;
1735             setfreq(nvoice, voicefreq, voicepitch);
1736 
1737             // Modulator
1738             if (NoteVoicePar[nvoice].FMEnabled != NONE)
1739             {
1740                 float FMpitch;
1741                 if (NoteVoicePar[nvoice].FMFreqFixed)
1742                     FMpitch = 0.0f;
1743                 else if (NoteVoicePar[nvoice].FMDetuneFromBaseOsc)
1744                     FMpitch = voicepitch;
1745                 else
1746                     FMpitch = basevoicepitch;
1747 
1748                 float FMrelativepitch = 0.0f;
1749                 if (NoteVoicePar[nvoice].FMFreqEnvelope != NULL) {
1750                     FMrelativepitch +=
1751                         NoteVoicePar[nvoice].FMFreqEnvelope->envout() / 100.0f;
1752                     FMpitch += FMrelativepitch;
1753                     // Do not add any more adjustments to FMpitch after
1754                     // this. The rest of FMrelativepitch has already been
1755                     // accounted for in our sub voices when we created them,
1756                     // using getFMVoiceBaseFreq().
1757                 }
1758 
1759                 float FMfreq;
1760                 if (NoteVoicePar[nvoice].FMFreqFixed) {
1761                     // Apply FM detuning since base frequency is 440Hz.
1762                     FMrelativepitch += NoteVoicePar[nvoice].FMDetune / 100.0f;
1763                     FMfreq = power<2>(FMrelativepitch / 12.0f) * 440.0f;
1764                 } else if (NoteVoicePar[nvoice].FMDetuneFromBaseOsc) {
1765                     // Apply FM detuning since base frequency is from main voice.
1766                     FMrelativepitch += NoteVoicePar[nvoice].FMDetune / 100.0f;
1767                     FMfreq = power<2>(FMrelativepitch / 12.0f) * voicefreq;
1768                 } else {
1769                     // No need to apply FM detuning, since getFMVoiceBaseFreq()
1770                     // takes it into account.
1771                     FMfreq = getFMVoiceBaseFreq(nvoice) *
1772                         power<2>((basevoicepitch + globalpitch + FMrelativepitch) / 12.0f);
1773                     FMfreq *= portamentofreqrap;
1774                 }
1775                 setfreqFM(nvoice, FMfreq, FMpitch);
1776                 FMoldamplitude[nvoice] = FMnewamplitude[nvoice];
1777                 FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume * ctl->fmamp.relamp;
1778                 if (NoteVoicePar[nvoice].FMAmpEnvelope != NULL)
1779                     FMnewamplitude[nvoice] *= NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
1780             }
1781         }
1782     }
1783     time += synth->sent_buffersize_f / synth->samplerate_f;
1784 }
1785 
1786 
1787 // Fadein in a way that removes clicks but keep sound "punchy"
fadein(float * smps)1788 void ADnote::fadein(float *smps)
1789 {
1790     int zerocrossings = 0;
1791     for (int i = 1; i < synth->sent_buffersize; ++i)
1792         if (smps[i - 1] < 0.0f && smps[i] > 0.0f)
1793             zerocrossings++; // this is only the positive crossings
1794 
1795     float tmp = (synth->sent_buffersize - 1.0f) / (zerocrossings + 1) / 3.0f;
1796     if (tmp < 8.0f)
1797         tmp = 8.0f;
1798     tmp *= NoteGlobalPar.Fadein_adjustment;
1799 
1800     int fadein = int(tmp); // how many samples is the fade-in
1801     if (fadein < 8)
1802         fadein = 8;
1803     if (fadein > synth->sent_buffersize)
1804         fadein = synth->sent_buffersize;
1805     for (int i = 0; i < fadein; ++i) // fade-in
1806     {
1807         float tmp = 0.5f - cosf((float)i / (float) fadein * PI) * 0.5f;
1808         smps[i] *= tmp;
1809     }
1810 }
1811 
1812 
1813 // ported from, zynaddubfx 2.4.4
1814 
1815 /*
1816  * Computes the Oscillator (Without Modulation) - LinearInterpolation
1817  */
1818 
1819 /* As the code here is a bit odd due to optimization, here is what happens
1820  * First the current position and frequency are retrieved from the running
1821  * state. These are broken up into high and low portions to indicate how many
1822  * samples are skipped in one step and how many fractional samples are skipped.
1823  * Outside of this method the fractional samples are just handled with floating
1824  * point code, but that's a bit slower than it needs to be. In this code the low
1825  * portions are known to exist between 0.0 and 1.0 and it is known that they are
1826  * stored in single precision floating point IEEE numbers. This implies that
1827  * a maximum of 24 bits are significant. The below code does your standard
1828  * linear interpolation that you'll see throughout this codebase, but by
1829  * sticking to integers for tracking the overflow of the low portion, around 15%
1830  * of the execution time was shaved off in the ADnote test.
1831  */
computeVoiceOscillatorLinearInterpolation(int nvoice)1832 inline void ADnote::computeVoiceOscillatorLinearInterpolation(int nvoice)
1833 {
1834     for (int k = 0; k < unison_size[nvoice]; ++k)
1835     {
1836         int    poshi  = oscposhi[nvoice][k];
1837         int    poslo  = oscposlo[nvoice][k] * (1<<24);
1838         int    freqhi = oscfreqhi[nvoice][k];
1839         int    freqlo = oscfreqlo[nvoice][k] * (1<<24);
1840         float *smps   = NoteVoicePar[nvoice].OscilSmp;
1841         float *tw     = tmpwave_unison[k];
1842         assert(oscfreqlo[nvoice][k] < 1.0f);
1843         for (int i = 0; i < synth->sent_buffersize; ++i)
1844         {
1845             tw[i]  = (smps[poshi] * ((1<<24) - poslo) + smps[poshi + 1] * poslo)/(1.0f*(1<<24));
1846             poslo += freqlo;
1847             poshi += freqhi + (poslo>>24);
1848             poslo &= 0xffffff;
1849             poshi &= synth->oscilsize - 1;
1850         }
1851         oscposhi[nvoice][k] = poshi;
1852         oscposlo[nvoice][k] = poslo/(1.0f*(1<<24));
1853     }
1854 }
1855 
1856 // end of port
1857 
1858 // Applies the Oscillator (Morphing)
applyVoiceOscillatorMorph(int nvoice)1859 void ADnote::applyVoiceOscillatorMorph(int nvoice)
1860 {
1861     if (isgreater(FMnewamplitude[nvoice], 1.0f))
1862         FMnewamplitude[nvoice] = 1.0f;
1863     if (isgreater(FMoldamplitude[nvoice], 1.0f))
1864         FMoldamplitude[nvoice] = 1.0f;
1865 
1866     for (int k = 0; k < unison_size[nvoice]; ++k)
1867     {
1868         float *tw = tmpwave_unison[k];
1869         float *mod = tmpmod_unison[k];
1870 
1871         for (int i = 0; i < synth->sent_buffersize; ++i)
1872         {
1873             float amp = interpolateAmplitude(FMoldamplitude[nvoice],
1874                                        FMnewamplitude[nvoice], i,
1875                                        synth->sent_buffersize);
1876             tw[i] = (tw[i] * (1.0f - amp)) + amp * mod[i];
1877         }
1878     }
1879 }
1880 
1881 
1882 // Applies the Oscillator (Ring Modulation)
applyVoiceOscillatorRingModulation(int nvoice)1883 void ADnote::applyVoiceOscillatorRingModulation(int nvoice)
1884 {
1885     float amp;
1886     bool isSide = NoteVoicePar[nvoice].FMringToSide;
1887     if (isgreater(FMnewamplitude[nvoice], 1.0f))
1888         FMnewamplitude[nvoice] = 1.0f;
1889     if (isgreater(FMoldamplitude[nvoice], 1.0f))
1890         FMoldamplitude[nvoice] = 1.0f;
1891     for (int k = 0; k < unison_size[nvoice]; ++k)
1892     {
1893         float *tw = tmpwave_unison[k];
1894         float *mod = tmpmod_unison[k];
1895 
1896         for (int i = 0; i < synth->sent_buffersize; ++i)
1897         {
1898             amp = interpolateAmplitude(FMoldamplitude[nvoice],
1899                                        FMnewamplitude[nvoice], i,
1900                                        synth->sent_buffersize);
1901             if (isSide) // sidebands
1902                 tw[i] *= (mod[i] * amp * 2);
1903                 //tw[i] *= (mod[i] + 1.0f) * 0.5f * amp + (1.0f - amp);
1904             else // ring
1905                 tw[i] *= mod[i] * amp + (1.0f - amp);
1906         }
1907     }
1908 }
1909 
1910 
1911 // Computes the Modulator
computeVoiceModulator(int nvoice,int FMmode)1912 void ADnote::computeVoiceModulator(int nvoice, int FMmode)
1913 {
1914     if (subFMVoice[nvoice] != NULL) {
1915         int subVoiceNumber = NoteVoicePar[nvoice].FMVoice;
1916         for (int k = 0; k < unison_size[nvoice]; ++k) {
1917             // Sub voices use VoiceOut, so just pass NULL.
1918             subFMVoice[nvoice][k]->noteout(NULL, NULL);
1919             const float *smps = subFMVoice[nvoice][k]->NoteVoicePar[subVoiceNumber].VoiceOut;
1920             // For historical/compatibility reasons we do not reduce volume here
1921             // if are using stereo. See same section in computeVoiceOscillator.
1922             memcpy(tmpmod_unison[k], smps, synth->bufferbytes);
1923         }
1924     }
1925     else if (parentFMmod != NULL) {
1926         if (NoteVoicePar[nvoice].FMEnabled == FREQ_MOD) {
1927             computeVoiceModulatorForFMFrequencyModulation(nvoice);
1928         } else {
1929             computeVoiceModulatorFrequencyModulation(nvoice, FMmode);
1930         }
1931     } else {
1932         computeVoiceModulatorLinearInterpolation(nvoice);
1933     }
1934 
1935     if (freqbasedmod[nvoice])
1936     {
1937         applyAmplitudeOnVoiceModulator(nvoice);
1938         normalizeVoiceModulatorFrequencyModulation(nvoice, FMmode);
1939 
1940         // Ring and morph modulation do not need normalization, and they take
1941         // amplitude into account themselves.
1942     }
1943 }
1944 
applyAmplitudeOnVoiceModulator(int nvoice)1945 void ADnote::applyAmplitudeOnVoiceModulator(int nvoice)
1946 {
1947    // Amplitude interpolation
1948     if (aboveAmplitudeThreshold(FMoldamplitude[nvoice], FMnewamplitude[nvoice]))
1949     {
1950         for (int k = 0; k < unison_size[nvoice]; ++k)
1951         {
1952             float *tw = tmpmod_unison[k];
1953             for (int i = 0; i < synth->sent_buffersize; ++i)
1954                 tw[i] *= interpolateAmplitude(FMoldamplitude[nvoice],
1955                                               FMnewamplitude[nvoice], i,
1956                                               synth->sent_buffersize);
1957         }
1958     }
1959     else
1960     {
1961         for (int k = 0; k < unison_size[nvoice]; ++k)
1962         {
1963             float *tw = tmpmod_unison[k];
1964             for (int i = 0; i < synth->sent_buffersize; ++i)
1965                 tw[i] *= FMnewamplitude[nvoice];
1966         }
1967     }
1968 }
1969 
1970 // Normalize the modulator for phase/frequency modulation
normalizeVoiceModulatorFrequencyModulation(int nvoice,int FMmode)1971 void ADnote::normalizeVoiceModulatorFrequencyModulation(int nvoice, int FMmode)
1972 {
1973     if (FMmode == PW_MOD) { // PWM modulation
1974         for (int k = 1; k < unison_size[nvoice]; k += 2) {
1975             float *tw = tmpmod_unison[k];
1976             for (int i = 1; i < synth->sent_buffersize; ++i)
1977                 tw[i] = -tw[i];
1978         }
1979     }
1980 
1981     // normalize: makes all sample-rates, oscil_sizes to produce same sound
1982     if (FMmode == FREQ_MOD) // Frequency modulation
1983     {
1984         for (int k = 0; k < unison_size[nvoice]; ++k)
1985         {
1986             float *tw = tmpmod_unison[k];
1987             float  fmold = FMoldsmp[nvoice][k];
1988             for (int i = 0; i < synth->sent_buffersize; ++i)
1989             {
1990                 fmold = fmold + tw[i] * synth->oscil_norm_factor_fm;
1991                 tw[i] = fmold;
1992             }
1993             FMoldsmp[nvoice][k] = fmold;
1994         }
1995     }
1996     else  // Phase or PWM modulation
1997     {
1998         for (int k = 0; k < unison_size[nvoice]; ++k)
1999         {
2000             float *tw = tmpmod_unison[k];
2001             for (int i = 0; i < synth->sent_buffersize; ++i)
2002                 tw[i] *= synth->oscil_norm_factor_pm;
2003         }
2004     }
2005 
2006     if (parentFMmod != NULL) {
2007         // This is a sub voice. Mix our frequency modulation with the
2008         // parent modulation.
2009         float *tmp = parentFMmod;
2010         for (int k = 0; k < unison_size[nvoice]; ++k) {
2011             float *tw = tmpmod_unison[k];
2012             for (int i = 0; i < synth->sent_buffersize; ++i)
2013                 tw[i] += tmp[i];
2014         }
2015     }
2016 }
2017 
2018 // Render the modulator with linear interpolation, no modulation on it
computeVoiceModulatorLinearInterpolation(int nvoice)2019 void ADnote::computeVoiceModulatorLinearInterpolation(int nvoice)
2020 {
2021     // Compute the modulator and store it in tmpmod_unison[][]
2022     for (int k = 0; k < unison_size[nvoice]; ++k)
2023     {
2024         int poshiFM = oscposhiFM[nvoice][k];
2025         float posloFM  = oscposloFM[nvoice][k];
2026         int freqhiFM = oscfreqhiFM[nvoice][k];
2027         float freqloFM = oscfreqloFM[nvoice][k];
2028         float *tw = tmpmod_unison[k];
2029         const float *smps = NoteVoicePar[nvoice].FMSmp;
2030 
2031         for (int i = 0; i < synth->sent_buffersize; ++i)
2032         {
2033             tw[i] = (smps[poshiFM] * (1 - posloFM)
2034                      + smps[poshiFM + 1] * posloFM) / (1.0f);
2035 
2036             posloFM += freqloFM;
2037             if (posloFM >= 1.0f)
2038             {
2039                 posloFM -= 1.0f;
2040                 poshiFM++;
2041             }
2042             poshiFM += freqhiFM;
2043             poshiFM &= synth->oscilsize - 1;
2044         }
2045         oscposhiFM[nvoice][k] = poshiFM;
2046         oscposloFM[nvoice][k] = posloFM;
2047     }
2048 }
2049 
2050 // Computes the Modulator (Phase Modulation or Frequency Modulation from parent voice)
computeVoiceModulatorFrequencyModulation(int nvoice,int FMmode)2051 void ADnote::computeVoiceModulatorFrequencyModulation(int nvoice, int FMmode)
2052 {
2053     // do the modulation using parent's modulator, onto a new modulator
2054     for (int k = 0; k < unison_size[nvoice]; ++k)
2055     {
2056         float *tw = tmpmod_unison[k];
2057         int poshiFM = oscposhiFM[nvoice][k];
2058         float posloFM = oscposloFM[nvoice][k];
2059         int freqhiFM = oscfreqhiFM[nvoice][k];
2060         float freqloFM = oscfreqloFM[nvoice][k];
2061         // When we have parent modulation, we want to maintain the same
2062         // sound. However, if the carrier and modulator are very far apart in
2063         // frequency, then the modulation will affect them very differently,
2064         // since the phase difference is linear, not logarithmic. Compensate for
2065         // this by favoring the carrier, and adjust the rate of modulation
2066         // logarithmically, relative to this.
2067         float oscVsFMratio = ((float)freqhiFM + freqloFM)
2068             / ((float)oscfreqhi[nvoice][k] + oscfreqlo[nvoice][k]);
2069         const float *smps = NoteVoicePar[nvoice].FMSmp;
2070 
2071         for (int i = 0; i < synth->sent_buffersize; ++i)
2072         {
2073             float pMod = parentFMmod[i] * oscVsFMratio;
2074             int FMmodfreqhi = int(pMod);
2075             float FMmodfreqlo = pMod-FMmodfreqhi;
2076             if (FMmodfreqhi < 0)
2077                 FMmodfreqlo++;
2078 
2079             // carrier, which will become the new modulator
2080             int carposhi = poshiFM + FMmodfreqhi;
2081             float carposlo = posloFM + FMmodfreqlo;
2082 
2083             if (FMmode == PW_MOD && (k & 1))
2084                 carposhi += NoteVoicePar[nvoice].phase_offset;
2085 
2086             if (carposlo >= 1.0f)
2087             {
2088                 carposhi++;
2089                 carposlo -= 1.0f;
2090             }
2091             carposhi &= (synth->oscilsize - 1);
2092 
2093             tw[i] = smps[carposhi] * (1.0f - carposlo)
2094                     + smps[carposhi + 1] * carposlo;
2095             posloFM += freqloFM;
2096             if (posloFM >= 1.0f)
2097             {
2098                 posloFM -= 1.0f;
2099                 poshiFM++;
2100             }
2101 
2102             poshiFM += freqhiFM;
2103             poshiFM &= synth->oscilsize - 1;
2104         }
2105         oscposhiFM[nvoice][k] = poshiFM;
2106         oscposloFM[nvoice][k] = posloFM;
2107     }
2108 }
2109 
computeVoiceModulatorForFMFrequencyModulation(int nvoice)2110 void ADnote::computeVoiceModulatorForFMFrequencyModulation(int nvoice)
2111 {
2112     // Here we have a tricky situation: We are generating a modulator which will
2113     // be used for FM modulation, and the modulator itself is also modulated by
2114     // a parent voice. Because FM modulation needs to be integrated (it is the
2115     // derivative function of PM modulation), we cannot modulate the modulator
2116     // in the same way as the other modulation types. Instead, we start with the
2117     // original unmodulated function, and then integrate either backwards or
2118     // forwards until we reach the phase offset from the parent modulation. To
2119     // preserve accuracy we move in exact steps of the frequency, which is what
2120     // would have happened if there was no modulation. Then we take the linear
2121     // interpolation between the two nearest samples, and use that to construct
2122     // the resulting curve.
2123     for (int k = 0; k < unison_size[nvoice]; ++k)
2124     {
2125         float *tw = tmpmod_unison[k];
2126         int poshiFM = oscposhiFM[nvoice][k];
2127         float posloFM = oscposloFM[nvoice][k];
2128         int freqhiFM = oscfreqhiFM[nvoice][k];
2129         float freqloFM = oscfreqloFM[nvoice][k];
2130         float freqFM = (float)freqhiFM + freqloFM;
2131         float oscVsFMratio = freqFM
2132             / ((float)oscfreqhi[nvoice][k] + oscfreqlo[nvoice][k]);
2133         const float *smps = NoteVoicePar[nvoice].FMSmp;
2134         float oldInterpPhase = FMFMoldInterpPhase[nvoice][k];
2135         float currentPhase = FMFMoldPhase[nvoice][k];
2136         float currentPMod = FMFMoldPMod[nvoice][k];
2137 
2138         for (int i = 0; i < synth->sent_buffersize; ++i)
2139         {
2140             float pMod = parentFMmod[i] * oscVsFMratio;
2141             while (currentPMod > pMod)
2142             {
2143                 posloFM -= freqloFM;
2144                 if (posloFM < 0.0f)
2145                 {
2146                     posloFM += 1.0f;
2147                     poshiFM--;
2148                 }
2149                 poshiFM -= freqhiFM;
2150                 poshiFM &= synth->oscilsize - 1;
2151 
2152                 currentPMod -= freqFM;
2153                 currentPhase -= smps[poshiFM] * (1.0f - posloFM)
2154                     + smps[poshiFM + 1] * posloFM;
2155             }
2156             float pModBelow = pMod - freqFM;
2157             while (currentPMod < pModBelow)
2158             {
2159                 currentPMod += freqFM;
2160                 currentPhase += smps[poshiFM] * (1.0f - posloFM)
2161                     + smps[poshiFM + 1] * posloFM;
2162 
2163                 posloFM += freqloFM;
2164                 if (posloFM >= 1.0f)
2165                 {
2166                     posloFM -= 1.0f;
2167                     poshiFM++;
2168                 }
2169                 poshiFM += freqhiFM;
2170                 poshiFM &= synth->oscilsize - 1;
2171             }
2172 
2173             float nextPhase = currentPhase
2174                 + (smps[poshiFM] * (1.0f - posloFM)
2175                    + smps[poshiFM + 1] * posloFM);
2176 
2177             posloFM += freqloFM;
2178             if (posloFM >= 1.0f)
2179             {
2180                 posloFM -= 1.0f;
2181                 poshiFM++;
2182             }
2183             poshiFM += freqhiFM;
2184             poshiFM &= synth->oscilsize - 1;
2185 
2186             float nextAmount = (pMod - currentPMod) / freqFM;
2187             float currentAmount= 1.0f - nextAmount;
2188             float interpPhase = currentPhase * currentAmount
2189                 + nextPhase * nextAmount;
2190             tw[i] = interpPhase - oldInterpPhase;
2191             oldInterpPhase = interpPhase;
2192 
2193             currentPhase = nextPhase;
2194         }
2195         oscposhiFM[nvoice][k] = poshiFM;
2196         oscposloFM[nvoice][k] = posloFM;
2197         FMFMoldPhase[nvoice][k] = currentPhase;
2198         FMFMoldPMod[nvoice][k] = currentPMod;
2199         FMFMoldInterpPhase[nvoice][k] = oldInterpPhase;
2200     }
2201 }
2202 
2203 // Computes the Oscillator (Phase Modulation or Frequency Modulation)
computeVoiceOscillatorFrequencyModulation(int nvoice)2204 void ADnote::computeVoiceOscillatorFrequencyModulation(int nvoice)
2205 {
2206     // do the modulation
2207     for (int k = 0; k < unison_size[nvoice]; ++k)
2208     {
2209         float *tw = tmpwave_unison[k];
2210         int poshi = oscposhi[nvoice][k];
2211         float poslo = oscposlo[nvoice][k];
2212         int freqhi = oscfreqhi[nvoice][k];
2213         float freqlo = oscfreqlo[nvoice][k];
2214         // If this ADnote has frequency based modulation, the modulator resides
2215         // in tmpmod_unison, otherwise it comes from the parent. If there is no
2216         // modulation at all this function should not be called.
2217         const float *mod = freqbasedmod[nvoice] ? tmpmod_unison[k] : parentFMmod;
2218 
2219         for (int i = 0; i < synth->sent_buffersize; ++i)
2220         {
2221             int FMmodfreqhi = int(mod[i]);
2222             float FMmodfreqlo = mod[i]-FMmodfreqhi;
2223             if (FMmodfreqhi < 0)
2224                 FMmodfreqlo++;
2225 
2226             // carrier
2227             int carposhi = poshi + FMmodfreqhi;
2228             float carposlo = poslo + FMmodfreqlo;
2229 
2230             if (carposlo >= 1.0f)
2231             {
2232                 carposhi++;
2233                 carposlo -= 1.0f;
2234             }
2235             carposhi &= (synth->oscilsize - 1);
2236 
2237             tw[i] = NoteVoicePar[nvoice].OscilSmp[carposhi] * (1.0f - carposlo)
2238                     + NoteVoicePar[nvoice].OscilSmp[carposhi + 1] * carposlo;
2239             poslo += freqlo;
2240             if (poslo >= 1.0f)
2241             {
2242                 poslo -= 1.0f;
2243                 poshi++;
2244             }
2245 
2246             poshi += freqhi;
2247             poshi &= synth->oscilsize - 1;
2248         }
2249         oscposhi[nvoice][k] = poshi;
2250         oscposlo[nvoice][k] = poslo;
2251     }
2252 }
2253 
computeVoiceOscillatorForFMFrequencyModulation(int nvoice)2254 void ADnote::computeVoiceOscillatorForFMFrequencyModulation(int nvoice)
2255 {
2256     // See computeVoiceModulatorForFMFrequencyModulation for details on how this works.
2257     for (int k = 0; k < unison_size[nvoice]; ++k)
2258     {
2259         float *tw = tmpwave_unison[k];
2260         int poshi = oscposhi[nvoice][k];
2261         float poslo = oscposlo[nvoice][k];
2262         int freqhi = oscfreqhi[nvoice][k];
2263         float freqlo = oscfreqlo[nvoice][k];
2264         float freq = (float)freqhi + freqlo;
2265         const float *smps = NoteVoicePar[nvoice].OscilSmp;
2266         float oldInterpPhase = oscFMoldInterpPhase[nvoice][k];
2267         float currentPhase = oscFMoldPhase[nvoice][k];
2268         float currentPMod = oscFMoldPMod[nvoice][k];
2269 
2270         for (int i = 0; i < synth->sent_buffersize; ++i)
2271         {
2272             float pMod = parentFMmod[i];
2273             while (currentPMod > pMod)
2274             {
2275                 poslo -= freqlo;
2276                 if (poslo < 0.0f)
2277                 {
2278                     poslo += 1.0f;
2279                     poshi--;
2280                 }
2281                 poshi -= freqhi;
2282                 poshi &= synth->oscilsize - 1;
2283 
2284                 currentPMod -= freq;
2285                 currentPhase -= smps[poshi] * (1.0f - poslo)
2286                     + smps[poshi + 1] * poslo;
2287             }
2288             float pModBelow = pMod - freq;
2289             while (currentPMod < pModBelow)
2290             {
2291                 currentPMod += freq;
2292                 currentPhase += smps[poshi] * (1.0f - poslo)
2293                     + smps[poshi + 1] * poslo;
2294 
2295                 poslo += freqlo;
2296                 if (poslo >= 1.0f)
2297                 {
2298                     poslo -= 1.0f;
2299                     poshi++;
2300                 }
2301                 poshi += freqhi;
2302                 poshi &= synth->oscilsize - 1;
2303             }
2304 
2305             float nextPhase = currentPhase
2306                 + (smps[poshi] * (1.0f - poslo)
2307                    + smps[poshi + 1] * poslo);
2308 
2309             poslo += freqlo;
2310             if (poslo >= 1.0f)
2311             {
2312                 poslo -= 1.0f;
2313                 poshi++;
2314             }
2315             poshi += freqhi;
2316             poshi &= synth->oscilsize - 1;
2317 
2318             float nextAmount = (pMod - currentPMod) / freq;
2319             float currentAmount= 1.0f - nextAmount;
2320             float interpPhase = currentPhase * currentAmount
2321                 + nextPhase * nextAmount;
2322             tw[i] = interpPhase - oldInterpPhase;
2323             oldInterpPhase = interpPhase;
2324 
2325             currentPhase = nextPhase;
2326         }
2327         oscposhi[nvoice][k] = poshi;
2328         oscposlo[nvoice][k] = poslo;
2329         oscFMoldPhase[nvoice][k] = currentPhase;
2330         oscFMoldPMod[nvoice][k] = currentPMod;
2331         oscFMoldInterpPhase[nvoice][k] = oldInterpPhase;
2332     }
2333 }
2334 
2335 
2336 
2337 // Computes the Noise
computeVoiceNoise(int nvoice)2338 void ADnote::computeVoiceNoise(int nvoice)
2339 {
2340     for (int k = 0; k < unison_size[nvoice]; ++k)
2341     {
2342         float *tw = tmpwave_unison[k];
2343         for (int i = 0; i < synth->sent_buffersize; ++i)
2344             tw[i] = synth->numRandom() * 2.0f - 1.0f;
2345     }
2346 }
2347 
2348 
2349 // ported from Zyn 2.5.2
ComputeVoicePinkNoise(int nvoice)2350 void ADnote::ComputeVoicePinkNoise(int nvoice)
2351 {
2352     for (int k = 0; k < unison_size[nvoice]; ++k)
2353     {
2354         float *tw = tmpwave_unison[k];
2355         float *f = &pinking[nvoice][k > 0 ? 7 : 0];
2356         for (int i = 0; i < synth->sent_buffersize; ++i)
2357         {
2358             float white = (synth->numRandom() - 0.5 ) / 4.0;
2359             f[0] = 0.99886*f[0]+white*0.0555179;
2360             f[1] = 0.99332*f[1]+white*0.0750759;
2361             f[2] = 0.96900*f[2]+white*0.1538520;
2362             f[3] = 0.86650*f[3]+white*0.3104856;
2363             f[4] = 0.55000*f[4]+white*0.5329522;
2364             f[5] = -0.7616*f[5]-white*0.0168980;
2365             tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362;
2366             f[6] = white*0.115926;
2367         }
2368     }
2369 }
2370 
computeVoiceOscillator(int nvoice)2371 void ADnote::computeVoiceOscillator(int nvoice)
2372 {
2373     if (subVoice[nvoice] != NULL) {
2374         int subVoiceNumber = NoteVoicePar[nvoice].Voice;
2375         for (int k = 0; k < unison_size[nvoice]; ++k) {
2376             // Sub voices use VoiceOut, so just pass NULL.
2377             subVoice[nvoice][k]->noteout(NULL, NULL);
2378             const float *smps = subVoice[nvoice][k]->NoteVoicePar[subVoiceNumber].VoiceOut;
2379             float *tw = tmpwave_unison[k];
2380             if (stereo) {
2381                 // Reduce volume due to stereo being combined to mono.
2382                 for (int i = 0; i < synth->buffersize; ++i) {
2383                     tw[i] = smps[i] * 0.5f;
2384                 }
2385             } else {
2386                 memcpy(tw, smps, synth->bufferbytes);
2387             }
2388         }
2389     } else {
2390         switch (NoteVoicePar[nvoice].noisetype)
2391         {
2392             case 0: //  sound
2393                 // There may be frequency modulation coming from the parent,
2394                 // even if this oscillator itself does not have it.
2395                 if (parentFMmod != NULL && forFM)
2396                     computeVoiceOscillatorForFMFrequencyModulation(nvoice);
2397                 else if (parentFMmod != NULL || freqbasedmod[nvoice])
2398                     computeVoiceOscillatorFrequencyModulation(nvoice);
2399                 else
2400                     computeVoiceOscillatorLinearInterpolation(nvoice);
2401                 break;
2402             case 1:
2403                 computeVoiceNoise(nvoice); // white noise
2404                 break;
2405             case 2:
2406                 ComputeVoicePinkNoise(nvoice); // pink noise
2407                 break;
2408             default:
2409                 ComputeVoiceSpotNoise(nvoice); // spot noise
2410                 break;
2411         }
2412     }
2413 
2414     // Apply non-frequency modulation onto rendered voice.
2415     switch(NoteVoicePar[nvoice].FMEnabled)
2416     {
2417         case MORPH:
2418             applyVoiceOscillatorMorph(nvoice);
2419             break;
2420         case RING_MOD:
2421             applyVoiceOscillatorRingModulation(nvoice);
2422             break;
2423         default:
2424             // No additional modulation.
2425             break;
2426     }
2427 }
2428 
ComputeVoiceSpotNoise(int nvoice)2429 void ADnote::ComputeVoiceSpotNoise(int nvoice)
2430 {
2431     for (int k = 0; k < unison_size[nvoice]; ++k)
2432     {
2433         float *tw = tmpwave_unison[k];
2434         for (int i = 0; i < synth->sent_buffersize; ++i)
2435         {
2436             if (Tspot <= 0)
2437             {
2438                 tw[i] = synth->numRandom() * 6.0f - 3.0f;
2439                 Tspot = (synth->randomINT() >> 24);
2440             }
2441             else
2442             {
2443                 tw[i] = 0.0f;
2444                 Tspot--;
2445             }
2446         }
2447     }
2448 }
2449 
2450 
2451 // Compute the ADnote samples, returns 0 if the note is finished
noteout(float * outl,float * outr)2452 int ADnote::noteout(float *outl, float *outr)
2453 {
2454     Config &Runtime = synth->getRuntime();
2455     float *tmpwavel = Runtime.genTmp1;
2456     float *tmpwaver = Runtime.genTmp2;
2457     float *bypassl = Runtime.genTmp3;
2458     float *bypassr = Runtime.genTmp4;
2459     int i, nvoice;
2460     if (outl != NULL) {
2461         memset(outl, 0, synth->sent_bufferbytes);
2462         memset(outr, 0, synth->sent_bufferbytes);
2463     }
2464 
2465     if (NoteStatus == NOTE_DISABLED)
2466         return 0;
2467 
2468     if (subVoiceNumber == -1) {
2469         memset(bypassl, 0, synth->sent_bufferbytes);
2470         memset(bypassr, 0, synth->sent_bufferbytes);
2471     }
2472 
2473     if (paramsUpdate.checkUpdated())
2474         computeNoteParameters();
2475 
2476     computeWorkingParameters();
2477 
2478     for (nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
2479     {
2480         if (!NoteVoicePar[nvoice].Enabled || NoteVoicePar[nvoice].DelayTicks > 0)
2481             continue;
2482 
2483         if (NoteVoicePar[nvoice].FMEnabled != NONE)
2484             computeVoiceModulator(nvoice, NoteVoicePar[nvoice].FMEnabled);
2485 
2486         computeVoiceOscillator(nvoice);
2487 
2488         // Mix subvoices into voice
2489         memset(tmpwavel, 0, synth->sent_bufferbytes);
2490         if (stereo)
2491             memset(tmpwaver, 0, synth->sent_bufferbytes);
2492         for (int k = 0; k < unison_size[nvoice]; ++k)
2493         {
2494             float *tw = tmpwave_unison[k];
2495             if (stereo)
2496             {
2497                 float stereo_pos = 0.0f;
2498                 bool is_pwm = NoteVoicePar[nvoice].FMEnabled == PW_MOD;
2499                 if (is_pwm)
2500                 {
2501                     if (unison_size[nvoice] > 2)
2502                         stereo_pos = k/2 / (float)((unison_size[nvoice] / 2) - 1) * 2.0f - 1.0f;
2503                 } else if (unison_size[nvoice] > 1)
2504                 {
2505                     stereo_pos = (float) k
2506                         / (float)(unison_size[nvoice]
2507                                   - 1) * 2.0f - 1.0f;
2508                 }
2509                 float stereo_spread = unison_stereo_spread[nvoice] * 2.0f; // between 0 and 2.0
2510                 if (stereo_spread > 1.0f)
2511                 {
2512                     float stereo_pos_1 = (stereo_pos >= 0.0f) ? 1.0f : -1.0f;
2513                     stereo_pos = (2.0f - stereo_spread) * stereo_pos
2514                                   + (stereo_spread - 1.0f) * stereo_pos_1;
2515                 }
2516                 else
2517                     stereo_pos *= stereo_spread;
2518 
2519                 if (unison_size[nvoice] == 1 || (is_pwm && unison_size[nvoice] == 2))
2520                     stereo_pos = 0.0f;
2521                 float upan = (stereo_pos + 1.0f) * 0.5f;
2522                 float lvol = (1.0f - upan) * 2.0f;
2523                 if (lvol > 1.0f)
2524                     lvol = 1.0f;
2525 
2526                 float rvol = upan * 2.0f;
2527                 if (rvol > 1.0f)
2528                     rvol = 1.0f;
2529 
2530                 if (unison_invert_phase[nvoice][k])
2531                 {
2532                     lvol = -lvol;
2533                     rvol = -rvol;
2534                 }
2535 
2536                 for (i = 0; i < synth->sent_buffersize; ++i)
2537                     tmpwavel[i] += tw[i] * lvol;
2538                 for (i = 0; i < synth->sent_buffersize; ++i)
2539                     tmpwaver[i] += tw[i] * rvol;
2540             }
2541             else
2542                 for (i = 0; i < synth->sent_buffersize; ++i)
2543                     tmpwavel[i] += tw[i];
2544         }
2545 
2546         // reduce the amplitude for large unison sizes
2547         float unison_amplitude = 1.0f / sqrtf(unison_size[nvoice]);
2548 
2549         // Amplitude
2550         float oldam = oldamplitude[nvoice] * unison_amplitude;
2551         float newam = newamplitude[nvoice] * unison_amplitude;
2552 
2553         if (aboveAmplitudeThreshold(oldam, newam))
2554         {
2555             int rest = synth->sent_buffersize;
2556             // test if the amplitude if rising and the difference is high
2557             if (newam > oldam && (newam - oldam) > 0.25f)
2558             {
2559                 rest = 10;
2560                 if (rest > synth->sent_buffersize)
2561                     rest = synth->sent_buffersize;
2562                 for (int i = 0; i < synth->sent_buffersize - rest; ++i)
2563                     tmpwavel[i] *= oldam;
2564                 if (stereo)
2565                     for (int i = 0; i < synth->sent_buffersize - rest; ++i)
2566                         tmpwaver[i] *= oldam;
2567             }
2568             // Amplitude interpolation
2569             for (i = 0; i < rest; ++i)
2570             {
2571                 float amp = interpolateAmplitude(oldam, newam, i, rest);
2572                 tmpwavel[i + (synth->sent_buffersize - rest)] *= amp;
2573                 if (stereo)
2574                     tmpwaver[i + (synth->sent_buffersize - rest)] *= amp;
2575             }
2576         }
2577         else
2578         {
2579             for (i = 0; i < synth->sent_buffersize; ++i)
2580                 tmpwavel[i] *= newam;
2581             if (stereo)
2582                 for (i = 0; i < synth->sent_buffersize; ++i)
2583                     tmpwaver[i] *= newam;
2584         }
2585 
2586         // Fade in
2587         if (firsttick[nvoice])
2588         {
2589             fadein(tmpwavel);
2590             if (stereo)
2591                 fadein(tmpwaver);
2592             firsttick[nvoice] = 0;
2593         }
2594 
2595 
2596         // Filter
2597         if (NoteVoicePar[nvoice].VoiceFilterL != NULL)
2598             NoteVoicePar[nvoice].VoiceFilterL->filterout(tmpwavel);
2599         if (stereo && NoteVoicePar[nvoice].VoiceFilterR != NULL)
2600             NoteVoicePar[nvoice].VoiceFilterR->filterout(tmpwaver);
2601 
2602         // check if the amplitude envelope is finished.
2603         // if yes, the voice will fadeout
2604         if (NoteVoicePar[nvoice].AmpEnvelope != NULL)
2605         {
2606             if (NoteVoicePar[nvoice].AmpEnvelope->finished())
2607             {
2608                 for (i = 0; i < synth->sent_buffersize; ++i)
2609                     tmpwavel[i] *= 1.0f - (float)i / synth->sent_buffersize_f;
2610                 if (stereo)
2611                     for (i = 0; i < synth->sent_buffersize; ++i)
2612                         tmpwaver[i] *= 1.0f - (float)i / synth->sent_buffersize_f;
2613             }
2614             // the voice is killed later
2615         }
2616 
2617         // Put the ADnote samples in VoiceOut (without applying Global volume,
2618         // because I wish to use this voice as a modulator)
2619         if (NoteVoicePar[nvoice].VoiceOut)
2620         {
2621             if (stereo)
2622                 for (i = 0; i < synth->sent_buffersize; ++i)
2623                     NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i] + tmpwaver[i];
2624             else // mono
2625                 for (i = 0; i < synth->sent_buffersize; ++i)
2626                     NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i];
2627             if (NoteVoicePar[nvoice].Volume == 0.0f)
2628                 // If we are muted, we are done.
2629                 continue;
2630         }
2631 
2632         pangainL = adpars->VoicePar[nvoice].pangainL; // assume voice not random pan
2633         pangainR = adpars->VoicePar[nvoice].pangainR;
2634         if (adpars->VoicePar[nvoice].PRandom)
2635         {
2636             pangainL = NoteVoicePar[nvoice].randpanL;
2637             pangainR = NoteVoicePar[nvoice].randpanR;
2638         }
2639 
2640         if (outl != NULL) {
2641             // Add the voice that do not bypass the filter to out.
2642             if (!NoteVoicePar[nvoice].filterbypass) // no bypass
2643             {
2644                 if (stereo)
2645                 {
2646 
2647                     for (i = 0; i < synth->sent_buffersize; ++i) // stereo
2648                     {
2649                         outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume * pangainL;
2650                         outr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume * pangainR;
2651                     }
2652                 }
2653                 else
2654                     for (i = 0; i < synth->sent_buffersize; ++i)
2655                         outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume * 0.7f; // mono
2656             }
2657             else // bypass the filter
2658             {
2659                 if (stereo)
2660                 {
2661                     for (i = 0; i < synth->sent_buffersize; ++i) // stereo
2662                     {
2663                         bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume
2664                                       * pangainL;
2665                         bypassr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume
2666                                       * pangainR;
2667                     }
2668                 }
2669                 else
2670                     for (i = 0; i < synth->sent_buffersize; ++i)
2671                         bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; // mono
2672             }
2673             // check if there is necessary to process the voice longer
2674             // (if the Amplitude envelope isn't finished)
2675             if (NoteVoicePar[nvoice].AmpEnvelope != NULL)
2676                 if (NoteVoicePar[nvoice].AmpEnvelope->finished())
2677                     killVoice(nvoice);
2678         }
2679     }
2680 
2681     if (outl != NULL) {
2682         // Processing Global parameters
2683         NoteGlobalPar.GlobalFilterL->filterout(outl);
2684 
2685         if (!stereo) // set the right channel=left channel
2686         {
2687             memcpy(outr, outl, synth->sent_bufferbytes);
2688             memcpy(bypassr, bypassl, synth->sent_bufferbytes);
2689         }
2690         else
2691             NoteGlobalPar.GlobalFilterR->filterout(outr);
2692 
2693         for (i = 0; i < synth->sent_buffersize; ++i)
2694         {
2695             outl[i] += bypassl[i];
2696             outr[i] += bypassr[i];
2697         }
2698 
2699         pangainL = adpars->GlobalPar.pangainL; // assume it's not random panning ...
2700         pangainR = adpars->GlobalPar.pangainR;
2701         if (adpars->GlobalPar.PRandom)         // it is random panning
2702         {
2703             pangainL = NoteGlobalPar.randpanL;
2704             pangainR = NoteGlobalPar.randpanR;
2705         }
2706 
2707         if (aboveAmplitudeThreshold(globaloldamplitude, globalnewamplitude))
2708         {
2709             // Amplitude Interpolation
2710             for (i = 0; i < synth->sent_buffersize; ++i)
2711             {
2712                 float tmpvol = interpolateAmplitude(globaloldamplitude,
2713                                                     globalnewamplitude, i,
2714                                                     synth->sent_buffersize);
2715                 outl[i] *= tmpvol * pangainL;
2716                 outr[i] *= tmpvol * pangainR;
2717             }
2718         }
2719         else
2720         {
2721             for (i = 0; i < synth->sent_buffersize; ++i)
2722             {
2723                 outl[i] *= globalnewamplitude * pangainL;
2724                 outr[i] *= globalnewamplitude * pangainR;
2725             }
2726         }
2727 
2728         // Apply the punch
2729         if (NoteGlobalPar.Punch.Enabled)
2730         {
2731             for (i = 0; i < synth->sent_buffersize; ++i)
2732             {
2733                 float punchamp = NoteGlobalPar.Punch.initialvalue
2734                                  * NoteGlobalPar.Punch.t + 1.0f;
2735                 outl[i] *= punchamp;
2736                 outr[i] *= punchamp;
2737                 NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt;
2738                 if (NoteGlobalPar.Punch.t < 0.0f)
2739                 {
2740                     NoteGlobalPar.Punch.Enabled = 0;
2741                     break;
2742                 }
2743             }
2744         }
2745 
2746         // Apply legato fading if any
2747         if (legatoFadeStep != 0.0f)
2748         {
2749             for (int i = 0; i < synth->sent_buffersize; ++i)
2750             {
2751                 legatoFade += legatoFadeStep;
2752                 if (legatoFade <= 0.0f)
2753                 {
2754                     legatoFade = 0.0f;
2755                     legatoFadeStep = 0.0f;
2756                     memset(outl + i, 0, (synth->sent_buffersize - i) * sizeof(float));
2757                     memset(outr + i, 0, (synth->sent_buffersize - i) * sizeof(float));
2758                     break;
2759                 }
2760                 else if (legatoFade >= 1.0f)
2761                 {
2762                     legatoFade = 1.0f;
2763                     legatoFadeStep = 0.0f;
2764                     break;
2765                 }
2766                 outl[i] *= legatoFade;
2767                 outr[i] *= legatoFade;
2768             }
2769         }
2770     }
2771 
2772     // Check if the global amplitude is finished.
2773     // If it does, disable the note
2774     if (NoteGlobalPar.AmpEnvelope->finished())
2775     {
2776         if (outl != NULL) {
2777             for (i = 0; i < synth->sent_buffersize; ++i) // fade-out
2778             {
2779                 float tmp = 1.0f - (float)i / synth->sent_buffersize_f;
2780                 outl[i] *= tmp;
2781                 outr[i] *= tmp;
2782             }
2783         }
2784         killNote();
2785     }
2786     return 1;
2787 }
2788 
2789 
2790 // Release the key (NoteOff)
releasekey(void)2791 void ADnote::releasekey(void)
2792 {
2793     int nvoice;
2794     for (nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
2795     {
2796         if (!NoteVoicePar[nvoice].Enabled)
2797             continue;
2798         if (NoteVoicePar[nvoice].AmpEnvelope != NULL)
2799             NoteVoicePar[nvoice].AmpEnvelope->releasekey();
2800         if (NoteVoicePar[nvoice].FreqEnvelope != NULL)
2801             NoteVoicePar[nvoice].FreqEnvelope->releasekey();
2802         if (NoteVoicePar[nvoice].FilterEnvelope != NULL)
2803             NoteVoicePar[nvoice].FilterEnvelope->releasekey();
2804         if (NoteVoicePar[nvoice].FMFreqEnvelope != NULL)
2805             NoteVoicePar[nvoice].FMFreqEnvelope->releasekey();
2806         if (NoteVoicePar[nvoice].FMAmpEnvelope != NULL)
2807             NoteVoicePar[nvoice].FMAmpEnvelope->releasekey();
2808         if (subVoice[nvoice] != NULL)
2809             for (int k = 0; k < unison_size[nvoice]; ++k)
2810                 subVoice[nvoice][k]->releasekey();
2811         if (subFMVoice[nvoice] != NULL)
2812             for (int k = 0; k < unison_size[nvoice]; ++k)
2813                 subFMVoice[nvoice][k]->releasekey();
2814     }
2815     NoteGlobalPar.FreqEnvelope->releasekey();
2816     NoteGlobalPar.FilterEnvelope->releasekey();
2817     NoteGlobalPar.AmpEnvelope->releasekey();
2818     if (NoteStatus == NOTE_KEEPALIVE)
2819         NoteStatus = NOTE_ENABLED;
2820 }
2821