From 3570151d2664cdc79136ec2b7e38dfc6cb11f094 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 21 Sep 2009 00:04:20 +0300 Subject: [PATCH] Started to add the unison effect to ADsynth (cherry picked from commit ae7d0b438ab9082d32b3e551657fab1012d9d2c3) --- plugins/zynaddsubfx/src/Synth/ADnote.cpp | 565 +++++++++++++++-------- plugins/zynaddsubfx/src/Synth/ADnote.h | 25 +- 2 files changed, 387 insertions(+), 203 deletions(-) diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.cpp b/plugins/zynaddsubfx/src/Synth/ADnote.cpp index d6a0b7bdf..883678016 100644 --- a/plugins/zynaddsubfx/src/Synth/ADnote.cpp +++ b/plugins/zynaddsubfx/src/Synth/ADnote.cpp @@ -33,7 +33,8 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve { ready=0; - tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; + tmpwavel=new REALTYPE [SOUND_BUFFER_SIZE]; + tmpwaver=new REALTYPE [SOUND_BUFFER_SIZE]; bypassl=new REALTYPE [SOUND_BUFFER_SIZE]; bypassr=new REALTYPE [SOUND_BUFFER_SIZE]; @@ -83,18 +84,40 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve } else NoteGlobalPar.Punch.Enabled=0; for (int nvoice=0;nvoiceVoicePar[nvoice].OscilSmp->newrandseed(rand()); + pars->VoicePar[nvoice].OscilSmp->newrandseed(rand()); 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 }; +#warning get from parameter + int unison=30; + unison_size[nvoice]=unison; + + unison_freq_rap[nvoice]=new REALTYPE[unison]; + for (int k=0;kVoicePar[nvoice].Pfixedfreq; NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; @@ -119,10 +142,13 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); }; - oscposhi[nvoice]=0; - oscposlo[nvoice]=0.0; - oscposhiFM[nvoice]=0; - oscposloFM[nvoice]=0.0; + + for (int k=0;kVoicePar[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); + 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;iVoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - oscposhi[nvoice]%=OSCIL_SIZE; + oscposhi_start+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + oscposhi_start%=OSCIL_SIZE; + for (int k=0;kVoicePar[nvoice].PFMVelocityScaleFunction); - FMoldsmp[nvoice]=0.0;//this is for FM (integration) + FMoldsmp[nvoice]=new REALTYPE [unison]; + for (int k=0;kVoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + + }; + max_unison=1; + for (int nvoice=0;nvoicemax_unison) max_unison=unison_size[nvoice]; + }; + + tmpwave_unison=new REALTYPE*[max_unison]; + for (int k=0;kVoicePar[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); 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 @@ -325,6 +367,10 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + + +#warning TODO: ADD HERE THE CODE FOR UNISON + }; /// initparameters(); @@ -426,22 +472,36 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int void ADnote::KillVoice(int nvoice) { - delete []NoteVoicePar[nvoice].OscilSmp; + delete []oscfreqhi[nvoice]; + delete []oscfreqlo[nvoice]; + delete []oscfreqhiFM[nvoice]; + delete []oscfreqloFM[nvoice]; + delete []oscposhi[nvoice]; + delete []oscposlo[nvoice]; + delete []oscposhiFM[nvoice]; + delete []oscposloFM[nvoice]; - if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope); - NoteVoicePar[nvoice].FreqEnvelope=NULL; + delete []NoteVoicePar[nvoice].OscilSmp; + delete []unison_freq_rap[nvoice]; + delete []FMoldsmp[nvoice]; - if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo); - NoteVoicePar[nvoice].FreqLfo=NULL; + if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope); + NoteVoicePar[nvoice].FreqEnvelope=NULL; - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope); + 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].VoiceFilterL!=NULL) delete (NoteVoicePar[nvoice].VoiceFilterL); + NoteVoicePar[nvoice].VoiceFilterL=NULL; + + if (NoteVoicePar[nvoice].VoiceFilterR!=NULL) delete (NoteVoicePar[nvoice].VoiceFilterR); + NoteVoicePar[nvoice].VoiceFilterR=NULL; if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) delete (NoteVoicePar[nvoice].FilterEnvelope); NoteVoicePar[nvoice].FilterEnvelope=NULL; @@ -492,9 +552,14 @@ void ADnote::KillNote() ADnote::~ADnote() { if (NoteEnabled==ON) KillNote(); - delete [] tmpwave; + delete [] tmpwavel; + delete [] tmpwaver; delete [] bypassl; delete [] bypassr; + for (int k=0;kVoicePar[nvoice].PFilterEnabled!=0) { - NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter); + NoteVoicePar[nvoice].VoiceFilterL=new Filter(partparams->VoicePar[nvoice].VoiceFilter); + NoteVoicePar[nvoice].VoiceFilterR=new Filter(partparams->VoicePar[nvoice].VoiceFilter); }; if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0) @@ -593,10 +659,15 @@ void ADnote::initparameters() }; 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 k=0;kVoicePar[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; + int oscposhiFM_add=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + for (int k=0;kVoicePar[nvoice].PFMFreqEnvelopeEnabled!=0) @@ -628,13 +699,15 @@ void ADnote::initparameters() */ 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; + for (int k=0;kOSCIL_SIZE) speed=OSCIL_SIZE; - F2I(speed,oscfreqhi[nvoice]); - oscfreqlo[nvoice]=speed-floor(speed); + F2I(speed,oscfreqhi[nvoice][k]); + oscfreqlo[nvoice][k]=speed-floor(speed); + }; }; /* @@ -642,13 +715,15 @@ void ADnote::setfreq(int nvoice,REALTYPE freq) */ 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; + for (int k=0;kOSCIL_SIZE) speed=OSCIL_SIZE; - F2I(speed,oscfreqhiFM[nvoice]); - oscfreqloFM[nvoice]=speed-floor(speed); + F2I(speed,oscfreqhiFM[nvoice][k]); + oscfreqloFM[nvoice][k]=speed-floor(speed); + }; }; /* @@ -736,7 +811,7 @@ void ADnote::computecurrentparameters() /****************/ /* Voice Filter */ /****************/ - if (NoteVoicePar[nvoice].VoiceFilter!=NULL) { + if (NoteVoicePar[nvoice].VoiceFilterL!=NULL) { filterpitch=NoteVoicePar[nvoice].FilterCenterPitch; if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) @@ -746,9 +821,10 @@ void ADnote::computecurrentparameters() filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout(); filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking; - filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq); + filterfreq=NoteVoicePar[nvoice].VoiceFilterL->getrealfreq(filterfreq); - NoteVoicePar[nvoice].VoiceFilter->setfreq(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 @@ -815,22 +891,27 @@ 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=1.0) { - poslo-=1.0; - poshi++; - }; - poshi+=oscfreqhi[nvoice]; - poshi&=OSCIL_SIZE-1; - }; - oscposhi[nvoice]=poshi; - oscposlo[nvoice]=poslo; + + for (int k=0;k=1.0) { + poslo-=1.0; + poshi++; + }; + poshi+=freqhi; + poshi&=OSCIL_SIZE-1; + }; + oscposhi[nvoice][k]=poshi; + oscposlo[nvoice][k]=poslo; + }; }; @@ -881,35 +962,43 @@ inline void ADnote::ComputeVoiceOscillatorMorph(int 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=0) { + //if I use VoiceOut[] as modullator + int FMVoice=NoteVoicePar[nvoice].FMVoice; + for (int k=0;k=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; - }; + for (i=0;i=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=freqhiFM; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice][k]=poshiFM; + oscposloFM[nvoice][k]=posloFM; + }; + }; }; /* @@ -922,36 +1011,44 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) 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=0) { + // if I use VoiceOut[] as modullator + for (int k=0;k=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; - }; + for (i=0;i=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=freqhiFM; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice][k]=poshiFM; + oscposloFM[nvoice][k]=posloFM; + }; + }; }; @@ -961,80 +1058,116 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) */ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode) { - int carposhi; - int i,FMmodfreqhi; - REALTYPE FMmodfreqlo,carposlo; + int carposhi=0; + int i,FMmodfreqhi=0; + REALTYPE FMmodfreqlo=0,carposlo=0; 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; - }; + for (i=0;i=1.0) { + posloFM=fmod(posloFM,1.0); + poshiFM++; + }; + poshiFM+=freqhiFM; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice][k]=poshiFM; + oscposloFM[nvoice][k]=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); + //carrier + carposhi=poshi+FMmodfreqhi; + carposlo=poslo+FMmodfreqlo; - tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) - +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; + if (carposlo>=1.0) { + carposhi++; + carposlo=fmod(carposlo,1.0); + }; + carposhi&=(OSCIL_SIZE-1); - oscposlo[nvoice]+=oscfreqlo[nvoice]; - if (oscposlo[nvoice]>=1.0) { - oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0); - oscposhi[nvoice]++; - }; + tw[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) + +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; - oscposhi[nvoice]+=oscfreqhi[nvoice]; - oscposhi[nvoice]&=OSCIL_SIZE-1; - }; + poslo+=freqlo; + if (poslo>=1.0) { + poslo=fmod(freqlo,1.0); + poshi++; + }; + + poshi+=freqhi; + poshi&=OSCIL_SIZE-1; + }; + oscposhi[nvoice][k]=poshi; + oscposlo[nvoice][k]=poslo; + + }; }; @@ -1049,7 +1182,10 @@ inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice) */ inline void ADnote::ComputeVoiceNoise(int nvoice) { - for (int i=0;ioldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)) { + if ((newam>oldam)&&((newam-oldam)>0.25)) { rest=10; if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE; - for (int i=0;ifilterout(&tmpwave[0]); + 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 (i=0;ifinished()!=0) KillVoice(nvoice); diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.h b/plugins/zynaddsubfx/src/Synth/ADnote.h index 1ec25832e..edb14500f 100644 --- a/plugins/zynaddsubfx/src/Synth/ADnote.h +++ b/plugins/zynaddsubfx/src/Synth/ADnote.h @@ -178,7 +178,8 @@ private: * FILTER PARAMETERS * *************************/ - Filter *VoiceFilter; + Filter *VoiceFilterL; + Filter *VoiceFilterR; REALTYPE FilterCenterPitch;/* Filter center Pitch*/ REALTYPE FilterFreqTracking; @@ -206,6 +207,7 @@ private: Envelope *FMFreqEnvelope; Envelope *FMAmpEnvelope; + } NoteVoicePar[NUM_VOICES]; @@ -216,17 +218,23 @@ private: //time from the start of the note REALTYPE time; + //the size of unison for a single voice + int unison_size[NUM_VOICES]; + //fractional part (skip) - REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES]; + REALTYPE *oscposlo[NUM_VOICES],*oscfreqlo[NUM_VOICES]; //integer part (skip) - int oscposhi[NUM_VOICES],oscfreqhi[NUM_VOICES]; + int *oscposhi[NUM_VOICES],*oscfreqhi[NUM_VOICES]; //fractional part (skip) of the Modullator - REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES]; + REALTYPE *oscposloFM[NUM_VOICES],*oscfreqloFM[NUM_VOICES]; + + //how the unison subvoice's frequency is changed (1.0 for no change) + REALTYPE *unison_freq_rap[NUM_VOICES]; //integer part (skip) of the Modullator - unsigned short int oscposhiFM[NUM_VOICES],oscfreqhiFM[NUM_VOICES]; + unsigned int *oscposhiFM[NUM_VOICES],*oscfreqhiFM[NUM_VOICES]; //used to compute and interpolate the amplitudes of voices and modullators REALTYPE oldamplitude[NUM_VOICES], @@ -235,10 +243,13 @@ private: FMnewamplitude[NUM_VOICES]; //used by Frequency Modulation (for integration) - REALTYPE FMoldsmp[NUM_VOICES]; + REALTYPE *FMoldsmp[NUM_VOICES]; //temporary buffer - REALTYPE *tmpwave; + REALTYPE *tmpwavel; + REALTYPE *tmpwaver; + int max_unison; + REALTYPE **tmpwave_unison; //Filter bypass samples REALTYPE *bypassl,*bypassr;