zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 97013fd5ca25c477d8db76105a22ddd1b8cc6cdd
parent 2565eb855025cd3941f272b57b4b93fd86965e79
Author: Paul <nop@nop-desktop.(none)>
Date:   Wed, 23 Sep 2009 00:07:25 +0300

Added Vibratto to unison effect

Diffstat:
MChangeLog | 6++++--
Msrc/Params/ADnoteParameters.cpp | 5++++-
Msrc/Params/ADnoteParameters.h | 3+++
Msrc/Synth/ADnote.cpp | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/Synth/ADnote.h | 12++++++++++++
Msrc/UI/ADnoteUI.fl | 9++++++++-
6 files changed, 102 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -892,6 +892,9 @@ 07 Sep 2009 (Mark McCurry) - Fixed glitch in XMLwrapper, which would prevent file loading + 20 Sep 2009 (Paul Nasca) - Started to implement the Unison effect for ADsynth - -\ No newline at end of file + +22 Sep 2009 (Paul Nasca) + - Added vibratto and other features to Unison effect diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp @@ -99,8 +99,9 @@ void ADnoteParameters::defaults(int n) VoicePar[nvoice].Enabled=0; VoicePar[nvoice].Unison_size=1; - VoicePar[nvoice].Unison_frequency_spread=64; + VoicePar[nvoice].Unison_frequency_spread=30; VoicePar[nvoice].Unison_stereo_spread=64; + VoicePar[nvoice].Unison_vibratto=64; VoicePar[nvoice].Type=0; VoicePar[nvoice].Pfixedfreq=0; @@ -283,6 +284,7 @@ void ADnoteParameters::add2XMLsection(XMLwrapper *xml,int n) xml->addpar("unison_size",VoicePar[nvoice].Unison_size); xml->addpar("unison_frequency_spread",VoicePar[nvoice].Unison_frequency_spread); xml->addpar("unison_stereo_spread",VoicePar[nvoice].Unison_stereo_spread); + xml->addpar("unison_vibratto",VoicePar[nvoice].Unison_vibratto); xml->addpar("delay",VoicePar[nvoice].PDelay); xml->addparbool("resonance",VoicePar[nvoice].Presonance); @@ -563,6 +565,7 @@ void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n) VoicePar[nvoice].Unison_size=xml->getpar127("unison_size",VoicePar[nvoice].Unison_size); VoicePar[nvoice].Unison_frequency_spread=xml->getpar127("unison_frequency_spread",VoicePar[nvoice].Unison_frequency_spread); VoicePar[nvoice].Unison_stereo_spread=xml->getpar127("unison_stereo_spread",VoicePar[nvoice].Unison_stereo_spread); + VoicePar[nvoice].Unison_vibratto=xml->getpar127("unison_vibratto",VoicePar[nvoice].Unison_vibratto); VoicePar[nvoice].Type=xml->getpar127("type",VoicePar[nvoice].Type); VoicePar[nvoice].PDelay=xml->getpar127("delay",VoicePar[nvoice].PDelay); diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h @@ -124,6 +124,9 @@ struct ADnoteVoiceParam { /** Stereo spread of the subvoices*/ unsigned char Unison_stereo_spread; + + /** Vibratto of the subvoices (which makes the unison more "natural")*/ + unsigned char Unison_vibratto; /** Type of the voice (0=Sound,1=Noise)*/ unsigned char Type; diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -104,18 +104,20 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve //compute unison unison_size[nvoice]=unison; + unison_base_freq_rap[nvoice]=new REALTYPE[unison]; unison_freq_rap[nvoice]=new REALTYPE[unison]; REALTYPE unison_spread=pars->VoicePar[nvoice].Unison_frequency_spread/127.0; - unison_spread=pow(unison_spread*2.0,2.0)*50.0;//cents + unison_spread=pow(unison_spread*2.0,2.0)*100.0;//cents + REALTYPE unison_real_spread=pow(2.0,(unison_spread*0.5)/1200.0); + REALTYPE unison_vibratto_a=pars->VoicePar[nvoice].Unison_vibratto/127.0;//0.0 .. 1.0 switch (unison){ case 1: - unison_freq_rap[nvoice][0]=1.0;//if the unison is not used, always make the only subvoice to have the default note + unison_base_freq_rap[nvoice][0]=1.0;//if the unison is not used, always make the only subvoice to have the default note break; case 2:{//unison for 2 subvoices - REALTYPE tmp=pow(2.0,(unison_spread*0.5)/1200.0); - unison_freq_rap[nvoice][0]=1.0/tmp; - unison_freq_rap[nvoice][1]=tmp; + unison_base_freq_rap[nvoice][0]=1.0/unison_real_spread; + unison_base_freq_rap[nvoice][1]=unison_real_spread; }; break; default:{//unison for more than 2 subvoices @@ -131,10 +133,39 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve REALTYPE diff=max-min; for (int k=0;k<unison;k++){ unison_values[k]=(unison_values[k]-(max+min)*0.5)/diff;//the lowest value will be -1 and the highest will be 1 - unison_freq_rap[nvoice][k]=pow(2.0,(unison_spread*unison_values[k]*0.5)/1200); + unison_base_freq_rap[nvoice][k]=pow(2.0,(unison_spread*unison_values[k]*0.5)/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.0+(unison_base_freq_rap[nvoice][k]-1.0)*(1.0-unison_vibratto_a); + }; + }; + unison_vibratto[nvoice].step=new REALTYPE[unison]; + unison_vibratto[nvoice].position=new REALTYPE[unison]; + unison_vibratto[nvoice].amplitude=(unison_real_spread-1.0)*unison_vibratto_a*0.5; + + REALTYPE increments_per_second=SAMPLE_RATE/(REALTYPE)SOUND_BUFFER_SIZE; + for (int k=0;k<unison;k++){ + unison_vibratto[nvoice].position[k]=RND*0.9-0.45; + REALTYPE vibratto_period=0.5+RND*2.5; + + + unison_vibratto[nvoice].position[k]=0; + REALTYPE m=4.0/(vibratto_period*increments_per_second); + if (RND<0.5) m=-m; + unison_vibratto[nvoice].step[k]=m; + }; + + if (unison==1) {//no vibratto for a single voice + unison_vibratto[nvoice].step[0]=0.0; + unison_vibratto[nvoice].position[0]=0.0; + unison_vibratto[nvoice].amplitude=0.0; + }; oscfreqhi[nvoice]=new int[unison]; oscfreqlo[nvoice]=new REALTYPE[unison]; @@ -395,9 +426,6 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int 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(); @@ -509,8 +537,11 @@ void ADnote::KillVoice(int nvoice) delete []oscposloFM[nvoice]; delete []NoteVoicePar[nvoice].OscilSmp; + delete []unison_base_freq_rap[nvoice]; delete []unison_freq_rap[nvoice]; delete []FMoldsmp[nvoice]; + delete []unison_vibratto[nvoice].step; + delete []unison_vibratto[nvoice].position; if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope); NoteVoicePar[nvoice].FreqEnvelope=NULL; @@ -719,6 +750,35 @@ void ADnote::initparameters() }; }; + +/* + * 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.0; + return; + }; + for (int k=0;k<unison_size[nvoice];k++){ + REALTYPE pos=unison_vibratto[nvoice].position[k]; + REALTYPE step=unison_vibratto[nvoice].step[k]; + pos+=step; + if (pos<=-1.0) { + pos=-1.0; + step=-step; + }; + if (pos>=1.0){ + pos=1.0; + step=-step; + }; + unison_freq_rap[nvoice][k]=unison_base_freq_rap[nvoice][k]+pos*unison_vibratto[nvoice].amplitude; + + unison_vibratto[nvoice].position[k]=pos; + step=unison_vibratto[nvoice].step[k]=step; + }; + +}; /* @@ -821,6 +881,8 @@ void ADnote::computecurrentparameters() NoteVoicePar[nvoice].DelayTicks-=1; if (NoteVoicePar[nvoice].DelayTicks>0) continue; + compute_unison_freq_rap(nvoice); + /*******************/ /* Voice Amplitude */ /*******************/ diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -59,6 +59,7 @@ private: void setfreq(int nvoice,REALTYPE in_freq); void setfreqFM(int nvoice,REALTYPE in_freq); + void compute_unison_freq_rap(int nvoice); void computecurrentparameters(); void initparameters(); void KillVoice(int nvoice); @@ -233,9 +234,20 @@ private: //fractional part (skip) of the Modullator REALTYPE *oscposloFM[NUM_VOICES],*oscfreqloFM[NUM_VOICES]; + //the unison base_value + REALTYPE *unison_base_freq_rap[NUM_VOICES]; + //how the unison subvoice's frequency is changed (1.0 for no change) REALTYPE *unison_freq_rap[NUM_VOICES]; + //unison vibratto + struct { + REALTYPE amplitude; //amplitude which be added to unison_freq_rap + REALTYPE *step; //value which increments the position + REALTYPE *position;//between -1.0 and 1.0 + }unison_vibratto[NUM_VOICES]; + + //integer part (skip) of the Modullator unsigned int *oscposhiFM[NUM_VOICES],*oscfreqhiFM[NUM_VOICES]; diff --git a/src/UI/ADnoteUI.fl b/src/UI/ADnoteUI.fl @@ -571,6 +571,13 @@ voiceonbutton->redraw();} open code0 {o->add("OFF");char tmp[100];for (int i=1;ADnote_unison_sizes[i];i++){snprintf(tmp,100,"size %d",ADnote_unison_sizes[i]);o->add(tmp);};} code1 {o->value(pars->VoicePar[nvoice].PDetuneType);} } {} + Fl_Dial {} { + label Vibratto + callback {pars->VoicePar[nvoice].Unison_vibratto=(int)o->value();} selected + tooltip Vibratto xywh {340 540 25 25} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 + code0 {o->value(pars->VoicePar[nvoice].Unison_vibratto);} + class WidgetPDial + } } } Fl_Group {} { @@ -1015,7 +1022,7 @@ advoice=new ADvoiceUI(0,0,765,585); ADnoteVoice->add(advoice); advoice->init(pars,nvoice,master); advoice->show(); -ADnoteVoice->redraw();} selected +ADnoteVoice->redraw();} xywh {5 585 130 25} type Simple labelfont 1 align 8 minimum 0 maximum 2 step 1 value 1 textfont 1 textsize 13 code0 {o->bounds(1,NUM_VOICES);} }