summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C')
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C984
1 files changed, 984 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C
new file mode 100644
index 00000000..574e2bea
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C
@@ -0,0 +1,984 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ ADnote.C - 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) 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 <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#include "../globals.h"
+#include "../Misc/Util.h"
+#include "ADnote.h"
+
+
+ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_){
+ ready=0;
+
+ tmpwave=new REALTYPE [SOUND_BUFFER_SIZE];
+ bypassl=new REALTYPE [SOUND_BUFFER_SIZE];
+ bypassr=new REALTYPE [SOUND_BUFFER_SIZE];
+
+ partparams=pars;
+ ctl=ctl_;
+ portamento=portamento_;
+ midinote=midinote_;
+ NoteEnabled=ON;
+ basefreq=freq;
+ if (velocity>1.0) velocity=1.0;
+ this->velocity=velocity;
+ time=0.0;
+ 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.0;
+
+
+ NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq
+ pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing
+ (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1);
+
+ if (pars->GlobalPar.PPunchStrength!=0) {
+ NoteGlobalPar.Punch.Enabled=1;
+ NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0
+ NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0)
+ *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) );
+ REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms
+ REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0);
+ NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch);
+ } else NoteGlobalPar.Punch.Enabled=0;
+
+ for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ pars->VoicePar[nvoice].OscilSmp->newrandseed(rand());
+ NoteVoicePar[nvoice].OscilSmp=NULL;
+ NoteVoicePar[nvoice].FMSmp=NULL;
+ NoteVoicePar[nvoice].VoiceOut=NULL;
+
+ NoteVoicePar[nvoice].FMVoice=-1;
+
+ if (pars->VoicePar[nvoice].Enabled==0) {
+ NoteVoicePar[nvoice].Enabled=OFF;
+ continue; //the voice is disabled
+ };
+
+ 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);
+ };
+
+ oscposhi[nvoice]=0;oscposlo[nvoice]=0.0;
+ oscposhiFM[nvoice]=0;oscposloFM[nvoice]=0.0;
+
+ NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point
+
+ //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(rand());
+ oscposhi[nvoice]=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[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i];
+
+ oscposhi[nvoice]+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
+ oscposhi[nvoice]%=OSCIL_SIZE;
+
+
+ NoteVoicePar[nvoice].FreqLfo=NULL;
+ NoteVoicePar[nvoice].FreqEnvelope=NULL;
+
+ NoteVoicePar[nvoice].AmpLfo=NULL;
+ NoteVoicePar[nvoice].AmpEnvelope=NULL;
+
+ NoteVoicePar[nvoice].VoiceFilter=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)
+ REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0);
+ switch (NoteVoicePar[nvoice].FMEnabled){
+ case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0);
+ NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0;
+ break;
+ case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0;
+ break;
+ // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//???????????
+ // break;
+ default:if (fmvoldamp>1.0) fmvoldamp=1.0;
+ NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp;
+ };
+
+ //Voice's modulator velocity sensing
+ NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
+
+ FMoldsmp[nvoice]=0.0;//this is for FM (integration)
+
+ firsttick[nvoice]=1;
+ NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE);
+ };
+
+ initparameters();
+ ready=1;
+};
+
+
+/*
+ * Kill a voice of ADnote
+ */
+void ADnote::KillVoice(int nvoice){
+
+ delete (NoteVoicePar[nvoice].OscilSmp);
+
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope);
+ NoteVoicePar[nvoice].FreqEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo);
+ NoteVoicePar[nvoice].FreqLfo=NULL;
+
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope);
+ NoteVoicePar[nvoice].AmpEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].AmpLfo!=NULL) delete (NoteVoicePar[nvoice].AmpLfo);
+ NoteVoicePar[nvoice].AmpLfo=NULL;
+
+ if (NoteVoicePar[nvoice].VoiceFilter!=NULL) delete (NoteVoicePar[nvoice].VoiceFilter);
+ NoteVoicePar[nvoice].VoiceFilter=NULL;
+
+ if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) delete (NoteVoicePar[nvoice].FilterEnvelope);
+ NoteVoicePar[nvoice].FilterEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FilterLfo!=NULL) delete (NoteVoicePar[nvoice].FilterLfo);
+ NoteVoicePar[nvoice].FilterLfo=NULL;
+
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMFreqEnvelope);
+ NoteVoicePar[nvoice].FMFreqEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMAmpEnvelope);
+ NoteVoicePar[nvoice].FMAmpEnvelope=NULL;
+
+ if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) delete NoteVoicePar[nvoice].FMSmp;
+
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL)
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;//do not delete, yet: perhaps is used by another voice
+
+ NoteVoicePar[nvoice].Enabled=OFF;
+};
+
+/*
+ * Kill the note
+ */
+void ADnote::KillNote(){
+ int nvoice;
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled==ON) KillVoice(nvoice);
+
+ //delete VoiceOut
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL) delete(NoteVoicePar[nvoice].VoiceOut);
+ NoteVoicePar[nvoice].VoiceOut=NULL;
+ };
+
+ delete (NoteGlobalPar.FreqEnvelope);
+ delete (NoteGlobalPar.FreqLfo);
+ delete (NoteGlobalPar.AmpEnvelope);
+ delete (NoteGlobalPar.AmpLfo);
+ delete (NoteGlobalPar.GlobalFilterL);
+ if (stereo!=0) delete (NoteGlobalPar.GlobalFilterR);
+ delete (NoteGlobalPar.FilterEnvelope);
+ delete (NoteGlobalPar.FilterLfo);
+
+ NoteEnabled=OFF;
+};
+
+ADnote::~ADnote(){
+ if (NoteEnabled==ON) KillNote();
+ delete [] tmpwave;
+ delete [] bypassl;
+ delete [] bypassr;
+};
+
+
+/*
+ * Init the parameters
+ */
+void ADnote::initparameters(){
+ int nvoice,i,tmp[NUM_VOICES];
+
+ // Global Parameters
+ NoteGlobalPar.FreqEnvelope=new Envelope(partparams->GlobalPar.FreqEnvelope,basefreq);
+ NoteGlobalPar.FreqLfo=new LFO(partparams->GlobalPar.FreqLfo,basefreq);
+
+ NoteGlobalPar.AmpEnvelope=new Envelope(partparams->GlobalPar.AmpEnvelope,basefreq);
+ NoteGlobalPar.AmpLfo=new LFO(partparams->GlobalPar.AmpLfo,basefreq);
+
+ NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB
+ *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing
+
+ NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output
+ globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
+
+ NoteGlobalPar.GlobalFilterL=new Filter(partparams->GlobalPar.GlobalFilter);
+ if (stereo!=0) NoteGlobalPar.GlobalFilterR=new Filter(partparams->GlobalPar.GlobalFilter);
+
+ NoteGlobalPar.FilterEnvelope=new Envelope(partparams->GlobalPar.FilterEnvelope,basefreq);
+ NoteGlobalPar.FilterLfo=new LFO(partparams->GlobalPar.FilterLfo,basefreq);
+ 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 (i=0;i<NUM_VOICES;i++) if (NoteVoicePar[i].FMVoice>=i) NoteVoicePar[i].FMVoice=-1;
+
+ // Voice Parameter init
+ for (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=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -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.0;
+
+ newamplitude[nvoice]=1.0;
+ if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) {
+ NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq);
+ NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
+ };
+
+ if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0){
+ NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq);
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout();
+ };
+
+ /* Voice Frequency Parameters Init */
+ if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq);
+
+ if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq);
+
+ /* Voice Filter Parameters Init */
+ if (partparams->VoicePar[nvoice].PFilterEnabled!=0){
+ NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter);
+ };
+
+ if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq);
+
+ if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0)
+ NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq);
+
+ 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(rand());
+ NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];
+
+ //Perform Anti-aliasing only on MORPH or RING MODULATION
+
+ int vc=nvoice;
+ if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil;
+
+ REALTYPE tmp=1.0;
+ if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)||
+ (NoteVoicePar[nvoice].FMEnabled==MORPH)||
+ (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){
+ tmp=getFMvoicebasefreq(nvoice);
+ };
+ if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand());
+
+ oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE;
+ for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i];
+ oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
+ oscposhiFM[nvoice]%=OSCIL_SIZE;
+ };
+
+ if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq);
+
+ FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp;
+
+ if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0){
+ NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq);
+ FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
+ };
+ };
+
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0;
+ for (i=nvoice+1;i<NUM_VOICES;i++)
+ if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)){
+ NoteVoicePar[nvoice].VoiceOut=new REALTYPE[SOUND_BUFFER_SIZE];
+ tmp[i]=1;
+ };
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;
+ };
+};
+
+
+
+/*
+ * Computes the frequency of an oscillator
+ */
+void ADnote::setfreq(int nvoice,REALTYPE freq){
+ REALTYPE speed;
+ freq=fabs(freq);
+ speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
+ if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
+
+ F2I(speed,oscfreqhi[nvoice]);
+ oscfreqlo[nvoice]=speed-floor(speed);
+};
+
+/*
+ * Computes the frequency of an modullator oscillator
+ */
+void ADnote::setfreqFM(int nvoice,REALTYPE freq){
+ REALTYPE speed;
+ freq=fabs(freq);
+ speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
+ if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
+
+ F2I(speed,oscfreqhiFM[nvoice]);
+ oscfreqloFM[nvoice]=speed-floor(speed);
+};
+
+/*
+ * Get Voice base frequency
+ */
+REALTYPE ADnote::getvoicebasefreq(int nvoice){
+ REALTYPE detune=NoteVoicePar[nvoice].Detune/100.0+
+ NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+
+ NoteGlobalPar.Detune/100.0;
+
+ if (NoteVoicePar[nvoice].fixedfreq==0) return(this->basefreq*pow(2,detune/12.0));
+ else {//the fixed freq is enabled
+ REALTYPE fixedfreq=440.0;
+ int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET;
+ if (fixedfreqET!=0) {//if the frequency varies according the keyboard note
+ REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0);
+ if (fixedfreqET<=64) fixedfreq*=pow(2.0,tmp);
+ else fixedfreq*=pow(3.0,tmp);
+ };
+ return(fixedfreq*pow(2.0,detune/12.0));
+ };
+};
+
+/*
+ * Get Voice's Modullator base frequency
+ */
+REALTYPE ADnote::getFMvoicebasefreq(int nvoice){
+ REALTYPE detune=NoteVoicePar[nvoice].FMDetune/100.0;
+ return(getvoicebasefreq(nvoice)*pow(2,detune/12.0));
+};
+
+/*
+ * Computes all the parameters for each tick
+ */
+void ADnote::computecurrentparameters(){
+ int nvoice;
+ REALTYPE voicefreq,voicepitch,filterpitch,filterfreq,FMfreq,FMrelativepitch,globalpitch,globalfilterpitch;
+ globalpitch=0.01*(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;
+
+ REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq
+ +NoteGlobalPar.FilterFreqTracking;
+
+ tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq);
+
+ REALTYPE 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
+ REALTYPE portamentofreqrap=1.0;
+ 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;
+
+ /*******************/
+ /* Voice Amplitude */
+ /*******************/
+ oldamplitude[nvoice]=newamplitude[nvoice];
+ newamplitude[nvoice]=1.0;
+
+ 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].VoiceFilter!=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=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq);
+
+ NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq);
+ };
+
+ if (NoteVoicePar[nvoice].noisetype==0){//compute only if the voice isn't noise
+
+ /*******************/
+ /* Voice Frequency */
+ /*******************/
+ voicepitch=0.0;
+ if (NoteVoicePar[nvoice].FreqLfo!=NULL)
+ voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0
+ *ctl->bandwidth.relbw;
+
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0;
+ voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//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.0;
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100;
+ FMfreq=pow(2.0,FMrelativepitch/12.0)*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+=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
+};
+
+
+/*
+ * Fadein in a way that removes clicks but keep sound "punchy"
+ */
+inline void ADnote::fadein(REALTYPE *smps){
+ int zerocrossings=0;
+ for (int i=1;i<SOUND_BUFFER_SIZE;i++)
+ if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings
+
+ REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0;
+ if (tmp<8.0) tmp=8.0;
+
+ int n;
+ F2I(tmp,n);//how many samples is the fade-in
+ if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE;
+ for (int i=0;i<n;i++) {//fade-in
+ REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5;
+ smps[i]*=tmp;
+ };
+};
+
+/*
+ * Computes the Oscillator (Without Modulation) - LinearInterpolation
+ */
+inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice){
+ int i,poshi;
+ REALTYPE poslo;
+
+ poshi=oscposhi[nvoice];
+ poslo=oscposlo[nvoice];
+ REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
+ poslo+=oscfreqlo[nvoice];
+ if (poslo>=1.0) {
+ poslo-=1.0;
+ poshi++;
+ };
+ poshi+=oscfreqhi[nvoice];
+ poshi&=OSCIL_SIZE-1;
+ };
+ oscposhi[nvoice]=poshi;
+ oscposlo[nvoice]=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 OSCIL_SIZE (>512)
+inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){
+ int i,poshi;
+ REALTYPE poslo;
+
+ poshi=oscposhi[nvoice];
+ poslo=oscposlo[nvoice];
+ REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
+ REALTYPE xm1,x0,x1,x2,a,b,c;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ xm1=smps[poshi];
+ x0=smps[poshi+1];
+ x1=smps[poshi+2];
+ x2=smps[poshi+3];
+ a=(3.0 * (x0-x1) - xm1 + x2) / 2.0;
+ b = 2.0*x1 + xm1 - (5.0*x0 + x2) / 2.0;
+ c = (x1 - xm1) / 2.0;
+ tmpwave[i]=(((a * poslo) + b) * poslo + c) * poslo + x0;
+ printf("a\n");
+ //tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
+ poslo+=oscfreqlo[nvoice];
+ if (poslo>=1.0) {
+ poslo-=1.0;
+ poshi++;
+ };
+ poshi+=oscfreqhi[nvoice];
+ poshi&=OSCIL_SIZE-1;
+ };
+ oscposhi[nvoice]=poshi;
+ oscposlo[nvoice]=poslo;
+};
+*/
+/*
+ * Computes the Oscillator (Morphing)
+ */
+inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice){
+ int i;
+ REALTYPE amp;
+ ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
+ if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
+
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ //if I use VoiceOut[] as modullator
+ int FMVoice=NoteVoicePar[nvoice].FMVoice;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]=tmpwave[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
+ };
+ } else {
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]=tmpwave[i]*(1.0-amp)+amp
+ *(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM-=1.0;
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+};
+
+/*
+ * Computes the Oscillator (Ring Modulation)
+ */
+inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice){
+ int i;
+ REALTYPE amp;
+ ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
+ if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ // if I use VoiceOut[] as modullator
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ int FMVoice=NoteVoicePar[nvoice].FMVoice;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++)
+ tmpwave[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
+ };
+ } else {
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp
+ +(1.0-amp);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM-=1.0;
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+};
+
+
+
+/*
+ * Computes the Oscillator (Phase Modulation or Frequency Modulation)
+ */
+inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode){
+ int carposhi;
+ int i,FMmodfreqhi;
+ REALTYPE FMmodfreqlo,carposlo;
+
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ //if I use VoiceOut[] as modulator
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i];
+ } else {
+ //Compute the modulator and store it in tmpwave[]
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM=fmod(posloFM,1.0);
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+ // Amplitude interpolation
+ if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ };
+ } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=FMnewamplitude[nvoice];
+
+
+ //normalize makes all sample-rates, oscil_sizes toproduce same sound
+ if (FMmode!=0){//Frequency modulation
+ REALTYPE normalize=OSCIL_SIZE/262144.0*44100.0/(REALTYPE)SAMPLE_RATE;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ FMoldsmp[nvoice]=fmod(FMoldsmp[nvoice]+tmpwave[i]*normalize,OSCIL_SIZE);
+ tmpwave[i]=FMoldsmp[nvoice];
+ };
+ } else {//Phase modulation
+ REALTYPE normalize=OSCIL_SIZE/262144.0;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=normalize;
+ };
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ F2I(tmpwave[i],FMmodfreqhi);
+ FMmodfreqlo=fmod(tmpwave[i]+0.0000000001,1.0);
+ if (FMmodfreqhi<0) FMmodfreqlo++;
+
+ //carrier
+ carposhi=oscposhi[nvoice]+FMmodfreqhi;
+ carposlo=oscposlo[nvoice]+FMmodfreqlo;
+
+ if (carposlo>=1.0) {
+ carposhi++;
+ carposlo=fmod(carposlo,1.0);
+ };
+ carposhi&=(OSCIL_SIZE-1);
+
+ tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo)
+ +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo;
+
+ oscposlo[nvoice]+=oscfreqlo[nvoice];
+ if (oscposlo[nvoice]>=1.0) {
+ oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0);
+ oscposhi[nvoice]++;
+ };
+
+ oscposhi[nvoice]+=oscfreqhi[nvoice];
+ oscposhi[nvoice]&=OSCIL_SIZE-1;
+ };
+};
+
+
+/*Calculeaza Oscilatorul cu PITCH MODULATION*/
+inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice){
+//TODO
+};
+
+/*
+ * Computes the Noise
+ */
+inline void ADnote::ComputeVoiceNoise(int nvoice){
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=RND*2.0-1.0;
+};
+
+
+
+/*
+ * Compute the ADnote samples
+ * Returns 0 if the note is finished
+ */
+int ADnote::noteout(REALTYPE *outl,REALTYPE *outr){
+ int i,nvoice;
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]=denormalkillbuf[i];
+ outr[i]=denormalkillbuf[i];
+ };
+
+ if (NoteEnabled==OFF) return(0);
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ bypassl[i]=0.0;
+ bypassr[i]=0.0;
+ };
+
+ computecurrentparameters();
+
+ for (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
+
+ // Amplitude
+ if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])){
+ int rest=SOUND_BUFFER_SIZE;
+ //test if the amplitude if raising and the difference is high
+ if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)){
+ rest=10;
+ if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE;
+ for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwave[i]*=oldamplitude[nvoice];
+ };
+ // Amplitude interpolation
+ for (i=0;i<rest;i++){
+ tmpwave[i+(SOUND_BUFFER_SIZE-rest)]*=INTERPOLATE_AMPLITUDE(oldamplitude[nvoice]
+ ,newamplitude[nvoice],i,rest);
+ };
+ } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=newamplitude[nvoice];
+
+ // Fade in
+ if (firsttick[nvoice]!=0){
+ fadein(&tmpwave[0]);
+ firsttick[nvoice]=0;
+ };
+
+
+ // Filter
+ if (NoteVoicePar[nvoice].VoiceFilter!=NULL) NoteVoicePar[nvoice].VoiceFilter->filterout(&tmpwave[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 (i=0;i<SOUND_BUFFER_SIZE;i++)
+ tmpwave[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ //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)
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwave[i];
+
+
+ // Add the voice that do not bypass the filter to out
+ if (NoteVoicePar[nvoice].filterbypass==0){//no bypass
+ if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
+ else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
+ outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
+ outr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
+ };
+ } else {//bypass the filter
+ if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
+ else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
+ bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
+ bypassr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
+ };
+ };
+ // 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) {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {//set the right channel=left channel
+ outr[i]=outl[i];
+ bypassr[i]=bypassl[i];
+ }
+ } else NoteGlobalPar.GlobalFilterR->filterout(&outr[0]);
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]+=bypassl[i];
+ outr[i]+=bypassr[i];
+ };
+
+ if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){
+ // Amplitude Interpolation
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude
+ ,globalnewamplitude,i,SOUND_BUFFER_SIZE);
+ outl[i]*=tmpvol*NoteGlobalPar.Panning;
+ outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning);
+ };
+ } else {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]*=globalnewamplitude*NoteGlobalPar.Panning;
+ outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning);
+ };
+ };
+
+ //Apply the punch
+ if (NoteGlobalPar.Punch.Enabled!=0){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0;
+ outl[i]*=punchamp;
+ outr[i]*=punchamp;
+ NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt;
+ if (NoteGlobalPar.Punch.t<0.0) {
+ NoteGlobalPar.Punch.Enabled=0;
+ break;
+ };
+ };
+ };
+
+ // Check if the global amplitude is finished.
+ // If it does, disable the note
+ if (NoteGlobalPar.AmpEnvelope->finished()!=0) {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out
+ REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ outl[i]*=tmp;
+ outr[i]*=tmp;
+ };
+ KillNote();
+ };
+ return(1);
+};
+
+
+/*
+ * Relase the key (NoteOff)
+ */
+void ADnote::relasekey(){
+int nvoice;
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled==0) continue;
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) NoteVoicePar[nvoice].AmpEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey();
+ };
+ NoteGlobalPar.FreqEnvelope->relasekey();
+ NoteGlobalPar.FilterEnvelope->relasekey();
+ NoteGlobalPar.AmpEnvelope->relasekey();
+
+};
+
+/*
+ * Check if the note is finished
+ */
+int ADnote::finished(){
+ if (NoteEnabled==ON) return(0);
+ else return(1);
+};
+
+
+