Started to add the unison effect to ADsynth

(cherry picked from commit ae7d0b438ab9082d32b3e551657fab1012d9d2c3)
This commit is contained in:
Paul
2009-09-21 00:04:20 +03:00
committed by Tobias Doerffel
parent afc9791926
commit 3570151d26
2 changed files with 387 additions and 203 deletions

View File

@@ -33,7 +33,8 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
{
ready=0;
tmpwave=new REALTYPE [SOUND_BUFFER_SIZE];
tmpwavel=new REALTYPE [SOUND_BUFFER_SIZE];
tmpwaver=new REALTYPE [SOUND_BUFFER_SIZE];
bypassl=new REALTYPE [SOUND_BUFFER_SIZE];
bypassr=new REALTYPE [SOUND_BUFFER_SIZE];
@@ -83,18 +84,40 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
} else NoteGlobalPar.Punch.Enabled=0;
for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) {
pars->VoicePar[nvoice].OscilSmp->newrandseed(rand());
pars->VoicePar[nvoice].OscilSmp->newrandseed(rand());
NoteVoicePar[nvoice].OscilSmp=NULL;
NoteVoicePar[nvoice].FMSmp=NULL;
NoteVoicePar[nvoice].VoiceOut=NULL;
NoteVoicePar[nvoice].FMVoice=-1;
unison_size[nvoice]=1;
if (pars->VoicePar[nvoice].Enabled==0) {
NoteVoicePar[nvoice].Enabled=OFF;
continue; //the voice is disabled
};
#warning get from parameter
int unison=30;
unison_size[nvoice]=unison;
unison_freq_rap[nvoice]=new REALTYPE[unison];
for (int k=0;k<unison;k++){
unison_freq_rap[nvoice][k]=1.0*pow(1.0001,k);
};
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];
oscfreqhiFM[nvoice]=new unsigned int[unison];
oscfreqloFM[nvoice]=new REALTYPE[unison];
oscposhi[nvoice]=new int[unison];
oscposlo[nvoice]=new REALTYPE[unison];
oscposhiFM[nvoice]=new unsigned int[unison];
oscposloFM[nvoice]=new REALTYPE[unison];
NoteVoicePar[nvoice].Enabled=ON;
NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq;
NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET;
@@ -119,10 +142,13 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune);
};
oscposhi[nvoice]=0;
oscposlo[nvoice]=0.0;
oscposhiFM[nvoice]=0;
oscposloFM[nvoice]=0.0;
for (int k=0;k<unison;k++){
oscposhi[nvoice][k]=0;
oscposlo[nvoice][k]=0.0;
oscposhiFM[nvoice][k]=0;
oscposloFM[nvoice][k]=0.0;
};
NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point
@@ -130,15 +156,18 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
int vc=nvoice;
if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil;
if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand());
oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),
pars->VoicePar[nvoice].Presonance);
int oscposhi_start=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice), pars->VoicePar[nvoice].Presonance);
//I store the first elments to the last position for speedups
for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i];
oscposhi[nvoice]+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
oscposhi[nvoice]%=OSCIL_SIZE;
oscposhi_start+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
oscposhi_start%=OSCIL_SIZE;
for (int k=0;k<unison;k++){
oscposhi[nvoice][k]=oscposhi_start;
oscposhi_start=(int)(RND*(OSCIL_SIZE-1));//put random starting point for other subvoices
};
NoteVoicePar[nvoice].FreqLfo=NULL;
NoteVoicePar[nvoice].FreqEnvelope=NULL;
@@ -146,7 +175,8 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
NoteVoicePar[nvoice].AmpLfo=NULL;
NoteVoicePar[nvoice].AmpEnvelope=NULL;
NoteVoicePar[nvoice].VoiceFilter=NULL;
NoteVoicePar[nvoice].VoiceFilterL=NULL;
NoteVoicePar[nvoice].VoiceFilterR=NULL;
NoteVoicePar[nvoice].FilterEnvelope=NULL;
NoteVoicePar[nvoice].FilterLfo=NULL;
@@ -197,17 +227,30 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve
//Voice's modulator velocity sensing
NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
FMoldsmp[nvoice]=0.0;//this is for FM (integration)
FMoldsmp[nvoice]=new REALTYPE [unison];
for (int k=0;k<unison;k++) FMoldsmp[nvoice][k]=0.0;//this is for FM (integration)
firsttick[nvoice]=1;
NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE);
};
max_unison=1;
for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){
if (unison_size[nvoice]>max_unison) max_unison=unison_size[nvoice];
};
tmpwave_unison=new REALTYPE*[max_unison];
for (int k=0;k<max_unison;k++){
tmpwave_unison[k]=new REALTYPE[SOUND_BUFFER_SIZE];
for (int i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave_unison[k][i]=0.0;
};
initparameters();
ready=1;
};
// ADlegatonote: This function is (mostly) a copy of ADnote(...) and
// initparameters() stuck together with some lines removed so that it
// only alter the already playing note (to perform legato). It is
@@ -290,7 +333,6 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int
if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil;
if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand());
///oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);
pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);//(gf)Modif of the above line.
//I store the first elments to the last position for speedups
@@ -325,6 +367,10 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int
NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
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();
@@ -426,22 +472,36 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int
void ADnote::KillVoice(int nvoice)
{
delete []NoteVoicePar[nvoice].OscilSmp;
delete []oscfreqhi[nvoice];
delete []oscfreqlo[nvoice];
delete []oscfreqhiFM[nvoice];
delete []oscfreqloFM[nvoice];
delete []oscposhi[nvoice];
delete []oscposlo[nvoice];
delete []oscposhiFM[nvoice];
delete []oscposloFM[nvoice];
if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope);
NoteVoicePar[nvoice].FreqEnvelope=NULL;
delete []NoteVoicePar[nvoice].OscilSmp;
delete []unison_freq_rap[nvoice];
delete []FMoldsmp[nvoice];
if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo);
NoteVoicePar[nvoice].FreqLfo=NULL;
if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope);
NoteVoicePar[nvoice].FreqEnvelope=NULL;
if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope);
if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo);
NoteVoicePar[nvoice].FreqLfo=NULL;
if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope);
NoteVoicePar[nvoice].AmpEnvelope=NULL;
if (NoteVoicePar[nvoice].AmpLfo!=NULL) delete (NoteVoicePar[nvoice].AmpLfo);
NoteVoicePar[nvoice].AmpLfo=NULL;
if (NoteVoicePar[nvoice].VoiceFilter!=NULL) delete (NoteVoicePar[nvoice].VoiceFilter);
NoteVoicePar[nvoice].VoiceFilter=NULL;
if (NoteVoicePar[nvoice].VoiceFilterL!=NULL) delete (NoteVoicePar[nvoice].VoiceFilterL);
NoteVoicePar[nvoice].VoiceFilterL=NULL;
if (NoteVoicePar[nvoice].VoiceFilterR!=NULL) delete (NoteVoicePar[nvoice].VoiceFilterR);
NoteVoicePar[nvoice].VoiceFilterR=NULL;
if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) delete (NoteVoicePar[nvoice].FilterEnvelope);
NoteVoicePar[nvoice].FilterEnvelope=NULL;
@@ -492,9 +552,14 @@ void ADnote::KillNote()
ADnote::~ADnote()
{
if (NoteEnabled==ON) KillNote();
delete [] tmpwave;
delete [] tmpwavel;
delete [] tmpwaver;
delete [] bypassl;
delete [] bypassr;
for (int k=0;k<max_unison;k++) delete[]tmpwave_unison[k];
delete[]tmpwave_unison;
};
@@ -564,7 +629,8 @@ void ADnote::initparameters()
/* Voice Filter Parameters Init */
if (partparams->VoicePar[nvoice].PFilterEnabled!=0) {
NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter);
NoteVoicePar[nvoice].VoiceFilterL=new Filter(partparams->VoicePar[nvoice].VoiceFilter);
NoteVoicePar[nvoice].VoiceFilterR=new Filter(partparams->VoicePar[nvoice].VoiceFilter);
};
if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0)
@@ -593,10 +659,15 @@ void ADnote::initparameters()
};
if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand());
oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE;
for (int k=0;k<unison_size[nvoice];k++){
oscposhiFM[nvoice][k]=(oscposhi[nvoice][k]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE;
};
for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i];
oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
oscposhiFM[nvoice]%=OSCIL_SIZE;
int oscposhiFM_add=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
for (int k=0;k<unison_size[nvoice];k++){
oscposhiFM[nvoice][k]+=oscposhiFM_add;
oscposhiFM[nvoice][k]%=OSCIL_SIZE;
};
};
if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)
@@ -628,13 +699,15 @@ void ADnote::initparameters()
*/
void ADnote::setfreq(int nvoice,REALTYPE freq)
{
REALTYPE speed;
freq=fabs(freq);
speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
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;
if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
F2I(speed,oscfreqhi[nvoice]);
oscfreqlo[nvoice]=speed-floor(speed);
F2I(speed,oscfreqhi[nvoice][k]);
oscfreqlo[nvoice][k]=speed-floor(speed);
};
};
/*
@@ -642,13 +715,15 @@ void ADnote::setfreq(int nvoice,REALTYPE freq)
*/
void ADnote::setfreqFM(int nvoice,REALTYPE freq)
{
REALTYPE speed;
freq=fabs(freq);
speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
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;
if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
F2I(speed,oscfreqhiFM[nvoice]);
oscfreqloFM[nvoice]=speed-floor(speed);
F2I(speed,oscfreqhiFM[nvoice][k]);
oscfreqloFM[nvoice][k]=speed-floor(speed);
};
};
/*
@@ -736,7 +811,7 @@ void ADnote::computecurrentparameters()
/****************/
/* Voice Filter */
/****************/
if (NoteVoicePar[nvoice].VoiceFilter!=NULL) {
if (NoteVoicePar[nvoice].VoiceFilterL!=NULL) {
filterpitch=NoteVoicePar[nvoice].FilterCenterPitch;
if (NoteVoicePar[nvoice].FilterEnvelope!=NULL)
@@ -746,9 +821,10 @@ void ADnote::computecurrentparameters()
filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout();
filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking;
filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq);
filterfreq=NoteVoicePar[nvoice].VoiceFilterL->getrealfreq(filterfreq);
NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq);
NoteVoicePar[nvoice].VoiceFilterL->setfreq(filterfreq);
if (stereo&&NoteVoicePar[nvoice].VoiceFilterR) NoteVoicePar[nvoice].VoiceFilterR->setfreq(filterfreq);
};
if (NoteVoicePar[nvoice].noisetype==0) {//compute only if the voice isn't noise
@@ -815,22 +891,27 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
{
int i,poshi;
REALTYPE poslo;
poshi=oscposhi[nvoice];
poslo=oscposlo[nvoice];
REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
poslo+=oscfreqlo[nvoice];
if (poslo>=1.0) {
poslo-=1.0;
poshi++;
};
poshi+=oscfreqhi[nvoice];
poshi&=OSCIL_SIZE-1;
};
oscposhi[nvoice]=poshi;
oscposlo[nvoice]=poslo;
for (int k=0;k<unison_size[nvoice];k++){
poshi=oscposhi[nvoice][k];
poslo=oscposlo[nvoice][k];
int freqhi=oscfreqhi[nvoice][k];
REALTYPE freqlo=oscfreqlo[nvoice][k];
REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tw[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
poslo+=freqlo;
if (poslo>=1.0) {
poslo-=1.0;
poshi++;
};
poshi+=freqhi;
poshi&=OSCIL_SIZE-1;
};
oscposhi[nvoice][k]=poshi;
oscposlo[nvoice][k]=poslo;
};
};
@@ -881,35 +962,43 @@ inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice)
if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
if (NoteVoicePar[nvoice].FMVoice>=0) {
//if I use VoiceOut[] as modullator
int FMVoice=NoteVoicePar[nvoice].FMVoice;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tmpwave[i]=tmpwave[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
};
} else {
int poshiFM=oscposhiFM[nvoice];
REALTYPE posloFM=oscposloFM[nvoice];
if (NoteVoicePar[nvoice].FMVoice>=0) {
//if I use VoiceOut[] as modullator
int FMVoice=NoteVoicePar[nvoice].FMVoice;
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tw[i]=tw[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
};
};
} else {
for (int k=0;k<unison_size[nvoice];k++){
int poshiFM=oscposhiFM[nvoice][k];
REALTYPE posloFM=oscposloFM[nvoice][k];
int freqhiFM=oscfreqhiFM[nvoice][k];
REALTYPE freqloFM=oscfreqloFM[nvoice][k];
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tmpwave[i]=tmpwave[i]*(1.0-amp)+amp
*(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
posloFM+=oscfreqloFM[nvoice];
if (posloFM>=1.0) {
posloFM-=1.0;
poshiFM++;
};
poshiFM+=oscfreqhiFM[nvoice];
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice]=poshiFM;
oscposloFM[nvoice]=posloFM;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tw[i]=tw[i]*(1.0-amp)+amp
*(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
posloFM+=freqloFM;
if (posloFM>=1.0) {
posloFM-=1.0;
poshiFM++;
};
poshiFM+=freqhiFM;
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice][k]=poshiFM;
oscposloFM[nvoice][k]=posloFM;
};
};
};
/*
@@ -922,36 +1011,44 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice)
ComputeVoiceOscillator_LinearInterpolation(nvoice);
if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
if (NoteVoicePar[nvoice].FMVoice>=0) {
// if I use VoiceOut[] as modullator
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
int FMVoice=NoteVoicePar[nvoice].FMVoice;
for (i=0;i<SOUND_BUFFER_SIZE;i++)
tmpwave[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
};
} else {
int poshiFM=oscposhiFM[nvoice];
REALTYPE posloFM=oscposloFM[nvoice];
if (NoteVoicePar[nvoice].FMVoice>=0) {
// if I use VoiceOut[] as modullator
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
int FMVoice=NoteVoicePar[nvoice].FMVoice;
for (i=0;i<SOUND_BUFFER_SIZE;i++)
tw[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
};
};
} else {
for (int k=0;k<unison_size[nvoice];k++){
int poshiFM=oscposhiFM[nvoice][k];
REALTYPE posloFM=oscposloFM[nvoice][k];
int freqhiFM=oscfreqhiFM[nvoice][k];
REALTYPE freqloFM=oscfreqloFM[nvoice][k];
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tmpwave[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp
+(1.0-amp);
posloFM+=oscfreqloFM[nvoice];
if (posloFM>=1.0) {
posloFM-=1.0;
poshiFM++;
};
poshiFM+=oscfreqhiFM[nvoice];
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice]=poshiFM;
oscposloFM[nvoice]=posloFM;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
tw[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp
+(1.0-amp);
posloFM+=freqloFM;
if (posloFM>=1.0) {
posloFM-=1.0;
poshiFM++;
};
poshiFM+=freqhiFM;
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice][k]=poshiFM;
oscposloFM[nvoice][k]=posloFM;
};
};
};
@@ -961,80 +1058,116 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice)
*/
inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode)
{
int carposhi;
int i,FMmodfreqhi;
REALTYPE FMmodfreqlo,carposlo;
int carposhi=0;
int i,FMmodfreqhi=0;
REALTYPE FMmodfreqlo=0,carposlo=0;
if (NoteVoicePar[nvoice].FMVoice>=0) {
//if I use VoiceOut[] as modulator
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i];
} else {
//Compute the modulator and store it in tmpwave[]
int poshiFM=oscposhiFM[nvoice];
REALTYPE posloFM=oscposloFM[nvoice];
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) tw[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i];
};
} else {
//Compute the modulator and store it in tmpwave_unison[][]
for (int k=0;k<unison_size[nvoice];k++){
int poshiFM=oscposhiFM[nvoice][k];
REALTYPE posloFM=oscposloFM[nvoice][k];
int freqhiFM=oscfreqhiFM[nvoice][k];
REALTYPE freqloFM=oscfreqloFM[nvoice][k];
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tmpwave[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
posloFM+=oscfreqloFM[nvoice];
if (posloFM>=1.0) {
posloFM=fmod(posloFM,1.0);
poshiFM++;
};
poshiFM+=oscfreqhiFM[nvoice];
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice]=poshiFM;
oscposloFM[nvoice]=posloFM;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tw[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
posloFM+=freqloFM;
if (posloFM>=1.0) {
posloFM=fmod(posloFM,1.0);
poshiFM++;
};
poshiFM+=freqhiFM;
poshiFM&=OSCIL_SIZE-1;
};
oscposhiFM[nvoice][k]=poshiFM;
oscposloFM[nvoice][k]=posloFM;
};
};
// Amplitude interpolation
if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tmpwave[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
};
} else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=FMnewamplitude[nvoice];
if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])) {
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
tw[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
};
};
} else {
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) tw[i]*=FMnewamplitude[nvoice];
};
};
//normalize makes all sample-rates, oscil_sizes toproduce same sound
if (FMmode!=0) {//Frequency modulation
REALTYPE normalize=OSCIL_SIZE/262144.0*44100.0/(REALTYPE)SAMPLE_RATE;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
FMoldsmp[nvoice]=fmod(FMoldsmp[nvoice]+tmpwave[i]*normalize,OSCIL_SIZE);
tmpwave[i]=FMoldsmp[nvoice];
};
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
REALTYPE fmold=FMoldsmp[nvoice][k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
fmold=fmod(fmold+tw[i]*normalize,OSCIL_SIZE);
tw[i]=fmold;
};
FMoldsmp[nvoice][k]=fmold;
};
} else {//Phase modulation
REALTYPE normalize=OSCIL_SIZE/262144.0;
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=normalize;
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (i=0;i<SOUND_BUFFER_SIZE;i++) tw[i]*=normalize;
};
};
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
F2I(tmpwave[i],FMmodfreqhi);
FMmodfreqlo=fmod(tmpwave[i]+0.0000000001,1.0);
if (FMmodfreqhi<0) FMmodfreqlo++;
//do the modulation
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
int poshi=oscposhi[nvoice][k];
REALTYPE poslo=oscposlo[nvoice][k];
int freqhi=oscfreqhi[nvoice][k];
REALTYPE freqlo=oscfreqlo[nvoice][k];
//carrier
carposhi=oscposhi[nvoice]+FMmodfreqhi;
carposlo=oscposlo[nvoice]+FMmodfreqlo;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
F2I(tw[i],FMmodfreqhi);
FMmodfreqlo=fmod(tw[i]+0.0000000001,1.0);
if (FMmodfreqhi<0) FMmodfreqlo++;
if (carposlo>=1.0) {
carposhi++;
carposlo=fmod(carposlo,1.0);
};
carposhi&=(OSCIL_SIZE-1);
//carrier
carposhi=poshi+FMmodfreqhi;
carposlo=poslo+FMmodfreqlo;
tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo)
+NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo;
if (carposlo>=1.0) {
carposhi++;
carposlo=fmod(carposlo,1.0);
};
carposhi&=(OSCIL_SIZE-1);
oscposlo[nvoice]+=oscfreqlo[nvoice];
if (oscposlo[nvoice]>=1.0) {
oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0);
oscposhi[nvoice]++;
};
tw[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo)
+NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo;
oscposhi[nvoice]+=oscfreqhi[nvoice];
oscposhi[nvoice]&=OSCIL_SIZE-1;
};
poslo+=freqlo;
if (poslo>=1.0) {
poslo=fmod(freqlo,1.0);
poshi++;
};
poshi+=freqhi;
poshi&=OSCIL_SIZE-1;
};
oscposhi[nvoice][k]=poshi;
oscposlo[nvoice][k]=poslo;
};
};
@@ -1049,7 +1182,10 @@ inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice)
*/
inline void ADnote::ComputeVoiceNoise(int nvoice)
{
for (int i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=RND*2.0-1.0;
for (int k=0;k<unison_size[nvoice];k++){
REALTYPE *tw=tmpwave_unison[k];
for (int i=0;i<SOUND_BUFFER_SIZE;i++) tw[i]=RND*2.0-1.0;
};
};
@@ -1101,60 +1237,97 @@ int ADnote::noteout(REALTYPE *outl,REALTYPE *outr)
} else ComputeVoiceNoise(nvoice);
// Voice Processing
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];
}else{
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]+=tw[i];
};
};
REALTYPE unison_amplitude=1.0/sqrt(unison_size[nvoice]);//reduce the amplitude for large unison sizes
// Amplitude
if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])) {
REALTYPE oldam=oldamplitude[nvoice]*unison_amplitude;
REALTYPE newam=newamplitude[nvoice]*unison_amplitude;
if (ABOVE_AMPLITUDE_THRESHOLD(oldam,newam)) {
int rest=SOUND_BUFFER_SIZE;
//test if the amplitude if raising and the difference is high
if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)) {
if ((newam>oldam)&&((newam-oldam)>0.25)) {
rest=10;
if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE;
for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwave[i]*=oldamplitude[nvoice];
for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwavel[i]*=oldam;
if (stereo) for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwaver[i]*=oldam;
};
// Amplitude interpolation
for (i=0;i<rest;i++) {
tmpwave[i+(SOUND_BUFFER_SIZE-rest)]*=INTERPOLATE_AMPLITUDE(oldamplitude[nvoice]
,newamplitude[nvoice],i,rest);
REALTYPE amp=INTERPOLATE_AMPLITUDE(oldam,newam,i,rest);
tmpwavel[i+(SOUND_BUFFER_SIZE-rest)]*=amp;
if (stereo) tmpwaver[i+(SOUND_BUFFER_SIZE-rest)]*=amp;
};
} else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=newamplitude[nvoice];
} else {
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]*=newam;
if (stereo) for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwaver[i]*=newam;
};
// Fade in
if (firsttick[nvoice]!=0) {
fadein(&tmpwave[0]);
fadein(&tmpwavel[0]);
if (stereo) fadein(&tmpwaver[0]);
firsttick[nvoice]=0;
};
// Filter
if (NoteVoicePar[nvoice].VoiceFilter!=NULL) NoteVoicePar[nvoice].VoiceFilter->filterout(&tmpwave[0]);
if (NoteVoicePar[nvoice].VoiceFilterL!=NULL) NoteVoicePar[nvoice].VoiceFilterL->filterout(&tmpwavel[0]);
if ((stereo)&&(NoteVoicePar[nvoice].VoiceFilterR!=NULL)) NoteVoicePar[nvoice].VoiceFilterR->filterout(&tmpwaver[0]);
//check if the amplitude envelope is finished, if yes, the voice will be fadeout
if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) {
if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0)
for (i=0;i<SOUND_BUFFER_SIZE;i++)
tmpwave[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwavel[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
if (stereo) for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwaver[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
//the voice is killed later
};
// Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator)
if (NoteVoicePar[nvoice].VoiceOut!=NULL)
for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwave[i];
if (NoteVoicePar[nvoice].VoiceOut!=NULL){
if (stereo) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwavel[i]+tmpwaver[i];
}else {//mono
for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwavel[i];
};
};
// Add the voice that do not bypass the filter to out
if (NoteVoicePar[nvoice].filterbypass==0) {//no bypass
if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
outr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
};
} else {//bypass the filter
if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
bypassr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
};
};
if (NoteVoicePar[nvoice].filterbypass==0) {//no bypass
if (stereo) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
outl[i]+=tmpwavel[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
outr[i]+=tmpwaver[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
};
}else{
for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwavel[i]*NoteVoicePar[nvoice].Volume;//mono
};
} else {//bypass the filter
if (stereo) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
bypassl[i]+=tmpwavel[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
bypassr[i]+=tmpwaver[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
};
}else{
for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwavel[i]*NoteVoicePar[nvoice].Volume;//mono
};
};
// chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished)
if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) {
if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) KillVoice(nvoice);

