Continued unison implementation.

(cherry picked from commit 2565eb855025cd3941f272b57b4b93fd86965e79)
This commit is contained in:
Paul
2009-09-22 22:55:33 +03:00
committed by Tobias Doerffel
parent 0cd6d22931
commit 5785f481b3
5 changed files with 113 additions and 49 deletions

View File

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

View File

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

View File

@@ -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
unison_spread=pow(unison_spread*2.0,2.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);
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];
};

View File

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

View File

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