commit 2565eb855025cd3941f272b57b4b93fd86965e79
parent 7a4dc58ea1213d1c769b8968f320858dc0fb5d5d
Author: Paul <nop@nop-desktop.(none)>
Date: Tue, 22 Sep 2009 22:55:09 +0300
Continued unison implementation.
Diffstat:
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);}
}