Added Vibratto to unison effect

(cherry picked from commit 97013fd5ca25c477d8db76105a22ddd1b8cc6cdd)
This commit is contained in:
Paul
2009-09-23 00:07:49 +03:00
committed by Tobias Doerffel
parent 5785f481b3
commit f8b8ea9686
6 changed files with 102 additions and 12 deletions

View File

@@ -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
22 Sep 2009 (Paul Nasca)
- Added vibratto and other features to Unison effect

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 */
/*******************/

View File

@@ -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];

View File

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