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:
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);}
}