View File

@@ -178,7 +178,8 @@ private:
* FILTER PARAMETERS *
*************************/
Filter *VoiceFilter;
Filter *VoiceFilterL;
Filter *VoiceFilterR;
REALTYPE FilterCenterPitch;/* Filter center Pitch*/
REALTYPE FilterFreqTracking;
@@ -206,6 +207,7 @@ private:
Envelope *FMFreqEnvelope;
Envelope *FMAmpEnvelope;
} NoteVoicePar[NUM_VOICES];
@@ -216,17 +218,23 @@ private:
//time from the start of the note
REALTYPE time;
//the size of unison for a single voice
int unison_size[NUM_VOICES];
//fractional part (skip)
REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES];
REALTYPE *oscposlo[NUM_VOICES],*oscfreqlo[NUM_VOICES];
//integer part (skip)
int oscposhi[NUM_VOICES],oscfreqhi[NUM_VOICES];
int *oscposhi[NUM_VOICES],*oscfreqhi[NUM_VOICES];
//fractional part (skip) of the Modullator
REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES];
REALTYPE *oscposloFM[NUM_VOICES],*oscfreqloFM[NUM_VOICES];
//how the unison subvoice's frequency is changed (1.0 for no change)
REALTYPE *unison_freq_rap[NUM_VOICES];
//integer part (skip) of the Modullator
unsigned short int oscposhiFM[NUM_VOICES],oscfreqhiFM[NUM_VOICES];
unsigned int *oscposhiFM[NUM_VOICES],*oscfreqhiFM[NUM_VOICES];
//used to compute and interpolate the amplitudes of voices and modullators
REALTYPE oldamplitude[NUM_VOICES],
@@ -235,10 +243,13 @@ private:
FMnewamplitude[NUM_VOICES];
//used by Frequency Modulation (for integration)
REALTYPE FMoldsmp[NUM_VOICES];
REALTYPE *FMoldsmp[NUM_VOICES];
//temporary buffer
REALTYPE *tmpwave;
REALTYPE *tmpwavel;
REALTYPE *tmpwaver;
int max_unison;
REALTYPE **tmpwave_unison;
//Filter bypass samples
REALTYPE *bypassl,*bypassr;