/* 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 #include #include #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;nvoiceVoicePar[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;iVoicePar[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;iGlobalPar.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=i) NoteVoicePar[i].FMVoice=-1; // Voice Parameter init for (nvoice=0;nvoiceVoicePar[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;iVoicePar[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;nvoiceOSCIL_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;nvoice0) 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;i0.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=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=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=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=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=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=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;i0)) 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;ifilterout(&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;ifinished()!=0) KillVoice(nvoice); }; }; //Processing Global parameters NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); if (stereo==0) { for (i=0;ifilterout(&outr[0]); for (i=0;ifinished()!=0) { for (i=0;irelasekey(); 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); };