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