zynaddsubfx

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

commit 2565eb855025cd3941f272b57b4b93fd86965e79
parent 7a4dc58ea1213d1c769b8968f320858dc0fb5d5d
Author: Paul <nop@nop-desktop.(none)>
Date:   Tue, 22 Sep 2009 22:55:09 +0300

Continued unison implementation.

Diffstat:
Msrc/Params/ADnoteParameters.cpp | 26+++++++++++++++++++++++++-
Msrc/Params/ADnoteParameters.h | 3+++
Msrc/Synth/ADnote.cpp | 83++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/Synth/ADnote.h | 7+++++--
Msrc/UI/ADnoteUI.fl | 45++++++++++++++++++++++-----------------------
5 files changed, 114 insertions(+), 50 deletions(-)

diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp @@ -25,6 +25,7 @@ #include <math.h> #include "ADnoteParameters.h" +int ADnote_unison_sizes[]={1,2,3,4,6,8,12,16,24,32,48,64,0}; ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets() { @@ -99,7 +100,7 @@ void ADnoteParameters::defaults(int n) VoicePar[nvoice].Unison_size=1; VoicePar[nvoice].Unison_frequency_spread=64; - VoicePar[nvoice].Unison_stereo_spread=100; + VoicePar[nvoice].Unison_stereo_spread=64; VoicePar[nvoice].Type=0; VoicePar[nvoice].Pfixedfreq=0; @@ -235,6 +236,29 @@ ADnoteParameters::~ADnoteParameters() }; }; +int ADnoteParameters::get_unison_size_index(int nvoice){ + int index=0; + if (nvoice>=NUM_VOICES) return 0; + int unison=VoicePar[nvoice].Unison_size; + while(1){ + if ((ADnote_unison_sizes[index]<=unison)||(ADnote_unison_sizes[index]==0)) return index; + index++; + }; + return 0; +}; + +void ADnoteParameters::set_unison_size_index(int nvoice,int index){ + int unison=1; + for (int i=0;i<=index;i++){ + unison=ADnote_unison_sizes[i]; + if (unison==0) { + unison=ADnote_unison_sizes[i-1]; + break; + }; + }; + + VoicePar[nvoice].Unison_size=unison; +}; diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h @@ -36,6 +36,7 @@ #include "Presets.h" enum FMTYPE {NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD}; +extern int ADnote_unison_sizes[]; /*****************************************************************/ /* GLOBAL PARAMETERS */ @@ -278,6 +279,8 @@ public: void getfromXML(XMLwrapper *xml); REALTYPE getBandwidthDetuneMultiplier(); + int get_unison_size_index(int nvoice); + void set_unison_size_index(int nvoice,int index); private: void defaults(int n);//n is the nvoice diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -97,26 +97,44 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve continue; //the voice is disabled }; + unison_stereo_spread[nvoice]=pars->VoicePar[nvoice].Unison_stereo_spread/127.0; int unison=pars->VoicePar[nvoice].Unison_size; if (unison<1) unison=1; - + + //compute unison unison_size[nvoice]=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,4.0)*50.0;//cents - - for (int k=0;k<unison;k++){ - REALTYPE current_rnd=RND*2.0-1.0; - -#warning TODO: make current_rnd to be spread evenly (keep a current_rnd array and fix that) - - - unison_freq_rap[nvoice][k]=pow(2.0,(unison_spread*current_rnd)/1200); + unison_spread=pow(unison_spread*2.0,2.0)*50.0;//cents + + 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 + 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; + }; + break; + default:{//unison for more than 2 subvoices + REALTYPE unison_values[unison]; + REALTYPE min=-1e-6,max=1e-6; + for (int k=0;k<unison;k++){ + REALTYPE step=(k/(REALTYPE) (unison-1))*2.0-1.0;//this makes the unison spread more uniform + REALTYPE val=step+(RND*2.0-1.0)/(unison-1); + unison_values[k]=val; + if (val>max) max=val; + if (val<min) min=val; + }; + 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); + }; + }; }; - - if (unison==1) unison_freq_rap[nvoice][0]=1.0;//if the unison is not used, always make the only subvoice to have the default note - oscfreqhi[nvoice]=new int[unison]; oscfreqlo[nvoice]=new REALTYPE[unison]; @@ -706,12 +724,11 @@ void ADnote::initparameters() /* * Computes the frequency of an oscillator */ -void ADnote::setfreq(int nvoice,REALTYPE freq) +void ADnote::setfreq(int nvoice,REALTYPE in_freq) { for (int k=0;k<unison_size[nvoice];k++){ - REALTYPE speed; - freq=fabs(freq)*unison_freq_rap[nvoice][k]; - speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; + REALTYPE freq=fabs(in_freq)*unison_freq_rap[nvoice][k]; + REALTYPE speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; if (speed>OSCIL_SIZE) speed=OSCIL_SIZE; F2I(speed,oscfreqhi[nvoice][k]); @@ -722,12 +739,11 @@ void ADnote::setfreq(int nvoice,REALTYPE freq) /* * Computes the frequency of an modullator oscillator */ -void ADnote::setfreqFM(int nvoice,REALTYPE freq) +void ADnote::setfreqFM(int nvoice,REALTYPE in_freq) { for (int k=0;k<unison_size[nvoice];k++){ - REALTYPE speed; - freq=fabs(freq)*unison_freq_rap[nvoice][k]; - speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; + REALTYPE freq=fabs(in_freq)*unison_freq_rap[nvoice][k]; + REALTYPE speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; if (speed>OSCIL_SIZE) speed=OSCIL_SIZE; F2I(speed,oscfreqhiFM[nvoice][k]); @@ -1247,14 +1263,33 @@ int ADnote::noteout(REALTYPE *outl,REALTYPE *outr) // Voice Processing + //mix subvoices into for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]=0.0; if (stereo) for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwaver[i]=0.0; for (int k=0;k<unison_size[nvoice];k++){ REALTYPE *tw=tmpwave_unison[k]; if (stereo){ -#warning #make stereo mixing - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]+=tw[i]; - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwaver[i]+=tw[i]; + REALTYPE stereo_pos=0; + if (unison_size[nvoice]>1) stereo_pos=k/(REALTYPE)(unison_size[nvoice]-1)*2.0-1.0; + REALTYPE stereo_spread=unison_stereo_spread[nvoice]*2.0;//between 0 and 2.0 + if (stereo_spread>1.0){ + REALTYPE stereo_pos_1=(stereo_pos>=0.0)?1.0:-1.0; + stereo_pos=(2.0-stereo_spread)*stereo_pos+(stereo_spread-1.0)*stereo_pos_1; + }else{ + stereo_pos*=stereo_spread; + }; + if (unison_size[nvoice]==1) stereo_pos=0.0; + REALTYPE panning=(stereo_pos+1.0)*0.5; + + + REALTYPE lvol=(1.0-panning)*2.0; + if (lvol>1.0) lvol=1.0; + + REALTYPE rvol=panning*2.0; + if (rvol>1.0) rvol=1.0; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]+=tw[i]*lvol; + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwaver[i]+=tw[i]*rvol; }else{ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]+=tw[i]; }; diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -57,8 +57,8 @@ public: private: - void setfreq(int nvoice,REALTYPE freq); - void setfreqFM(int nvoice,REALTYPE freq); + void setfreq(int nvoice,REALTYPE in_freq); + void setfreqFM(int nvoice,REALTYPE in_freq); void computecurrentparameters(); void initparameters(); void KillVoice(int nvoice); @@ -221,6 +221,9 @@ private: //the size of unison for a single voice int unison_size[NUM_VOICES]; + //the stereo spread of the unison subvoices (0.0=mono,1.0=max) + REALTYPE unison_stereo_spread[NUM_VOICES]; + //fractional part (skip) REALTYPE *oscposlo[NUM_VOICES],*oscfreqlo[NUM_VOICES]; diff --git a/src/UI/ADnoteUI.fl b/src/UI/ADnoteUI.fl @@ -548,31 +548,29 @@ voiceonbutton->redraw();} open code1 {char tmp[50]; for (int i=0;i<nvoice;i++) {sprintf(tmp,"Ext.%2d",i+1);o->add(tmp);};} code3 {o->value(pars->VoicePar[nvoice].Pextoscil+1);} } {} - Fl_Group {} { - label {Unison:} open - xywh {5 525 520 45} box UP_FRAME labeltype ENGRAVED_LABEL labelsize 15 align 20 + Fl_Group {} {open + xywh {5 525 475 45} box ENGRAVED_BOX } { - Fl_Counter {} { - label SIze - callback {int k=(int) o->value(); - -pars->VoicePar[nvoice].Unison_size=k;} - tooltip {Unison Size} xywh {85 540 50 20} type Simple labelsize 10 align 1 minimum 1 maximum 8 step 1 value 1 textfont 1 textsize 12 - code0 {int k=pars->VoicePar[nvoice].Unison_size;} - code2 {o->value(k);} + Fl_Dial {} { + label Stereo + callback {pars->VoicePar[nvoice].Unison_stereo_spread=(int)o->value();} + tooltip {Stereo Spread} xywh {265 540 25 25} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 + code0 {o->value(pars->VoicePar[nvoice].Unison_stereo_spread);} + class WidgetPDial } Fl_Value_Slider {} { label {Frequency Spread} callback {pars->VoicePar[nvoice].Unison_frequency_spread=(int)o->value();} - tooltip {Frequency Spread of the Unison} xywh {155 543 155 17} type {Horz Knob} box FLAT_BOX labelsize 11 align 5 maximum 127 step 1 value 64 + tooltip {Frequency Spread of the Unison} xywh {90 548 155 17} type {Horz Knob} box FLAT_BOX labelsize 11 align 5 maximum 127 step 1 value 64 code0 {o->value(pars->VoicePar[nvoice].Unison_frequency_spread);} } - Fl_Value_Slider {} { - label {Stereo Spread} - callback {pars->VoicePar[nvoice].Unison_stereo_spread=(int)o->value();} - tooltip {Stereo Spread of the Unison} xywh {345 543 155 17} type {Horz Knob} box FLAT_BOX labelsize 11 align 5 maximum 127 step 1 value 100 - code0 {o->value(pars->VoicePar[nvoice].Unison_stereo_spread);} - } + Fl_Choice {} { + label Unison + callback {pars->set_unison_size_index(nvoice,(int) o->value());} open + tooltip {Unison size} xywh {10 545 75 20} down_box BORDER_BOX labelfont 1 align 5 textfont 1 textsize 10 + 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_Group {} { @@ -754,7 +752,8 @@ o->redraw();} pars=NULL; oscedit=NULL;} {} } - Function {init(ADnoteParameters *parameters,int nvoice_,Master *master_)} {} { + Function {init(ADnoteParameters *parameters,int nvoice_,Master *master_)} {open + } { code {pars=parameters; nvoice=nvoice_; master=master_; @@ -992,8 +991,8 @@ resui->resonancewindow->show();} } } Fl_Window ADnoteVoice { - label {ADsynth Voice Parameters} selected - xywh {53 58 765 620} type Double visible + label {ADsynth Voice Parameters} + xywh {152 271 765 620} type Double visible } { Fl_Group advoice { xywh {0 0 760 575} box BORDER_BOX @@ -1012,11 +1011,11 @@ resui->resonancewindow->show();} advoice->hide(); ADnoteVoice->remove(advoice); delete advoice; -advoice=new ADvoiceUI(0,0,765,525); +advoice=new ADvoiceUI(0,0,765,585); ADnoteVoice->add(advoice); advoice->init(pars,nvoice,master); advoice->show(); -ADnoteVoice->redraw();} +ADnoteVoice->redraw();} selected 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);} }