|
- /*
- ZynAddSubFX - a software synthesizer
-
- ADnote.cpp - The "additive" synthesizer
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #include <cmath>
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
-
- #include "../globals.h"
- #include "../Misc/Util.h"
- #include "../DSP/Filter.h"
- #include "OscilGen.h"
- #include "ADnote.h"
-
-
- ADnote::ADnote(ADnoteParameters *pars,
- Controller *ctl_,
- float freq,
- float velocity,
- int portamento_,
- int midinote_,
- bool besilent)
- :SynthNote(freq, velocity, portamento_, midinote, besilent)
- {
- tmpwavel = new float [synth->buffersize];
- tmpwaver = new float [synth->buffersize];
- bypassl = new float [synth->buffersize];
- bypassr = new float [synth->buffersize];
-
- partparams = pars;
- ctl = ctl_;
- portamento = portamento_;
- midinote = midinote_;
- NoteEnabled = ON;
- basefreq = freq;
- if(velocity > 1.0f)
- velocity = 1.0f;
- this->velocity = velocity;
- time = 0.0f;
- stereo = pars->GlobalPar.PStereo;
-
- NoteGlobalPar.Detune = getdetune(pars->GlobalPar.PDetuneType,
- pars->GlobalPar.PCoarseDetune,
- pars->GlobalPar.PDetune);
- bandwidthDetuneMultiplier = pars->getBandwidthDetuneMultiplier();
-
- if(pars->GlobalPar.PPanning == 0)
- NoteGlobalPar.Panning = RND;
- else
- NoteGlobalPar.Panning = pars->GlobalPar.PPanning / 128.0f;
-
-
- NoteGlobalPar.FilterCenterPitch = pars->GlobalPar.GlobalFilter->getfreq() //center freq
- + pars->GlobalPar.PFilterVelocityScale
- / 127.0f * 6.0f //velocity sensing
- * (VelF(velocity,
- pars->GlobalPar.
- PFilterVelocityScaleFunction) - 1);
-
- if(pars->GlobalPar.PPunchStrength != 0) {
- NoteGlobalPar.Punch.Enabled = 1;
- NoteGlobalPar.Punch.t = 1.0f; //start from 1.0f and to 0.0f
- NoteGlobalPar.Punch.initialvalue =
- ((powf(10, 1.5f * pars->GlobalPar.PPunchStrength / 127.0f) - 1.0f)
- * VelF(velocity,
- pars->GlobalPar.PPunchVelocitySensing));
- float time =
- powf(10, 3.0f * pars->GlobalPar.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms
- float stretch = powf(440.0f / freq,
- pars->GlobalPar.PPunchStretch / 64.0f);
- NoteGlobalPar.Punch.dt = 1.0f / (time * synth->samplerate_f * stretch);
- }
- else
- NoteGlobalPar.Punch.Enabled = 0;
-
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- pars->VoicePar[nvoice].OscilSmp->newrandseed(prng());
- NoteVoicePar[nvoice].OscilSmp = NULL;
- NoteVoicePar[nvoice].FMSmp = NULL;
- NoteVoicePar[nvoice].VoiceOut = NULL;
-
- NoteVoicePar[nvoice].FMVoice = -1;
- unison_size[nvoice] = 1;
-
- if(pars->VoicePar[nvoice].Enabled == 0) {
- NoteVoicePar[nvoice].Enabled = OFF;
- continue; //the voice is disabled
- }
-
- unison_stereo_spread[nvoice] =
- pars->VoicePar[nvoice].Unison_stereo_spread / 127.0f;
- int unison = pars->VoicePar[nvoice].Unison_size;
- if(unison < 1)
- unison = 1;
-
- //compute unison
- unison_size[nvoice] = unison;
-
- unison_base_freq_rap[nvoice] = new float[unison];
- unison_freq_rap[nvoice] = new float[unison];
- unison_invert_phase[nvoice] = new bool[unison];
- float unison_spread = pars->getUnisonFrequencySpreadCents(
- nvoice);
- float unison_real_spread = powf(2.0f, (unison_spread * 0.5f) / 1200.0f);
- float unison_vibratto_a = pars->VoicePar[nvoice].Unison_vibratto
- / 127.0f; //0.0f .. 1.0f
-
-
- switch(unison) {
- case 1:
- unison_base_freq_rap[nvoice][0] = 1.0f; //if the unison is not used, always make the only subvoice to have the default note
- break;
- case 2: { //unison for 2 subvoices
- unison_base_freq_rap[nvoice][0] = 1.0f / unison_real_spread;
- unison_base_freq_rap[nvoice][1] = unison_real_spread;
- };
- break;
- default: { //unison for more than 2 subvoices
- float unison_values[unison];
- float min = -1e-6, max = 1e-6;
- for(int k = 0; k < unison; ++k) {
- float step = (k / (float) (unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform
- float val = step + (RND * 2.0f - 1.0f) / (unison - 1);
- unison_values[k] = limit(val, min, max);
- }
- float diff = max - min;
- for(int k = 0; k < unison; ++k) {
- unison_values[k] =
- (unison_values[k] - (max + min) * 0.5f) / diff; //the lowest value will be -1 and the highest will be 1
- unison_base_freq_rap[nvoice][k] =
- powf(2.0f, (unison_spread * unison_values[k]) / 1200);
- }
- };
- }
-
- //unison vibrattos
- if(unison > 1)
- for(int k = 0; k < unison; ++k) //reduce the frequency difference for larger vibrattos
- unison_base_freq_rap[nvoice][k] = 1.0f
- + (unison_base_freq_rap[
- nvoice][k] - 1.0f)
- * (1.0f - unison_vibratto_a);
- unison_vibratto[nvoice].step = new float[unison];
- unison_vibratto[nvoice].position = new float[unison];
- unison_vibratto[nvoice].amplitude =
- (unison_real_spread - 1.0f) * unison_vibratto_a;
-
- float increments_per_second = synth->samplerate_f / synth->buffersize_f;
- float vibratto_base_period = 0.25f
- * powf(
- 2.0f,
- (1.0f
- - pars->VoicePar[nvoice].
- Unison_vibratto_speed
- / 127.0f) * 4.0f);
- for(int k = 0; k < unison; ++k) {
- unison_vibratto[nvoice].position[k] = RND * 1.8f - 0.9f;
- //make period to vary randomly from 50% to 200% vibratto base period
- float vibratto_period = vibratto_base_period
- * powf(2.0f, RND * 2.0f - 1.0f);
-
- float m = 4.0f / (vibratto_period * increments_per_second);
- if(RND < 0.5f)
- m = -m;
- unison_vibratto[nvoice].step[k] = m;
- }
-
- if(unison == 1) { //no vibratto for a single voice
- unison_vibratto[nvoice].step[0] = 0.0f;
- unison_vibratto[nvoice].position[0] = 0.0f;
- unison_vibratto[nvoice].amplitude = 0.0f;
- }
-
- //phase invert for unison
- unison_invert_phase[nvoice][0] = false;
- if(unison != 1) {
- int inv = pars->VoicePar[nvoice].Unison_invert_phase;
- switch(inv) {
- case 0: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] = false;
- break;
- case 1: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] = (RND > 0.5f);
- break;
- default: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] =
- (k % inv == 0) ? true : false;
- break;
- }
- }
-
-
- oscfreqhi[nvoice] = new int[unison];
- oscfreqlo[nvoice] = new float[unison];
- oscfreqhiFM[nvoice] = new unsigned int[unison];
- oscfreqloFM[nvoice] = new float[unison];
- oscposhi[nvoice] = new int[unison];
- oscposlo[nvoice] = new float[unison];
- oscposhiFM[nvoice] = new unsigned int[unison];
- oscposloFM[nvoice] = new float[unison];
-
- NoteVoicePar[nvoice].Enabled = ON;
- NoteVoicePar[nvoice].fixedfreq = pars->VoicePar[nvoice].Pfixedfreq;
- NoteVoicePar[nvoice].fixedfreqET = pars->VoicePar[nvoice].PfixedfreqET;
-
- //use the Globalpars.detunetype if the detunetype is 0
- if(pars->VoicePar[nvoice].PDetuneType != 0) {
- NoteVoicePar[nvoice].Detune = getdetune(
- pars->VoicePar[nvoice].PDetuneType,
- pars->VoicePar[nvoice].
- PCoarseDetune,
- 8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
- pars->VoicePar[nvoice].PDetuneType,
- 0,
- pars->VoicePar[nvoice].PDetune); //fine detune
- }
- else {
- NoteVoicePar[nvoice].Detune = getdetune(
- pars->GlobalPar.PDetuneType,
- pars->VoicePar[nvoice].
- PCoarseDetune,
- 8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
- pars->GlobalPar.PDetuneType,
- 0,
- pars->VoicePar[nvoice].PDetune); //fine detune
- }
- if(pars->VoicePar[nvoice].PFMDetuneType != 0)
- NoteVoicePar[nvoice].FMDetune = getdetune(
- pars->VoicePar[nvoice].PFMDetuneType,
- pars->VoicePar[nvoice].
- PFMCoarseDetune,
- pars->VoicePar[nvoice].PFMDetune);
- else
- NoteVoicePar[nvoice].FMDetune = getdetune(
- pars->GlobalPar.PDetuneType,
- pars->VoicePar[nvoice].
- PFMCoarseDetune,
- pars->VoicePar[nvoice].PFMDetune);
-
-
-
- for(int k = 0; k < unison; ++k) {
- oscposhi[nvoice][k] = 0;
- oscposlo[nvoice][k] = 0.0f;
- oscposhiFM[nvoice][k] = 0;
- oscposloFM[nvoice][k] = 0.0f;
- }
-
- //the extra points contains the first point
- NoteVoicePar[nvoice].OscilSmp =
- new float[synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES];
-
- //Get the voice's oscil or external's voice oscil
- int vc = nvoice;
- if(pars->VoicePar[nvoice].Pextoscil != -1)
- vc = pars->VoicePar[nvoice].Pextoscil;
- if(!pars->GlobalPar.Hrandgrouping)
- pars->VoicePar[vc].OscilSmp->newrandseed(prng());
- int oscposhi_start =
- pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
- getvoicebasefreq(nvoice),
- pars->VoicePar[nvoice].Presonance);
-
- //I store the first elments to the last position for speedups
- for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
- NoteVoicePar[nvoice].OscilSmp[synth->oscilsize
- + i] =
- NoteVoicePar[nvoice].OscilSmp[i];
-
- oscposhi_start +=
- (int)((pars->VoicePar[nvoice].Poscilphase
- - 64.0f) / 128.0f * synth->oscilsize + synth->oscilsize * 4);
- oscposhi_start %= synth->oscilsize;
-
- for(int k = 0; k < unison; ++k) {
- oscposhi[nvoice][k] = oscposhi_start;
- oscposhi_start = (int)(RND * (synth->oscilsize - 1)); //put random starting point for other subvoices
- }
-
- NoteVoicePar[nvoice].FreqLfo = NULL;
- NoteVoicePar[nvoice].FreqEnvelope = NULL;
-
- NoteVoicePar[nvoice].AmpLfo = NULL;
- NoteVoicePar[nvoice].AmpEnvelope = NULL;
-
- NoteVoicePar[nvoice].VoiceFilterL = NULL;
- NoteVoicePar[nvoice].VoiceFilterR = NULL;
- NoteVoicePar[nvoice].FilterEnvelope = NULL;
- NoteVoicePar[nvoice].FilterLfo = NULL;
-
- NoteVoicePar[nvoice].FilterCenterPitch =
- pars->VoicePar[nvoice].VoiceFilter->getfreq();
- NoteVoicePar[nvoice].filterbypass =
- pars->VoicePar[nvoice].Pfilterbypass;
-
- switch(pars->VoicePar[nvoice].PFMEnabled) {
- case 1:
- NoteVoicePar[nvoice].FMEnabled = MORPH;
- break;
- case 2:
- NoteVoicePar[nvoice].FMEnabled = RING_MOD;
- break;
- case 3:
- NoteVoicePar[nvoice].FMEnabled = PHASE_MOD;
- break;
- case 4:
- NoteVoicePar[nvoice].FMEnabled = FREQ_MOD;
- break;
- case 5:
- NoteVoicePar[nvoice].FMEnabled = PITCH_MOD;
- break;
- default:
- NoteVoicePar[nvoice].FMEnabled = NONE;
- }
-
- NoteVoicePar[nvoice].FMVoice = pars->VoicePar[nvoice].PFMVoice;
- NoteVoicePar[nvoice].FMFreqEnvelope = NULL;
- NoteVoicePar[nvoice].FMAmpEnvelope = NULL;
-
- //Compute the Voice's modulator volume (incl. damping)
- float fmvoldamp = powf(440.0f / getvoicebasefreq(
- nvoice),
- pars->VoicePar[nvoice].PFMVolumeDamp / 64.0f
- - 1.0f);
- switch(NoteVoicePar[nvoice].FMEnabled) {
- case PHASE_MOD:
- fmvoldamp =
- powf(440.0f / getvoicebasefreq(
- nvoice), pars->VoicePar[nvoice].PFMVolumeDamp
- / 64.0f);
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars->VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
- break;
- case FREQ_MOD:
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars->VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
- break;
- // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0f*8.0f)*fmvoldamp;//???????????
- // break;
- default:
- if(fmvoldamp > 1.0f)
- fmvoldamp = 1.0f;
- NoteVoicePar[nvoice].FMVolume =
- pars->VoicePar[nvoice].PFMVolume
- / 127.0f * fmvoldamp;
- }
-
- //Voice's modulator velocity sensing
- NoteVoicePar[nvoice].FMVolume *=
- VelF(velocity,
- partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
-
- FMoldsmp[nvoice] = new float [unison];
- for(int k = 0; k < unison; ++k)
- FMoldsmp[nvoice][k] = 0.0f; //this is for FM (integration)
-
- firsttick[nvoice] = 1;
- NoteVoicePar[nvoice].DelayTicks =
- (int)((expf(pars->VoicePar[nvoice].PDelay / 127.0f
- * logf(50.0f))
- - 1.0f) / synth->buffersize_f / 10.0f * synth->samplerate_f);
- }
-
- max_unison = 1;
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
- if(unison_size[nvoice] > max_unison)
- max_unison = unison_size[nvoice];
-
-
- tmpwave_unison = new float *[max_unison];
- for(int k = 0; k < max_unison; ++k) {
- tmpwave_unison[k] = new float[synth->buffersize];
- memset(tmpwave_unison[k], 0, synth->bufferbytes);
- }
-
- initparameters();
- }
-
- // ADlegatonote: This function is (mostly) a copy of ADnote(...) and
- // initparameters() stuck together with some lines removed so that it
- // only alter the already playing note (to perform legato). It is
- // possible I left stuff that is not required for this.
- void ADnote::legatonote(float freq, float velocity, int portamento_,
- int midinote_, bool externcall)
- {
- ADnoteParameters *pars = partparams;
-
- // Manage legato stuff
- if(legato.update(freq, velocity, portamento_, midinote_, externcall))
- return;
-
- portamento = portamento_;
- midinote = midinote_;
- basefreq = freq;
-
- if(velocity > 1.0f)
- velocity = 1.0f;
- this->velocity = velocity;
-
- NoteGlobalPar.Detune = getdetune(pars->GlobalPar.PDetuneType,
- pars->GlobalPar.PCoarseDetune,
- pars->GlobalPar.PDetune);
- bandwidthDetuneMultiplier = pars->getBandwidthDetuneMultiplier();
-
- if(pars->GlobalPar.PPanning == 0)
- NoteGlobalPar.Panning = RND;
- else
- NoteGlobalPar.Panning = pars->GlobalPar.PPanning / 128.0f;
-
- //center freq
- NoteGlobalPar.FilterCenterPitch = pars->GlobalPar.GlobalFilter->getfreq()
- + pars->GlobalPar.PFilterVelocityScale
- / 127.0f * 6.0f //velocity sensing
- * (VelF(velocity,
- pars->GlobalPar.
- PFilterVelocityScaleFunction) - 1);
-
-
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- if(NoteVoicePar[nvoice].Enabled == OFF)
- continue; //(gf) Stay the same as first note in legato.
-
- NoteVoicePar[nvoice].fixedfreq = pars->VoicePar[nvoice].Pfixedfreq;
- NoteVoicePar[nvoice].fixedfreqET = pars->VoicePar[nvoice].PfixedfreqET;
-
- //use the Globalpars.detunetype if the detunetype is 0
- if(pars->VoicePar[nvoice].PDetuneType != 0) {
- NoteVoicePar[nvoice].Detune = getdetune(
- pars->VoicePar[nvoice].PDetuneType,
- pars->VoicePar[nvoice].PCoarseDetune,
- 8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
- pars->VoicePar[nvoice].PDetuneType,
- 0,
- pars->VoicePar[nvoice].PDetune); //fine detune
- }
- else {
- NoteVoicePar[nvoice].Detune = getdetune(
- pars->GlobalPar.PDetuneType,
- pars->VoicePar[nvoice].PCoarseDetune,
- 8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
- pars->GlobalPar.PDetuneType,
- 0,
- pars->VoicePar[nvoice].PDetune); //fine detune
- }
- if(pars->VoicePar[nvoice].PFMDetuneType != 0)
- NoteVoicePar[nvoice].FMDetune = getdetune(
- pars->VoicePar[nvoice].PFMDetuneType,
- pars->VoicePar[nvoice].PFMCoarseDetune,
- pars->VoicePar[nvoice].PFMDetune);
- else
- NoteVoicePar[nvoice].FMDetune = getdetune(
- pars->GlobalPar.PDetuneType,
- pars->VoicePar[nvoice].PFMCoarseDetune,
- pars->VoicePar[nvoice].PFMDetune);
-
-
- //Get the voice's oscil or external's voice oscil
- int vc = nvoice;
- if(pars->VoicePar[nvoice].Pextoscil != -1)
- vc = pars->VoicePar[nvoice].Pextoscil;
- if(!pars->GlobalPar.Hrandgrouping)
- pars->VoicePar[vc].OscilSmp->newrandseed(prng());
-
- pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
- getvoicebasefreq(nvoice),
- pars->VoicePar[nvoice].Presonance); //(gf)Modif of the above line.
-
- //I store the first elments to the last position for speedups
- for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
- NoteVoicePar[nvoice].OscilSmp[synth->oscilsize
- + i] =
- NoteVoicePar[nvoice].OscilSmp[i];
-
-
- NoteVoicePar[nvoice].FilterCenterPitch =
- pars->VoicePar[nvoice].VoiceFilter->getfreq();
- NoteVoicePar[nvoice].filterbypass =
- pars->VoicePar[nvoice].Pfilterbypass;
-
-
- NoteVoicePar[nvoice].FMVoice = pars->VoicePar[nvoice].PFMVoice;
-
- //Compute the Voice's modulator volume (incl. damping)
- float fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice),
- pars->VoicePar[nvoice].PFMVolumeDamp / 64.0f
- - 1.0f);
-
- switch(NoteVoicePar[nvoice].FMEnabled) {
- case PHASE_MOD:
- fmvoldamp =
- powf(440.0f / getvoicebasefreq(
- nvoice), pars->VoicePar[nvoice].PFMVolumeDamp
- / 64.0f);
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars->VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
- break;
- case FREQ_MOD:
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars->VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
- break;
- // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0f*8.0f)*fmvoldamp;//???????????
- // break;
- default:
- if(fmvoldamp > 1.0f)
- fmvoldamp = 1.0f;
- NoteVoicePar[nvoice].FMVolume =
- pars->VoicePar[nvoice].PFMVolume
- / 127.0f * fmvoldamp;
- }
-
- //Voice's modulator velocity sensing
- NoteVoicePar[nvoice].FMVolume *=
- VelF(velocity,
- partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
-
- NoteVoicePar[nvoice].DelayTicks =
- (int)((expf(pars->VoicePar[nvoice].PDelay / 127.0f
- * logf(50.0f))
- - 1.0f) / synth->buffersize_f / 10.0f * synth->samplerate_f);
- }
-
- /// initparameters();
-
- ///////////////
- // Altered content of initparameters():
-
- int tmp[NUM_VOICES];
-
- NoteGlobalPar.Volume = 4.0f
- * powf(0.1f, 3.0f
- * (1.0f - partparams->GlobalPar.PVolume
- / 96.0f)) //-60 dB .. 0 dB
- * VelF(
- velocity,
- partparams->GlobalPar.
- PAmpVelocityScaleFunction); //velocity sensing
-
- globalnewamplitude = NoteGlobalPar.Volume
- * NoteGlobalPar.AmpEnvelope->envout_dB()
- * NoteGlobalPar.AmpLfo->amplfoout();
-
- NoteGlobalPar.FilterQ = partparams->GlobalPar.GlobalFilter->getq();
- NoteGlobalPar.FilterFreqTracking =
- partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq);
-
- // Forbids the Modulation Voice to be greater or equal than voice
- for(int i = 0; i < NUM_VOICES; ++i)
- if(NoteVoicePar[i].FMVoice >= i)
- NoteVoicePar[i].FMVoice = -1;
-
- // Voice Parameter init
- for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- if(NoteVoicePar[nvoice].Enabled == 0)
- continue;
-
- NoteVoicePar[nvoice].noisetype = partparams->VoicePar[nvoice].Type;
- /* Voice Amplitude Parameters Init */
- NoteVoicePar[nvoice].Volume =
- powf(0.1f, 3.0f
- * (1.0f - partparams->VoicePar[nvoice].PVolume / 127.0f)) // -60 dB .. 0 dB
- * VelF(velocity,
- partparams->VoicePar[nvoice].PAmpVelocityScaleFunction); //velocity
-
- if(partparams->VoicePar[nvoice].PVolumeminus != 0)
- NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume;
-
- if(partparams->VoicePar[nvoice].PPanning == 0)
- NoteVoicePar[nvoice].Panning = RND; // random panning
- else
- NoteVoicePar[nvoice].Panning =
- partparams->VoicePar[nvoice].PPanning / 128.0f;
-
- newamplitude[nvoice] = 1.0f;
- if((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled != 0)
- && (NoteVoicePar[nvoice].AmpEnvelope != NULL))
- newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
-
-
- if((partparams->VoicePar[nvoice].PAmpLfoEnabled != 0)
- && (NoteVoicePar[nvoice].AmpLfo != NULL))
- newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout();
-
-
-
- NoteVoicePar[nvoice].FilterFreqTracking =
- partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq);
-
- /* Voice Modulation Parameters Init */
- if((NoteVoicePar[nvoice].FMEnabled != NONE)
- && (NoteVoicePar[nvoice].FMVoice < 0)) {
- partparams->VoicePar[nvoice].FMSmp->newrandseed(prng());
-
- //Perform Anti-aliasing only on MORPH or RING MODULATION
-
- int vc = nvoice;
- if(partparams->VoicePar[nvoice].PextFMoscil != -1)
- vc = partparams->VoicePar[nvoice].PextFMoscil;
-
- if(!partparams->GlobalPar.Hrandgrouping)
- partparams->VoicePar[vc].FMSmp->newrandseed(prng());
-
- for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
- NoteVoicePar[nvoice].FMSmp[synth->oscilsize + i] =
- NoteVoicePar[nvoice].FMSmp[i];
- }
-
- FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume
- * ctl->fmamp.relamp;
-
- if((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0)
- && (NoteVoicePar[nvoice].FMAmpEnvelope != NULL))
- FMnewamplitude[nvoice] *=
- NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
- }
-
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- for(unsigned i = nvoice + 1; i < NUM_VOICES; ++i)
- tmp[i] = 0;
- for(unsigned i = nvoice + 1; i < NUM_VOICES; ++i)
- if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0))
- tmp[i] = 1;
- }
- }
-
-
- /*
- * Kill a voice of ADnote
- */
- void ADnote::KillVoice(int nvoice)
- {
- delete [] oscfreqhi[nvoice];
- delete [] oscfreqlo[nvoice];
- delete [] oscfreqhiFM[nvoice];
- delete [] oscfreqloFM[nvoice];
- delete [] oscposhi[nvoice];
- delete [] oscposlo[nvoice];
- delete [] oscposhiFM[nvoice];
- delete [] oscposloFM[nvoice];
-
- delete [] unison_base_freq_rap[nvoice];
- delete [] unison_freq_rap[nvoice];
- delete [] unison_invert_phase[nvoice];
- delete [] FMoldsmp[nvoice];
- delete [] unison_vibratto[nvoice].step;
- delete [] unison_vibratto[nvoice].position;
-
- NoteVoicePar[nvoice].kill();
- }
-
- /*
- * Kill the note
- */
- void ADnote::KillNote()
- {
- for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- if(NoteVoicePar[nvoice].Enabled == ON)
- KillVoice(nvoice);
-
- if(NoteVoicePar[nvoice].VoiceOut)
- delete NoteVoicePar[nvoice].VoiceOut;
- NoteVoicePar[nvoice].VoiceOut = NULL;
- }
-
- NoteGlobalPar.kill();
-
- NoteEnabled = OFF;
- }
-
- ADnote::~ADnote()
- {
- if(NoteEnabled == ON)
- KillNote();
- delete [] tmpwavel;
- delete [] tmpwaver;
- delete [] bypassl;
- delete [] bypassr;
- for(int k = 0; k < max_unison; ++k)
- delete[] tmpwave_unison[k];
- delete[] tmpwave_unison;
- }
-
-
- /*
- * Init the parameters
- */
- void ADnote::initparameters()
- {
- int tmp[NUM_VOICES];
-
- // Global Parameters
- NoteGlobalPar.initparameters(partparams->GlobalPar, basefreq, velocity,
- stereo);
-
- NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output
- globalnewamplitude = NoteGlobalPar.Volume
- * NoteGlobalPar.AmpEnvelope->envout_dB()
- * NoteGlobalPar.AmpLfo->amplfoout();
-
- // Forbids the Modulation Voice to be greater or equal than voice
- for(int i = 0; i < NUM_VOICES; ++i)
- if(NoteVoicePar[i].FMVoice >= i)
- NoteVoicePar[i].FMVoice = -1;
-
- // Voice Parameter init
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- Voice &vce = NoteVoicePar[nvoice];
- ADnoteVoiceParam ¶m = partparams->VoicePar[nvoice];
-
- if(vce.Enabled == 0)
- continue;
-
- vce.noisetype = param.Type;
- /* Voice Amplitude Parameters Init */
- vce.Volume = powf(0.1f, 3.0f * (1.0f - param.PVolume / 127.0f)) // -60dB..0dB
- * VelF(velocity, param.PAmpVelocityScaleFunction);
-
- if(param.PVolumeminus)
- vce.Volume = -vce.Volume;
-
- if(param.PPanning == 0)
- vce.Panning = RND; // random panning
- else
- vce.Panning = param.PPanning / 128.0f;
-
- newamplitude[nvoice] = 1.0f;
- if(param.PAmpEnvelopeEnabled) {
- vce.AmpEnvelope = new Envelope(param.AmpEnvelope, basefreq);
- vce.AmpEnvelope->envout_dB(); //discard the first envelope sample
- newamplitude[nvoice] *= vce.AmpEnvelope->envout_dB();
- }
-
- if(param.PAmpLfoEnabled) {
- vce.AmpLfo = new LFO(param.AmpLfo, basefreq);
- newamplitude[nvoice] *= vce.AmpLfo->amplfoout();
- }
-
- /* Voice Frequency Parameters Init */
- if(param.PFreqEnvelopeEnabled != 0)
- vce.FreqEnvelope = new Envelope(param.FreqEnvelope, basefreq);
-
- if(param.PFreqLfoEnabled != 0)
- vce.FreqLfo = new LFO(param.FreqLfo, basefreq);
-
- /* Voice Filter Parameters Init */
- if(param.PFilterEnabled != 0) {
- vce.VoiceFilterL = Filter::generate(param.VoiceFilter);
- vce.VoiceFilterR = Filter::generate(param.VoiceFilter);
- }
-
- if(param.PFilterEnvelopeEnabled != 0)
- vce.FilterEnvelope = new Envelope(param.FilterEnvelope, basefreq);
-
- if(param.PFilterLfoEnabled != 0)
- vce.FilterLfo = new LFO(param.FilterLfo, basefreq);
-
- vce.FilterFreqTracking =
- param.VoiceFilter->getfreqtracking(basefreq);
-
- /* Voice Modulation Parameters Init */
- if((vce.FMEnabled != NONE) && (vce.FMVoice < 0)) {
- param.FMSmp->newrandseed(prng());
- vce.FMSmp = new float[synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES];
-
- //Perform Anti-aliasing only on MORPH or RING MODULATION
-
- int vc = nvoice;
- if(param.PextFMoscil != -1)
- vc = param.PextFMoscil;
-
- float tmp = 1.0f;
- if((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics != 0)
- || (vce.FMEnabled == MORPH)
- || (vce.FMEnabled == RING_MOD))
- tmp = getFMvoicebasefreq(nvoice);
-
- if(!partparams->GlobalPar.Hrandgrouping)
- partparams->VoicePar[vc].FMSmp->newrandseed(prng());
-
- for(int k = 0; k < unison_size[nvoice]; ++k)
- oscposhiFM[nvoice][k] = (oscposhi[nvoice][k]
- + partparams->VoicePar[vc].FMSmp->get(
- vce.FMSmp, tmp))
- % synth->oscilsize;
-
- for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
- vce.FMSmp[synth->oscilsize + i] = vce.FMSmp[i];
- int oscposhiFM_add =
- (int)((param.PFMoscilphase
- - 64.0f) / 128.0f * synth->oscilsize
- + synth->oscilsize * 4);
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- oscposhiFM[nvoice][k] += oscposhiFM_add;
- oscposhiFM[nvoice][k] %= synth->oscilsize;
- }
- }
-
- if(param.PFMFreqEnvelopeEnabled != 0)
- vce.FMFreqEnvelope = new Envelope(param.FMFreqEnvelope, basefreq);
-
- FMnewamplitude[nvoice] = vce.FMVolume * ctl->fmamp.relamp;
-
- if(param.PFMAmpEnvelopeEnabled != 0) {
- vce.FMAmpEnvelope = new Envelope(param.FMAmpEnvelope,
- basefreq);
- FMnewamplitude[nvoice] *= vce.FMAmpEnvelope->envout_dB();
- }
- }
-
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- for(int i = nvoice + 1; i < NUM_VOICES; ++i)
- tmp[i] = 0;
- for(int i = nvoice + 1; i < NUM_VOICES; ++i)
- if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) {
- NoteVoicePar[nvoice].VoiceOut = new float[synth->buffersize];
- tmp[i] = 1;
- }
-
- if(NoteVoicePar[nvoice].VoiceOut)
- memset(NoteVoicePar[nvoice].VoiceOut, 0, synth->bufferbytes);
- }
- }
-
-
- /*
- * Computes the relative frequency of each unison voice and it's vibratto
- * This must be called before setfreq* functions
- */
- void ADnote::compute_unison_freq_rap(int nvoice) {
- if(unison_size[nvoice] == 1) { //no unison
- unison_freq_rap[nvoice][0] = 1.0f;
- return;
- }
- float relbw = ctl->bandwidth.relbw * bandwidthDetuneMultiplier;
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float pos = unison_vibratto[nvoice].position[k];
- float step = unison_vibratto[nvoice].step[k];
- pos += step;
- if(pos <= -1.0f) {
- pos = -1.0f;
- step = -step;
- }
- if(pos >= 1.0f) {
- pos = 1.0f;
- step = -step;
- }
- float vibratto_val = (pos - 0.333333333f * pos * pos * pos) * 1.5f; //make the vibratto lfo smoother
- unison_freq_rap[nvoice][k] = 1.0f
- + ((unison_base_freq_rap[nvoice][k]
- - 1.0f) + vibratto_val
- * unison_vibratto[nvoice].amplitude)
- * relbw;
-
- unison_vibratto[nvoice].position[k] = pos;
- step = unison_vibratto[nvoice].step[k] = step;
- }
- }
-
-
- /*
- * Computes the frequency of an oscillator
- */
- void ADnote::setfreq(int nvoice, float in_freq)
- {
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float freq = fabs(in_freq) * unison_freq_rap[nvoice][k];
- float speed = freq * synth->oscilsize_f / synth->samplerate_f;
- if(speed > synth->oscilsize_f)
- speed = synth->oscilsize_f;
-
- F2I(speed, oscfreqhi[nvoice][k]);
- oscfreqlo[nvoice][k] = speed - floor(speed);
- }
- }
-
- /*
- * Computes the frequency of an modullator oscillator
- */
- void ADnote::setfreqFM(int nvoice, float in_freq)
- {
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float freq = fabs(in_freq) * unison_freq_rap[nvoice][k];
- float speed = freq * synth->oscilsize_f / synth->samplerate_f;
- if(speed > synth->samplerate_f)
- speed = synth->samplerate_f;
-
- F2I(speed, oscfreqhiFM[nvoice][k]);
- oscfreqloFM[nvoice][k] = speed - floor(speed);
- }
- }
-
- /*
- * Get Voice base frequency
- */
- float ADnote::getvoicebasefreq(int nvoice) const
- {
- float detune = NoteVoicePar[nvoice].Detune / 100.0f
- + NoteVoicePar[nvoice].FineDetune / 100.0f
- * ctl->bandwidth.relbw * bandwidthDetuneMultiplier
- + NoteGlobalPar.Detune / 100.0f;
-
- if(NoteVoicePar[nvoice].fixedfreq == 0)
- return this->basefreq * powf(2, detune / 12.0f);
- else { //the fixed freq is enabled
- float fixedfreq = 440.0f;
- int fixedfreqET = NoteVoicePar[nvoice].fixedfreqET;
- if(fixedfreqET != 0) { //if the frequency varies according the keyboard note
- float tmp =
- (midinote
- - 69.0f) / 12.0f
- * (powf(2.0f, (fixedfreqET - 1) / 63.0f) - 1.0f);
- if(fixedfreqET <= 64)
- fixedfreq *= powf(2.0f, tmp);
- else
- fixedfreq *= powf(3.0f, tmp);
- }
- return fixedfreq * powf(2.0f, detune / 12.0f);
- }
- }
-
- /*
- * Get Voice's Modullator base frequency
- */
- float ADnote::getFMvoicebasefreq(int nvoice) const
- {
- float detune = NoteVoicePar[nvoice].FMDetune / 100.0f;
- return getvoicebasefreq(nvoice) * powf(2, detune / 12.0f);
- }
-
- /*
- * Computes all the parameters for each tick
- */
- void ADnote::computecurrentparameters()
- {
- int nvoice;
- float voicefreq, voicepitch, filterpitch, filterfreq, FMfreq,
- FMrelativepitch, globalpitch, globalfilterpitch;
- globalpitch = 0.01f * (NoteGlobalPar.FreqEnvelope->envout()
- + NoteGlobalPar.FreqLfo->lfoout()
- * ctl->modwheel.relmod);
- globaloldamplitude = globalnewamplitude;
- globalnewamplitude = NoteGlobalPar.Volume
- * NoteGlobalPar.AmpEnvelope->envout_dB()
- * NoteGlobalPar.AmpLfo->amplfoout();
-
- globalfilterpitch = NoteGlobalPar.FilterEnvelope->envout()
- + NoteGlobalPar.FilterLfo->lfoout()
- + NoteGlobalPar.FilterCenterPitch;
-
- float tmpfilterfreq = globalfilterpitch + ctl->filtercutoff.relfreq
- + NoteGlobalPar.FilterFreqTracking;
-
- tmpfilterfreq = Filter::getrealfreq(tmpfilterfreq);
-
- float globalfilterq = NoteGlobalPar.FilterQ * ctl->filterq.relq;
- NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq, globalfilterq);
- if(stereo != 0)
- NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq, globalfilterq);
-
- //compute the portamento, if it is used by this note
- float portamentofreqrap = 1.0f;
- if(portamento != 0) { //this voice use portamento
- portamentofreqrap = ctl->portamento.freqrap;
- if(ctl->portamento.used == 0) //the portamento has finished
- portamento = 0; //this note is no longer "portamented"
- }
-
- //compute parameters for all voices
- for(nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- if(NoteVoicePar[nvoice].Enabled != ON)
- continue;
- NoteVoicePar[nvoice].DelayTicks -= 1;
- if(NoteVoicePar[nvoice].DelayTicks > 0)
- continue;
-
- compute_unison_freq_rap(nvoice);
-
- /*******************/
- /* Voice Amplitude */
- /*******************/
- oldamplitude[nvoice] = newamplitude[nvoice];
- newamplitude[nvoice] = 1.0f;
-
- if(NoteVoicePar[nvoice].AmpEnvelope != NULL)
- newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
-
- if(NoteVoicePar[nvoice].AmpLfo != NULL)
- newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout();
-
- /****************/
- /* Voice Filter */
- /****************/
- if(NoteVoicePar[nvoice].VoiceFilterL != NULL) {
- filterpitch = NoteVoicePar[nvoice].FilterCenterPitch;
-
- if(NoteVoicePar[nvoice].FilterEnvelope != NULL)
- filterpitch += NoteVoicePar[nvoice].FilterEnvelope->envout();
-
- if(NoteVoicePar[nvoice].FilterLfo != NULL)
- filterpitch += NoteVoicePar[nvoice].FilterLfo->lfoout();
-
- filterfreq = filterpitch + NoteVoicePar[nvoice].FilterFreqTracking;
- filterfreq = Filter::getrealfreq(filterfreq);
-
- NoteVoicePar[nvoice].VoiceFilterL->setfreq(filterfreq);
- if(stereo && NoteVoicePar[nvoice].VoiceFilterR)
- NoteVoicePar[nvoice].VoiceFilterR->setfreq(filterfreq);
- }
-
- if(NoteVoicePar[nvoice].noisetype == 0) { //compute only if the voice isn't noise
- /*******************/
- /* Voice Frequency */
- /*******************/
- voicepitch = 0.0f;
- if(NoteVoicePar[nvoice].FreqLfo != NULL)
- voicepitch += NoteVoicePar[nvoice].FreqLfo->lfoout() / 100.0f
- * ctl->bandwidth.relbw;
-
- if(NoteVoicePar[nvoice].FreqEnvelope != NULL)
- voicepitch += NoteVoicePar[nvoice].FreqEnvelope->envout()
- / 100.0f;
- voicefreq = getvoicebasefreq(nvoice)
- * powf(2, (voicepitch + globalpitch) / 12.0f); //Hz frequency
- voicefreq *= ctl->pitchwheel.relfreq; //change the frequency by the controller
- setfreq(nvoice, voicefreq * portamentofreqrap);
-
- /***************/
- /* Modulator */
- /***************/
- if(NoteVoicePar[nvoice].FMEnabled != NONE) {
- FMrelativepitch = NoteVoicePar[nvoice].FMDetune / 100.0f;
- if(NoteVoicePar[nvoice].FMFreqEnvelope != NULL)
- FMrelativepitch +=
- NoteVoicePar[nvoice].FMFreqEnvelope->envout() / 100;
- FMfreq =
- powf(2.0f, FMrelativepitch
- / 12.0f) * voicefreq * portamentofreqrap;
- setfreqFM(nvoice, FMfreq);
-
- FMoldamplitude[nvoice] = FMnewamplitude[nvoice];
- FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume
- * ctl->fmamp.relamp;
- if(NoteVoicePar[nvoice].FMAmpEnvelope != NULL)
- FMnewamplitude[nvoice] *=
- NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
- }
- }
- }
- time += synth->buffersize_f / synth->samplerate_f;
- }
-
-
- /*
- * Fadein in a way that removes clicks but keep sound "punchy"
- */
- inline void ADnote::fadein(float *smps) const
- {
- int zerocrossings = 0;
- for(int i = 1; i < synth->buffersize; ++i)
- if((smps[i - 1] < 0.0f) && (smps[i] > 0.0f))
- zerocrossings++; //this is only the possitive crossings
-
- float tmp = (synth->buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f;
- if(tmp < 8.0f)
- tmp = 8.0f;
-
- int n;
- F2I(tmp, n); //how many samples is the fade-in
- if(n > synth->buffersize)
- n = synth->buffersize;
- for(int i = 0; i < n; ++i) { //fade-in
- float tmp = 0.5f - cosf((float)i / (float) n * PI) * 0.5f;
- smps[i] *= tmp;
- }
- }
-
- /*
- * Computes the Oscillator (Without Modulation) - LinearInterpolation
- */
- inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
- {
- int i, poshi;
- float poslo;
-
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- poshi = oscposhi[nvoice][k];
- poslo = oscposlo[nvoice][k];
- int freqhi = oscfreqhi[nvoice][k];
- float freqlo = oscfreqlo[nvoice][k];
- float *smps = NoteVoicePar[nvoice].OscilSmp;
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i) {
- tw[i] = smps[poshi] * (1.0f - poslo) + smps[poshi + 1] * poslo;
- poslo += freqlo;
- if(poslo >= 1.0f) {
- poslo -= 1.0f;
- poshi++;
- }
- poshi += freqhi;
- poshi &= synth->oscilsize - 1;
- }
- oscposhi[nvoice][k] = poshi;
- oscposlo[nvoice][k] = poslo;
- }
- }
-
-
-
- /*
- * Computes the Oscillator (Without Modulation) - CubicInterpolation
- *
- The differences from the Linear are to little to deserve to be used. This is because I am using a large synth->oscilsize (>512)
- inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){
- int i,poshi;
- float poslo;
-
- poshi=oscposhi[nvoice];
- poslo=oscposlo[nvoice];
- float *smps=NoteVoicePar[nvoice].OscilSmp;
- float xm1,x0,x1,x2,a,b,c;
- for (i=0;i<synth->buffersize;i++){
- xm1=smps[poshi];
- x0=smps[poshi+1];
- x1=smps[poshi+2];
- x2=smps[poshi+3];
- a=(3.0f * (x0-x1) - xm1 + x2) / 2.0f;
- b = 2.0f*x1 + xm1 - (5.0f*x0 + x2) / 2.0f;
- c = (x1 - xm1) / 2.0f;
- tmpwave[i]=(((a * poslo) + b) * poslo + c) * poslo + x0;
- printf("a\n");
- //tmpwave[i]=smps[poshi]*(1.0f-poslo)+smps[poshi+1]*poslo;
- poslo+=oscfreqlo[nvoice];
- if (poslo>=1.0f) {
- poslo-=1.0f;
- poshi++;
- };
- poshi+=oscfreqhi[nvoice];
- poshi&=synth->oscilsize-1;
- };
- oscposhi[nvoice]=poshi;
- oscposlo[nvoice]=poslo;
- };
- */
- /*
- * Computes the Oscillator (Morphing)
- */
- inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice)
- {
- int i;
- float amp;
- ComputeVoiceOscillator_LinearInterpolation(nvoice);
- if(FMnewamplitude[nvoice] > 1.0f)
- FMnewamplitude[nvoice] = 1.0f;
- if(FMoldamplitude[nvoice] > 1.0f)
- FMoldamplitude[nvoice] = 1.0f;
-
- if(NoteVoicePar[nvoice].FMVoice >= 0) {
- //if I use VoiceOut[] as modullator
- int FMVoice = NoteVoicePar[nvoice].FMVoice;
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i) {
- amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice],
- i,
- synth->buffersize);
- tw[i] = tw[i]
- * (1.0f
- - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i];
- }
- }
- }
- else
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- int poshiFM = oscposhiFM[nvoice][k];
- float posloFM = oscposloFM[nvoice][k];
- int freqhiFM = oscfreqhiFM[nvoice][k];
- float freqloFM = oscfreqloFM[nvoice][k];
- float *tw = tmpwave_unison[k];
-
- for(i = 0; i < synth->buffersize; ++i) {
- amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice],
- i,
- synth->buffersize);
- tw[i] = tw[i] * (1.0f - amp) + amp
- * (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1 - posloFM)
- + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM);
- posloFM += freqloFM;
- if(posloFM >= 1.0f) {
- posloFM -= 1.0f;
- poshiFM++;
- }
- poshiFM += freqhiFM;
- poshiFM &= synth->oscilsize - 1;
- }
- oscposhiFM[nvoice][k] = poshiFM;
- oscposloFM[nvoice][k] = posloFM;
- }
- }
-
- /*
- * Computes the Oscillator (Ring Modulation)
- */
- inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice)
- {
- int i;
- float amp;
- ComputeVoiceOscillator_LinearInterpolation(nvoice);
- if(FMnewamplitude[nvoice] > 1.0f)
- FMnewamplitude[nvoice] = 1.0f;
- if(FMoldamplitude[nvoice] > 1.0f)
- FMoldamplitude[nvoice] = 1.0f;
- if(NoteVoicePar[nvoice].FMVoice >= 0)
- // if I use VoiceOut[] as modullator
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i) {
- amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice],
- i,
- synth->buffersize);
- int FMVoice = NoteVoicePar[nvoice].FMVoice;
- tw[i] *= (1.0f - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i];
- }
- }
- else
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- int poshiFM = oscposhiFM[nvoice][k];
- float posloFM = oscposloFM[nvoice][k];
- int freqhiFM = oscfreqhiFM[nvoice][k];
- float freqloFM = oscfreqloFM[nvoice][k];
- float *tw = tmpwave_unison[k];
-
- for(i = 0; i < synth->buffersize; ++i) {
- amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice],
- i,
- synth->buffersize);
- tw[i] *= (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0f - posloFM)
- + NoteVoicePar[nvoice].FMSmp[poshiFM
- + 1] * posloFM) * amp
- + (1.0f - amp);
- posloFM += freqloFM;
- if(posloFM >= 1.0f) {
- posloFM -= 1.0f;
- poshiFM++;
- }
- poshiFM += freqhiFM;
- poshiFM &= synth->oscilsize - 1;
- }
- oscposhiFM[nvoice][k] = poshiFM;
- oscposloFM[nvoice][k] = posloFM;
- }
- }
-
-
-
- /*
- * Computes the Oscillator (Phase Modulation or Frequency Modulation)
- */
- inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,
- int FMmode)
- {
- int carposhi = 0;
- int i, FMmodfreqhi = 0;
- float FMmodfreqlo = 0, carposlo = 0;
-
- if(NoteVoicePar[nvoice].FMVoice >= 0)
- //if I use VoiceOut[] as modulator
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- memcpy(tw, NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut,
- synth->bufferbytes);
- }
- else
- //Compute the modulator and store it in tmpwave_unison[][]
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- int poshiFM = oscposhiFM[nvoice][k];
- float posloFM = oscposloFM[nvoice][k];
- int freqhiFM = oscfreqhiFM[nvoice][k];
- float freqloFM = oscfreqloFM[nvoice][k];
- float *tw = tmpwave_unison[k];
-
- for(i = 0; i < synth->buffersize; ++i) {
- tw[i] =
- (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0f - posloFM)
- + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM);
- posloFM += freqloFM;
- if(posloFM >= 1.0f) {
- posloFM = fmod(posloFM, 1.0f);
- poshiFM++;
- }
- poshiFM += freqhiFM;
- poshiFM &= synth->oscilsize - 1;
- }
- oscposhiFM[nvoice][k] = poshiFM;
- oscposloFM[nvoice][k] = posloFM;
- }
- // Amplitude interpolation
- if(ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice]))
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i)
- tw[i] *= INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice],
- FMnewamplitude[nvoice],
- i,
- synth->buffersize);
- }
- else
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i)
- tw[i] *= FMnewamplitude[nvoice];
- }
-
-
- //normalize: makes all sample-rates, oscil_sizes to produce same sound
- if(FMmode != 0) { //Frequency modulation
- float normalize = synth->oscilsize_f / 262144.0f * 44100.0f
- / synth->samplerate_f;
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- float fmold = FMoldsmp[nvoice][k];
- for(i = 0; i < synth->buffersize; ++i) {
- fmold = fmod(fmold + tw[i] * normalize, synth->oscilsize);
- tw[i] = fmold;
- }
- FMoldsmp[nvoice][k] = fmold;
- }
- }
- else { //Phase modulation
- float normalize = synth->oscilsize_f / 262144.0f;
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(i = 0; i < synth->buffersize; ++i)
- tw[i] *= normalize;
- }
- }
-
- //do the modulation
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- int poshi = oscposhi[nvoice][k];
- float poslo = oscposlo[nvoice][k];
- int freqhi = oscfreqhi[nvoice][k];
- float freqlo = oscfreqlo[nvoice][k];
-
- for(i = 0; i < synth->buffersize; ++i) {
- F2I(tw[i], FMmodfreqhi);
- FMmodfreqlo = fmod(tw[i] + 0.0000000001f, 1.0f);
- if(FMmodfreqhi < 0)
- FMmodfreqlo++;
-
- //carrier
- carposhi = poshi + FMmodfreqhi;
- carposlo = poslo + FMmodfreqlo;
-
- if(carposlo >= 1.0f) {
- carposhi++;
- carposlo = fmod(carposlo, 1.0f);
- }
- carposhi &= (synth->oscilsize - 1);
-
- tw[i] = NoteVoicePar[nvoice].OscilSmp[carposhi]
- * (1.0f - carposlo)
- + NoteVoicePar[nvoice].OscilSmp[carposhi
- + 1] * carposlo;
-
- poslo += freqlo;
- if(poslo >= 1.0f) {
- poslo = fmod(poslo, 1.0f);
- poshi++;
- }
-
- poshi += freqhi;
- poshi &= synth->oscilsize - 1;
- }
- oscposhi[nvoice][k] = poshi;
- oscposlo[nvoice][k] = poslo;
- }
- }
-
-
- /*Calculeaza Oscilatorul cu PITCH MODULATION*/
- inline void ADnote::ComputeVoiceOscillatorPitchModulation(int /*nvoice*/)
- {
- //TODO
- }
-
- /*
- * Computes the Noise
- */
- inline void ADnote::ComputeVoiceNoise(int nvoice)
- {
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- for(int i = 0; i < synth->buffersize; ++i)
- tw[i] = RND * 2.0f - 1.0f;
- }
- }
-
-
-
- /*
- * Compute the ADnote samples
- * Returns 0 if the note is finished
- */
- int ADnote::noteout(float *outl, float *outr)
- {
- memcpy(outl, denormalkillbuf, synth->bufferbytes);
- memcpy(outr, denormalkillbuf, synth->bufferbytes);
-
- if(NoteEnabled == OFF)
- return 0;
-
- memset(bypassl, 0, synth->bufferbytes);
- memset(bypassr, 0, synth->bufferbytes);
- computecurrentparameters();
-
- for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- if((NoteVoicePar[nvoice].Enabled != ON)
- || (NoteVoicePar[nvoice].DelayTicks > 0))
- continue;
- if(NoteVoicePar[nvoice].noisetype == 0) //voice mode=sound
- switch(NoteVoicePar[nvoice].FMEnabled) {
- case MORPH:
- ComputeVoiceOscillatorMorph(nvoice);
- break;
- case RING_MOD:
- ComputeVoiceOscillatorRingModulation(nvoice);
- break;
- case PHASE_MOD:
- ComputeVoiceOscillatorFrequencyModulation(nvoice, 0);
- break;
- case FREQ_MOD:
- ComputeVoiceOscillatorFrequencyModulation(nvoice, 1);
- break;
- //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break;
- default:
- ComputeVoiceOscillator_LinearInterpolation(nvoice);
- //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice);
- }
- else
- ComputeVoiceNoise(nvoice);
- // Voice Processing
-
-
- //mix subvoices into voice
- memset(tmpwavel, 0, synth->bufferbytes);
- if(stereo)
- memset(tmpwaver, 0, synth->bufferbytes);
- for(int k = 0; k < unison_size[nvoice]; ++k) {
- float *tw = tmpwave_unison[k];
- if(stereo) {
- float stereo_pos = 0;
- if(unison_size[nvoice] > 1)
- stereo_pos = k
- / (float)(unison_size[nvoice]
- - 1) * 2.0f - 1.0f;
- float stereo_spread = unison_stereo_spread[nvoice] * 2.0f; //between 0 and 2.0f
- if(stereo_spread > 1.0f) {
- float stereo_pos_1 = (stereo_pos >= 0.0f) ? 1.0f : -1.0f;
- stereo_pos =
- (2.0f
- - stereo_spread) * stereo_pos
- + (stereo_spread - 1.0f) * stereo_pos_1;
- }
- else
- stereo_pos *= stereo_spread;
-
- if(unison_size[nvoice] == 1)
- stereo_pos = 0.0f;
- float panning = (stereo_pos + 1.0f) * 0.5f;
-
-
- float lvol = (1.0f - panning) * 2.0f;
- if(lvol > 1.0f)
- lvol = 1.0f;
-
- float rvol = panning * 2.0f;
- if(rvol > 1.0f)
- rvol = 1.0f;
-
- if(unison_invert_phase[nvoice][k]) {
- lvol = -lvol;
- rvol = -rvol;
- }
-
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwavel[i] += tw[i] * lvol;
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwaver[i] += tw[i] * rvol;
- }
- else
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwavel[i] += tw[i];
- }
-
-
- float unison_amplitude = 1.0f / sqrt(unison_size[nvoice]); //reduce the amplitude for large unison sizes
- // Amplitude
- float oldam = oldamplitude[nvoice] * unison_amplitude;
- float newam = newamplitude[nvoice] * unison_amplitude;
-
- if(ABOVE_AMPLITUDE_THRESHOLD(oldam, newam)) {
- int rest = synth->buffersize;
- //test if the amplitude if raising and the difference is high
- if((newam > oldam) && ((newam - oldam) > 0.25f)) {
- rest = 10;
- if(rest > synth->buffersize)
- rest = synth->buffersize;
- for(int i = 0; i < synth->buffersize - rest; ++i)
- tmpwavel[i] *= oldam;
- if(stereo)
- for(int i = 0; i < synth->buffersize - rest; ++i)
- tmpwaver[i] *= oldam;
- }
- // Amplitude interpolation
- for(int i = 0; i < rest; ++i) {
- float amp = INTERPOLATE_AMPLITUDE(oldam, newam, i, rest);
- tmpwavel[i + (synth->buffersize - rest)] *= amp;
- if(stereo)
- tmpwaver[i + (synth->buffersize - rest)] *= amp;
- }
- }
- else {
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwavel[i] *= newam;
- if(stereo)
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwaver[i] *= newam;
- }
-
- // Fade in
- if(firsttick[nvoice] != 0) {
- fadein(&tmpwavel[0]);
- if(stereo)
- fadein(&tmpwaver[0]);
- firsttick[nvoice] = 0;
- }
-
-
- // Filter
- if(NoteVoicePar[nvoice].VoiceFilterL != NULL)
- NoteVoicePar[nvoice].VoiceFilterL->filterout(&tmpwavel[0]);
- if((stereo) && (NoteVoicePar[nvoice].VoiceFilterR != NULL))
- NoteVoicePar[nvoice].VoiceFilterR->filterout(&tmpwaver[0]);
-
- //check if the amplitude envelope is finished, if yes, the voice will be fadeout
- if(NoteVoicePar[nvoice].AmpEnvelope != NULL)
- if(NoteVoicePar[nvoice].AmpEnvelope->finished() != 0) {
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwavel[i] *= 1.0f - (float)i / synth->buffersize_f;
- if(stereo)
- for(int i = 0; i < synth->buffersize; ++i)
- tmpwaver[i] *= 1.0f - (float)i / synth->buffersize_f;
- }
- //the voice is killed later
-
-
- // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator)
- if(NoteVoicePar[nvoice].VoiceOut != NULL) {
- if(stereo)
- for(int i = 0; i < synth->buffersize; ++i)
- NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i]
- + tmpwaver[i];
- else //mono
- for(int i = 0; i < synth->buffersize; ++i)
- NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i];
- }
-
-
- // Add the voice that do not bypass the filter to out
- if(NoteVoicePar[nvoice].filterbypass == 0) { //no bypass
- if(stereo)
- for(int i = 0; i < synth->buffersize; ++i) { //stereo
- outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume
- * NoteVoicePar[nvoice].Panning * 2.0f;
- outr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume
- * (1.0f - NoteVoicePar[nvoice].Panning) * 2.0f;
- }
- else
- for(int i = 0; i < synth->buffersize; ++i) //mono
- outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume;
- }
- else { //bypass the filter
- if(stereo)
- for(int i = 0; i < synth->buffersize; ++i) { //stereo
- bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume
- * NoteVoicePar[nvoice].Panning * 2.0f;
- bypassr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume
- * (1.0f
- - NoteVoicePar[nvoice].Panning) * 2.0f;
- }
- else
- for(int i = 0; i < synth->buffersize; ++i) //mono
- bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume;
- }
- // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished)
- if(NoteVoicePar[nvoice].AmpEnvelope != NULL)
- if(NoteVoicePar[nvoice].AmpEnvelope->finished() != 0)
- KillVoice(nvoice);
- }
-
-
- //Processing Global parameters
- NoteGlobalPar.GlobalFilterL->filterout(&outl[0]);
-
- if(stereo == 0) { //set the right channel=left channel
- memcpy(outr, outl, synth->bufferbytes);
- memcpy(bypassr, bypassl, synth->bufferbytes);
- }
- else
- NoteGlobalPar.GlobalFilterR->filterout(&outr[0]);
-
- for(int i = 0; i < synth->buffersize; ++i) {
- outl[i] += bypassl[i];
- outr[i] += bypassr[i];
- }
-
- if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude))
- // Amplitude Interpolation
- for(int i = 0; i < synth->buffersize; ++i) {
- float tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude,
- globalnewamplitude,
- i,
- synth->buffersize);
- outl[i] *= tmpvol * NoteGlobalPar.Panning;
- outr[i] *= tmpvol * (1.0f - NoteGlobalPar.Panning);
- }
- else
- for(int i = 0; i < synth->buffersize; ++i) {
- outl[i] *= globalnewamplitude * NoteGlobalPar.Panning;
- outr[i] *= globalnewamplitude * (1.0f - NoteGlobalPar.Panning);
- }
-
- //Apply the punch
- if(NoteGlobalPar.Punch.Enabled != 0)
- for(int i = 0; i < synth->buffersize; ++i) {
- float punchamp = NoteGlobalPar.Punch.initialvalue
- * NoteGlobalPar.Punch.t + 1.0f;
- outl[i] *= punchamp;
- outr[i] *= punchamp;
- NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt;
- if(NoteGlobalPar.Punch.t < 0.0f) {
- NoteGlobalPar.Punch.Enabled = 0;
- break;
- }
- }
-
-
- // Apply legato-specific sound signal modifications
- legato.apply(*this, outl, outr);
-
-
- // Check if the global amplitude is finished.
- // If it does, disable the note
- if(NoteGlobalPar.AmpEnvelope->finished()) {
- for(int i = 0; i < synth->buffersize; ++i) { //fade-out
- float tmp = 1.0f - (float)i / synth->buffersize_f;
- outl[i] *= tmp;
- outr[i] *= tmp;
- }
- KillNote();
- }
- return 1;
- }
-
-
- /*
- * Relase the key (NoteOff)
- */
- void ADnote::relasekey()
- {
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
- NoteVoicePar[nvoice].releasekey();
- NoteGlobalPar.FreqEnvelope->relasekey();
- NoteGlobalPar.FilterEnvelope->relasekey();
- NoteGlobalPar.AmpEnvelope->relasekey();
- }
-
- /*
- * Check if the note is finished
- */
- int ADnote::finished() const
- {
- if(NoteEnabled == ON)
- return 0;
- else
- return 1;
- }
-
- void ADnote::Voice::releasekey()
- {
- if(!Enabled)
- return;
- if(AmpEnvelope)
- AmpEnvelope->relasekey();
- if(FreqEnvelope)
- FreqEnvelope->relasekey();
- if(FilterEnvelope)
- FilterEnvelope->relasekey();
- if(FMFreqEnvelope)
- FMFreqEnvelope->relasekey();
- if(FMAmpEnvelope)
- FMAmpEnvelope->relasekey();
- }
-
- template<class T>
- static inline void nullify(T &t) {delete t; t = NULL; }
- template<class T>
- static inline void arrayNullify(T &t) {delete [] t; t = NULL; }
-
- void ADnote::Voice::kill()
- {
- arrayNullify(OscilSmp);
- nullify(FreqEnvelope);
- nullify(FreqLfo);
- nullify(AmpEnvelope);
- nullify(AmpLfo);
- nullify(VoiceFilterL);
- nullify(VoiceFilterR);
- nullify(FilterEnvelope);
- nullify(FilterLfo);
- nullify(FMFreqEnvelope);
- nullify(FMAmpEnvelope);
-
- if((FMEnabled != NONE) && (FMVoice < 0)) {
- delete[] FMSmp;
- FMSmp = NULL;
- }
-
- if(VoiceOut)
- memset(VoiceOut, 0, synth->bufferbytes);
- //do not delete, yet: perhaps is used by another voice
-
- Enabled = OFF;
- }
-
- void ADnote::Global::kill()
- {
- nullify(FreqEnvelope);
- nullify(FreqLfo);
- nullify(AmpEnvelope);
- nullify(AmpLfo);
- nullify(GlobalFilterL);
- nullify(GlobalFilterR);
- nullify(FilterEnvelope);
- nullify(FilterLfo);
- }
-
- void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m,
- float basefreq, float velocity,
- bool stereo)
- {
- FreqEnvelope = new Envelope(param.FreqEnvelope, basefreq);
- FreqLfo = new LFO(param.FreqLfo, basefreq);
-
- AmpEnvelope = new Envelope(param.AmpEnvelope, basefreq);
- AmpLfo = new LFO(param.AmpLfo, basefreq);
-
- Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB
- * VelF(velocity, param.PAmpVelocityScaleFunction); //sensing
-
- GlobalFilterL = Filter::generate(param.GlobalFilter);
- if(stereo)
- GlobalFilterR = Filter::generate(param.GlobalFilter);
- else
- GlobalFilterR = NULL;
-
- FilterEnvelope = new Envelope(param.FilterEnvelope, basefreq);
- FilterLfo = new LFO(param.FilterLfo, basefreq);
- FilterQ = param.GlobalFilter->getq();
- FilterFreqTracking = param.GlobalFilter->getfreqtracking(basefreq);
- }
|