diff options
Diffstat (limited to 'muse/synti/zynaddsubfx/Synth/OscilGen.C')
-rw-r--r-- | muse/synti/zynaddsubfx/Synth/OscilGen.C | 1182 |
1 files changed, 1182 insertions, 0 deletions
diff --git a/muse/synti/zynaddsubfx/Synth/OscilGen.C b/muse/synti/zynaddsubfx/Synth/OscilGen.C new file mode 100644 index 00000000..4e6a4dd3 --- /dev/null +++ b/muse/synti/zynaddsubfx/Synth/OscilGen.C @@ -0,0 +1,1182 @@ +/* + ZynAddSubFX - a software synthesizer + + OscilGen.C - Waveform generator for ADnote + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include <stdlib.h> +#include <math.h> +#include <stdio.h> + +#include "OscilGen.h" +#include "../Effects/Distorsion.h" + +REALTYPE *OscilGen::tmpsmps;//this array stores some termporary data and it has SOUND_BUFFER_SIZE elements +FFTFREQS OscilGen::outoscilFFTfreqs; + + +OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets(){ + setpresettype("Poscilgen"); + fft=fft_; + res=res_; + newFFTFREQS(&oscilFFTfreqs,OSCIL_SIZE/2); + newFFTFREQS(&basefuncFFTfreqs,OSCIL_SIZE/2); + + randseed=1; + ADvsPAD=false; + + defaults(); +}; + +OscilGen::~OscilGen(){ + deleteFFTFREQS(&basefuncFFTfreqs); + deleteFFTFREQS(&oscilFFTfreqs); +}; + + +void OscilGen::defaults(){ + + oldbasefunc=0;oldbasepar=64;oldhmagtype=0;oldwaveshapingfunction=0;oldwaveshaping=64; + oldbasefuncmodulation=0;oldharmonicshift=0;oldbasefuncmodulationpar1=0;oldbasefuncmodulationpar2=0;oldbasefuncmodulationpar3=0; + oldmodulation=0;oldmodulationpar1=0;oldmodulationpar2=0;oldmodulationpar3=0; + + for (int i=0;i<MAX_AD_HARMONICS;i++){ + hmag[i]=0.0; + hphase[i]=0.0; + Phmag[i]=64; + Phphase[i]=64; + }; + Phmag[0]=127; + Phmagtype=0; + if (ADvsPAD) Prand=127;//max phase randomness (usefull if the oscil will be imported to a ADsynth from a PADsynth + else Prand=64;//no randomness + + Pcurrentbasefunc=0; + Pbasefuncpar=64; + + Pbasefuncmodulation=0; + Pbasefuncmodulationpar1=64; + Pbasefuncmodulationpar2=64; + Pbasefuncmodulationpar3=32; + + Pmodulation=0; + Pmodulationpar1=64; + Pmodulationpar2=64; + Pmodulationpar3=32; + + Pwaveshapingfunction=0; + Pwaveshaping=64; + Pfiltertype=0; + Pfilterpar1=64; + Pfilterpar2=64; + Pfilterbeforews=0; + Psatype=0; + Psapar=64; + + Pamprandpower=64; + Pamprandtype=0; + + Pharmonicshift=0; + Pharmonicshiftfirst=0; + + Padaptiveharmonics=0; + Padaptiveharmonicspower=100; + Padaptiveharmonicsbasefreq=128; + Padaptiveharmonicspar=50; + + for (int i=0;i<OSCIL_SIZE/2;i++) { + oscilFFTfreqs.s[i]=0.0; + oscilFFTfreqs.c[i]=0.0; + basefuncFFTfreqs.s[i]=0.0; + basefuncFFTfreqs.c[i]=0.0; + }; + oscilprepared=0; + oldfilterpars=0;oldsapars=0; + prepare(); +}; + +void OscilGen::convert2sine(int magtype){ + REALTYPE mag[MAX_AD_HARMONICS],phase[MAX_AD_HARMONICS]; + REALTYPE oscil[OSCIL_SIZE]; + FFTFREQS freqs; + newFFTFREQS(&freqs,OSCIL_SIZE/2); + + get(oscil,-1.0); + FFTwrapper *fft=new FFTwrapper(OSCIL_SIZE); + fft->smps2freqs(oscil,freqs); + delete(fft); + + REALTYPE max=0.0; + + mag[0]=0; + phase[0]=0; + for (int i=0;i<MAX_AD_HARMONICS;i++){ + mag[i]=sqrt(pow(freqs.s[i+1],2)+pow(freqs.c[i+1],2.0)); + phase[i]=atan2(freqs.c[i+1],freqs.s[i+1]); + if (max<mag[i]) max=mag[i]; + }; + if (max<0.00001) max=1.0; + + defaults(); + + for (int i=0;i<MAX_AD_HARMONICS-1;i++){ + REALTYPE newmag=mag[i]/max; + REALTYPE newphase=phase[i]; + + Phmag[i]=(int) ((newmag)*64.0)+64; + + Phphase[i]=64-(int) (64.0*newphase/PI); + if (Phphase[i]>127) Phphase[i]=127; + + if (Phmag[i]==64) Phphase[i]=64; + }; + deleteFFTFREQS(&freqs); + prepare(); +}; + +/* + * Base Functions - START + */ +REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a){ + return((fmod(x,1.0)<a)?-1.0:1.0); +}; + +REALTYPE OscilGen::basefunc_saw(REALTYPE x,REALTYPE a){ + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + x=fmod(x,1); + if (x<a) return(x/a*2.0-1.0); + else return((1.0-x)/(1.0-a)*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_triangle(REALTYPE x,REALTYPE a){ + x=fmod(x+0.25,1); + a=1-a; + if (a<0.00001) a=0.00001; + if (x<0.5) x=x*4-1.0; + else x=(1.0-x)*4-1.0; + x/=-a; + if (x<-1.0) x=-1.0; + if (x>1.0) x=1.0; + return(x); +}; + +REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a){ + x=fmod(x,1); + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + return(pow(x,exp((a-0.5)*10.0))*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a){ + x=fmod(x,1)*2.0-1.0; + if (a<0.00001) a=0.00001; + return(exp(-x*x*(exp(a*8)+5.0))*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a){ + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + a=a*2.0-1.0; + x=cos((x+0.5)*2.0*PI)-a; + if (x<0.0) x=0.0; + return(x/(1.0-a)*2-1.0); +}; + +REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a){ + x=fmod(x,1); + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + return(sin(pow(x,exp((a-0.5)*5.0))*PI)*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a){ + if (a<0.00001) a=0.00001; + x=(fmod(x,1)-0.5)*exp((a-0.5)*log(128)); + if (x<-0.5) x=-0.5; + else if (x>0.5) x=0.5; + x=sin(x*PI*2.0); + return(x); +}; + +REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a){ + x=fmod(x+0.5,1)*2.0-1.0; + a=(a-0.5)*4;if (a>0.0) a*=2; + a=pow(3.0,a); + REALTYPE b=pow(fabs(x),a); + if (x<0) b=-b; + return(-sin(b*PI)); +}; + +REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a){ + x=fmod(x,1.0)*2.0*PI; + a=(a-0.5)*4;if (a<0.0) a*=2.0; + a=pow(3.0,a); + return(sin(x/2.0)*sin(a*x*x)); +}; + +REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a){ + x=fmod(x+0.5,1)*2.0-1.0; + a=(a-0.5)*9; + a=pow(3.0,a); + REALTYPE b=pow(fabs(x),a); + if (x<0) b=-b; + return(-pow(sin(b*PI),2)); +}; + +REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a){ + a=a*a*a*30.0+1.0; + return(cos(acos(x*2.0-1.0)*a)); +}; + +REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a){ + a=a*a*a*a*160.0+0.001; + return(-atan(sin(x*2.0*PI)*a)); +}; +/* + * Base Functions - END + */ + + +/* + * Get the base function + */ +void OscilGen::getbasefunction(REALTYPE *smps){ + int i; + REALTYPE par=(Pbasefuncpar+0.5)/128.0; + if (Pbasefuncpar==64) par=0.5; + + REALTYPE basefuncmodulationpar1=Pbasefuncmodulationpar1/127.0, + basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0, + basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0; + + switch(Pbasefuncmodulation){ + case 1:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0; + break; + case 2:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + break; + case 3:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0; + basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0; + break; + }; + +// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); + + for (i=0;i<OSCIL_SIZE;i++) { + REALTYPE t=i*1.0/OSCIL_SIZE; + + switch(Pbasefuncmodulation){ + case 1:t=t*basefuncmodulationpar3+sin((t+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//rev + break; + case 2:t=t+sin((t*basefuncmodulationpar3+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//sine + break; + case 3:t=t+pow((1.0-cos((t+basefuncmodulationpar2)*2.0*PI))*0.5,basefuncmodulationpar3)*basefuncmodulationpar1;//power + break; + }; + + t=t-floor(t); + + switch (Pcurrentbasefunc){ + case 1:smps[i]=basefunc_triangle(t,par); + break; + case 2:smps[i]=basefunc_pulse(t,par); + break; + case 3:smps[i]=basefunc_saw(t,par); + break; + case 4:smps[i]=basefunc_power(t,par); + break; + case 5:smps[i]=basefunc_gauss(t,par); + break; + case 6:smps[i]=basefunc_diode(t,par); + break; + case 7:smps[i]=basefunc_abssine(t,par); + break; + case 8:smps[i]=basefunc_pulsesine(t,par); + break; + case 9:smps[i]=basefunc_stretchsine(t,par); + break; + case 10:smps[i]=basefunc_chirp(t,par); + break; + case 11:smps[i]=basefunc_absstretchsine(t,par); + break; + case 12:smps[i]=basefunc_chebyshev(t,par); + break; + case 13:smps[i]=basefunc_sqr(t,par); + break; + default:smps[i]=-sin(2.0*PI*i/OSCIL_SIZE); + }; + }; +}; + +/* + * Filter the oscillator + */ +void OscilGen::oscilfilter(){ + if (Pfiltertype==0) return; + REALTYPE par=1.0-Pfilterpar1/128.0; + REALTYPE par2=Pfilterpar2/127.0; + REALTYPE max=0.0,tmp=0.0,p2,x; + for (int i=1;i<OSCIL_SIZE/2;i++){ + REALTYPE gain=1.0; + switch(Pfiltertype){ + case 1: gain=pow(1.0-par*par*par*0.99,i);//lp + tmp=par2*par2*par2*par2*0.5+0.0001; + if (gain<tmp) gain=pow(gain,10.0)/pow(tmp,9.0); + break; + case 2: gain=1.0-pow(1.0-par*par,i+1);//hp1 + gain=pow(gain,par2*2.0+0.1); + break; + case 3: if (par<0.2) par=par*0.25+0.15; + gain=1.0-pow(1.0-par*par*0.999+0.001,i*0.05*i+1.0);//hp1b + tmp=pow(5.0,par2*2.0); + gain=pow(gain,tmp); + break; + case 4: gain=i+1-pow(2,(1.0-par)*7.5);//bp1 + gain=1.0/(1.0+gain*gain/(i+1.0)); + tmp=pow(5.0,par2*2.0); + gain=pow(gain,tmp); + if (gain<1e-5) gain=1e-5; + break; + case 5: gain=i+1-pow(2,(1.0-par)*7.5);//bs1 + gain=pow(atan(gain/(i/10.0+1))/1.57,6); + gain=pow(gain,par2*par2*3.9+0.1); + break; + case 6: tmp=pow(par2,0.33); + gain=(i+1>pow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2 + break; + case 7: tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2 + if (Pfilterpar1==0) gain=1.0; + break; + case 8: tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2 + break; + case 9: tmp=pow(par2,0.33); + gain=(fabs(pow(2,(1.0-par)*7)-i)<i/2+1?0.0:1.0)*par2+(1.0-par2);//bs2 + break; + case 10:tmp=pow(5.0,par2*2.0-1.0); + tmp=pow(i/32.0,tmp)*32.0; + if (Pfilterpar2==64) tmp=i; + gain=cos(par*par*PI/2.0*tmp);//cos + gain*=gain; + break; + case 11:tmp=pow(5.0,par2*2.0-1.0); + tmp=pow(i/32.0,tmp)*32.0; + if (Pfilterpar2==64) tmp=i; + gain=sin(par*par*PI/2.0*tmp);//sin + gain*=gain; + break; + case 12:p2=1.0-par+0.2; + x=i/(64.0*p2*p2); + if (x<0.0) x=0.0; + else if (x>1.0) x=1.0; + tmp=pow(1.0-par2,2.0); + gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf + break; + case 13:tmp=(int) (pow(2.0,(1.0-par)*7.2)); + gain=1.0; + if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0); + break; + }; + + + oscilFFTfreqs.s[i]*=gain; + oscilFFTfreqs.c[i]*=gain; + REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+ + oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]; + if (max<tmp) max=tmp; + }; + + max=sqrt(max); + if (max<1e-10) max=1.0; + REALTYPE imax=1.0/max; + for (int i=1;i<OSCIL_SIZE/2;i++) { + oscilFFTfreqs.s[i]*=imax; + oscilFFTfreqs.c[i]*=imax; + }; +}; + +/* + * Change the base function + */ +void OscilGen::changebasefunction(){ + if (Pcurrentbasefunc!=0) { + getbasefunction(tmpsmps); + fft->smps2freqs(tmpsmps,basefuncFFTfreqs); + basefuncFFTfreqs.c[0]=0.0; + } else { + for (int i=0;i<OSCIL_SIZE/2;i++){ + basefuncFFTfreqs.s[i]=0.0; + basefuncFFTfreqs.c[i]=0.0; + }; + //in this case basefuncFFTfreqs_ are not used + } + oscilprepared=0; + oldbasefunc=Pcurrentbasefunc; + oldbasepar=Pbasefuncpar; + oldbasefuncmodulation=Pbasefuncmodulation; + oldbasefuncmodulationpar1=Pbasefuncmodulationpar1; + oldbasefuncmodulationpar2=Pbasefuncmodulationpar2; + oldbasefuncmodulationpar3=Pbasefuncmodulationpar3; +}; + +/* + * Waveshape + */ +void OscilGen::waveshape(){ + int i; + + oldwaveshapingfunction=Pwaveshapingfunction; + oldwaveshaping=Pwaveshaping; + if (Pwaveshapingfunction==0) return; + + oscilFFTfreqs.c[0]=0.0;//remove the DC + //reduce the amplitude of the freqs near the nyquist + for (i=1;i<OSCIL_SIZE/8;i++) { + REALTYPE tmp=i/(OSCIL_SIZE/8.0); + oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; + oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; + }; + fft->freqs2smps(oscilFFTfreqs,tmpsmps); + + //Normalize + REALTYPE max=0.0; + for (i=0;i<OSCIL_SIZE;i++) + if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]); + if (max<0.00001) max=1.0; + max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) tmpsmps[i]*=max; + + //Do the waveshaping + waveshapesmps(OSCIL_SIZE,tmpsmps,Pwaveshapingfunction,Pwaveshaping); + + fft->smps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT +}; + + +/* + * Do the Frequency Modulation of the Oscil + */ +void OscilGen::modulation(){ + int i; + + oldmodulation=Pmodulation; + oldmodulationpar1=Pmodulationpar1; + oldmodulationpar2=Pmodulationpar2; + oldmodulationpar3=Pmodulationpar3; + if (Pmodulation==0) return; + + + REALTYPE modulationpar1=Pmodulationpar1/127.0, + modulationpar2=0.5-Pmodulationpar2/127.0, + modulationpar3=Pmodulationpar3/127.0; + + switch(Pmodulation){ + case 1:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0)); + if (modulationpar3<0.9999) modulationpar3=-1.0; + break; + case 2:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0)); + break; + case 3:modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0; + modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0; + break; + }; + + oscilFFTfreqs.c[0]=0.0;//remove the DC + //reduce the amplitude of the freqs near the nyquist + for (i=1;i<OSCIL_SIZE/8;i++) { + REALTYPE tmp=i/(OSCIL_SIZE/8.0); + oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; + oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; + }; + fft->freqs2smps(oscilFFTfreqs,tmpsmps); + int extra_points=2; + REALTYPE *in=new REALTYPE[OSCIL_SIZE+extra_points]; + + //Normalize + REALTYPE max=0.0; + for (i=0;i<OSCIL_SIZE;i++) if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]); + if (max<0.00001) max=1.0; + max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) in[i]=tmpsmps[i]*max; + for (i=0;i<extra_points;i++) in[i+OSCIL_SIZE]=tmpsmps[i]*max; + + //Do the modulation + for (i=0;i<OSCIL_SIZE;i++) { + REALTYPE t=i*1.0/OSCIL_SIZE; + + switch(Pmodulation){ + case 1:t=t*modulationpar3+sin((t+modulationpar2)*2.0*PI)*modulationpar1;//rev + break; + case 2:t=t+sin((t*modulationpar3+modulationpar2)*2.0*PI)*modulationpar1;//sine + break; + case 3:t=t+pow((1.0-cos((t+modulationpar2)*2.0*PI))*0.5,modulationpar3)*modulationpar1;//power + break; + }; + + t=(t-floor(t))*OSCIL_SIZE; + + int poshi=(int) t; + REALTYPE poslo=t-floor(t); + + tmpsmps[i]=in[poshi]*(1.0-poslo)+in[poshi+1]*poslo; + }; + + delete(in); + fft->smps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT +}; + + + +/* + * Adjust the spectrum + */ +void OscilGen::spectrumadjust(){ + if (Psatype==0) return; + REALTYPE par=Psapar/127.0; + switch(Psatype){ + case 1: par=1.0-par*2.0; + if (par>=0.0) par=pow(5.0,par); + else par=pow(8.0,par); + break; + case 2: par=pow(10.0,(1.0-par)*3.0)*0.25; + break; + case 3: par=pow(10.0,(1.0-par)*3.0)*0.25; + break; + }; + + + REALTYPE max=0.0; + for (int i=0;i<OSCIL_SIZE/2;i++){ + REALTYPE tmp=pow(oscilFFTfreqs.c[i],2)+pow(oscilFFTfreqs.s[i],2.0); + if (max<tmp) max=tmp; + }; + max=sqrt(max)/OSCIL_SIZE*2.0; + if (max<1e-8) max=1.0; + + + for (int i=0;i<OSCIL_SIZE/2;i++){ + REALTYPE mag=sqrt(pow(oscilFFTfreqs.s[i],2)+pow(oscilFFTfreqs.c[i],2.0))/max; + REALTYPE phase=atan2(oscilFFTfreqs.s[i],oscilFFTfreqs.c[i]); + + switch (Psatype){ + case 1: mag=pow(mag,par); + break; + case 2: if (mag<par) mag=0.0; + break; + case 3: mag/=par; + if (mag>1.0) mag=1.0; + break; + }; + oscilFFTfreqs.c[i]=mag*cos(phase); + oscilFFTfreqs.s[i]=mag*sin(phase); + }; + +}; + +void OscilGen::shiftharmonics(){ + if (Pharmonicshift==0) return; + + REALTYPE hc,hs; + int harmonicshift=-Pharmonicshift; + + if (harmonicshift>0){ + for (int i=OSCIL_SIZE/2-2;i>=0;i--){ + int oldh=i-harmonicshift; + if (oldh<0){ + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + }; + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; + } else { + for (int i=0;i<OSCIL_SIZE/2-1;i++){ + int oldh=i+abs(harmonicshift); + if (oldh>=(OSCIL_SIZE/2-1)){ + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; + }; + + oscilFFTfreqs.c[0]=0.0; +}; + +/* + * Prepare the Oscillator + */ +void OscilGen::prepare(){ + int i,j,k; + REALTYPE a,b,c,d,hmagnew; + + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)|| + (oldbasefuncmodulation!=Pbasefuncmodulation)|| + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + changebasefunction(); + + for (i=0;i<MAX_AD_HARMONICS;i++) hphase[i]=(Phphase[i]-64.0)/64.0*PI/(i+1); + + for (i=0;i<MAX_AD_HARMONICS;i++){ + hmagnew=1.0-fabs(Phmag[i]/64.0-1.0); + switch(Phmagtype){ + case 1:hmag[i]=exp(hmagnew*log(0.01)); break; + case 2:hmag[i]=exp(hmagnew*log(0.001));break; + case 3:hmag[i]=exp(hmagnew*log(0.0001));break; + case 4:hmag[i]=exp(hmagnew*log(0.00001));break; + default:hmag[i]=1.0-hmagnew; + break; + }; + + if (Phmag[i]<64) hmag[i]=-hmag[i]; + }; + + //remove the harmonics where Phmag[i]==64 + for (i=0;i<MAX_AD_HARMONICS;i++) if (Phmag[i]==64) hmag[i]=0.0; + + + for (i=0;i<OSCIL_SIZE/2;i++) { + oscilFFTfreqs.c[i]=0.0; + oscilFFTfreqs.s[i]=0.0; + }; + if (Pcurrentbasefunc==0) {//the sine case + for (i=0;i<MAX_AD_HARMONICS;i++){ + oscilFFTfreqs.c[i+1]=-hmag[i]*sin(hphase[i]*(i+1))/2.0; + oscilFFTfreqs.s[i+1]=hmag[i]*cos(hphase[i]*(i+1))/2.0; + }; + } else { + for (j=0;j<MAX_AD_HARMONICS;j++){ + if (Phmag[j]==64) continue; + for (i=1;i<OSCIL_SIZE/2;i++){ + k=i*(j+1);if (k>=OSCIL_SIZE/2) break; + a=basefuncFFTfreqs.c[i]; + b=basefuncFFTfreqs.s[i]; + c=hmag[j]*cos(hphase[j]*k); + d=hmag[j]*sin(hphase[j]*k); + oscilFFTfreqs.c[k]+=a*c-b*d; + oscilFFTfreqs.s[k]+=a*d+b*c; + }; + }; + + }; + + if (Pharmonicshiftfirst!=0) shiftharmonics(); + + + + if (Pfilterbeforews==0){ + waveshape(); + oscilfilter(); + } else { + oscilfilter(); + waveshape(); + }; + + modulation(); + spectrumadjust(); + if (Pharmonicshiftfirst==0) shiftharmonics(); + + oscilFFTfreqs.c[0]=0.0; + + oldhmagtype=Phmagtype; + oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256; + + oscilprepared=1; +}; + +void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq){ + if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return; + if (freq<1.0) freq=440.0; + + FFTFREQS inf; + newFFTFREQS(&inf,OSCIL_SIZE/2); + for (int i=0;i<OSCIL_SIZE/2;i++) { + inf.s[i]=f.s[i]; + inf.c[i]=f.c[i]; + f.s[i]=0.0; + f.c[i]=0.0; + }; + inf.c[0]=0.0;inf.s[0]=0.0; + + REALTYPE hc=0.0,hs=0.0; + REALTYPE basefreq=30.0*pow(10.0,Padaptiveharmonicsbasefreq/128.0); + REALTYPE power=(Padaptiveharmonicspower+1.0)/101.0; + + REALTYPE rap=freq/basefreq; + + rap=pow(rap,power); + + bool down=false; + if (rap>1.0) { + rap=1.0/rap; + down=true; + }; + + for (int i=0;i<OSCIL_SIZE/2-2;i++){ + REALTYPE h=i*rap; + int high=(int)(i*rap); + REALTYPE low=fmod(h,1.0); + + if (high>=(OSCIL_SIZE/2-2)){ + break; + } else { + if (down){ + f.c[high]+=inf.c[i]*(1.0-low); + f.s[high]+=inf.s[i]*(1.0-low); + f.c[high+1]+=inf.c[i]*low; + f.s[high+1]+=inf.s[i]*low; + } else { + hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low; + hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low; + }; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + if (!down){ + if (i==0) {//corect the aplitude of the first harmonic + hc*=rap; + hs*=rap; + }; + f.c[i]=hc; + f.s[i]=hs; + }; + }; + + f.c[1]+=f.c[0];f.s[1]+=f.s[0]; + f.c[0]=0.0;f.s[0]=0.0; + deleteFFTFREQS(&inf); +}; + +void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size){ + if (Padaptiveharmonics<=1) return; + REALTYPE *inf=new REALTYPE[size]; + REALTYPE par=Padaptiveharmonicspar*0.01; + par=1.0-pow((1.0-par),1.5); + + for (int i=0;i<size;i++) { + inf[i]=f[i]*par; + f[i]=f[i]*(1.0-par); + }; + + + if (Padaptiveharmonics==2){//2n+1 + for (int i=0;i<size;i++) if ((i%2)==0) f[i]+=inf[i];//i=0 pt prima armonica,etc. + } else{//celelalte moduri + int nh=(Padaptiveharmonics-3)/2+2; + int sub_vs_add=(Padaptiveharmonics-3)%2; + if (sub_vs_add==0){ + for (int i=0;i<size;i++) { + if (((i+1)%nh)==0){ + f[i]+=inf[i]; + }; + }; + } else { + for (int i=0;i<size/nh-1;i++) { + f[(i+1)*nh-1]+=inf[i]; + }; + }; + }; + + delete(inf); +}; + + + +/* + * Get the oscillator function + */ +short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz){ + return(this->get(smps,freqHz,0)); +}; + +void OscilGen::newrandseed(unsigned int randseed){ + this->randseed=randseed; +}; + +/* + * Get the oscillator function + */ +short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){ + int i; + int nyquist,outpos; + + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||(oldhmagtype!=Phmagtype) + ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0; + if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216){ + oscilprepared=0; + oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216; + }; + if (oldsapars!=Psatype*256+Psapar){ + oscilprepared=0; + oldsapars=Psatype*256+Psapar; + }; + + if ((oldbasefuncmodulation!=Pbasefuncmodulation)|| + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + oscilprepared=0; + + if ((oldmodulation!=Pmodulation)|| + (oldmodulationpar1!=Pmodulationpar1)|| + (oldmodulationpar2!=Pmodulationpar2)|| + (oldmodulationpar3!=Pmodulationpar3)) + oscilprepared=0; + + if (oldharmonicshift!=Pharmonicshift+Pharmonicshiftfirst*256) oscilprepared=0; + + if (oscilprepared!=1) prepare(); + + outpos=(int)((RND*2.0-1.0)*(REALTYPE) OSCIL_SIZE*(Prand-64.0)/64.0); + outpos=(outpos+2*OSCIL_SIZE) % OSCIL_SIZE; + + + for (i=0;i<OSCIL_SIZE/2;i++){ + outoscilFFTfreqs.c[i]=0.0; + outoscilFFTfreqs.s[i]=0.0; + }; + + nyquist=(int)(0.5*SAMPLE_RATE/fabs(freqHz))+2; + if (ADvsPAD) nyquist=(int)(OSCIL_SIZE/2); + if (nyquist>OSCIL_SIZE/2) nyquist=OSCIL_SIZE/2; + + + int realnyquist=nyquist; + + if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2; + for (i=1;i<nyquist-1;i++) { + outoscilFFTfreqs.c[i]=oscilFFTfreqs.c[i]; + outoscilFFTfreqs.s[i]=oscilFFTfreqs.s[i]; + }; + + adaptiveharmonic(outoscilFFTfreqs,freqHz); + adaptiveharmonicpostprocess(&outoscilFFTfreqs.c[1],OSCIL_SIZE/2-1); + adaptiveharmonicpostprocess(&outoscilFFTfreqs.s[1],OSCIL_SIZE/2-1); + + nyquist=realnyquist; + if (Padaptiveharmonics){//do the antialiasing in the case of adaptive harmonics + for (i=nyquist;i<OSCIL_SIZE/2;i++) { + outoscilFFTfreqs.s[i]=0; + outoscilFFTfreqs.c[i]=0; + }; + }; + + // Randomness (each harmonic), the block type is computed + // in ADnote by setting start position according to this setting + if ((Prand>64)&&(freqHz>=0.0)&&(!ADvsPAD)){ + REALTYPE rnd,angle,a,b,c,d; + rnd=PI*pow((Prand-64.0)/64.0,2.0); + for (i=1;i<nyquist-1;i++){//to Nyquist only for AntiAliasing + angle=rnd*i*RND; + a=outoscilFFTfreqs.c[i]; + b=outoscilFFTfreqs.s[i]; + c=cos(angle); + d=sin(angle); + outoscilFFTfreqs.c[i]=a*c-b*d; + outoscilFFTfreqs.s[i]=a*d+b*c; + }; + }; + + //Harmonic Amplitude Randomness + if ((freqHz>0.1)&&(!ADvsPAD)) { + unsigned int realrnd=rand(); + srand(randseed); + REALTYPE power=Pamprandpower/127.0; + REALTYPE normalize=1.0/(1.2-power); + switch (Pamprandtype){ + case 1: power=power*2.0-0.5; + power=pow(15.0,power); + for (i=1;i<nyquist-1;i++){ + REALTYPE amp=pow(RND,power)*normalize; + outoscilFFTfreqs.c[i]*=amp; + outoscilFFTfreqs.s[i]*=amp; + }; + break; + case 2: power=power*2.0-0.5; + power=pow(15.0,power)*2.0; + REALTYPE rndfreq=2*PI*RND; + for (i=1;i<nyquist-1;i++){ + REALTYPE amp=pow(fabs(sin(i*rndfreq)),power)*normalize; + outoscilFFTfreqs.c[i]*=amp; + outoscilFFTfreqs.s[i]*=amp; + }; + break; + }; + srand(realrnd+1); + }; + + if ((freqHz>0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz); + + //Full RMS normalize + REALTYPE sum=0; + for (int j=1;j<OSCIL_SIZE/2;j++) { + REALTYPE term=outoscilFFTfreqs.c[j]*outoscilFFTfreqs.c[j] + +outoscilFFTfreqs.s[j]*outoscilFFTfreqs.s[j]; + sum+=term; + }; + if (sum<0.000001) sum=1.0; + sum=1.0/sqrt(sum); + for (int j=1;j<OSCIL_SIZE/2;j++) { + outoscilFFTfreqs.c[j]*=sum; + outoscilFFTfreqs.s[j]*=sum; + }; + + + if ((ADvsPAD)&&(freqHz>0.1)){//in this case the smps will contain the freqs + for (i=1;i<OSCIL_SIZE/2;i++) smps[i-1]=sqrt(outoscilFFTfreqs.c[i]*outoscilFFTfreqs.c[i] + +outoscilFFTfreqs.s[i]*outoscilFFTfreqs.s[i]); + } else { + fft->freqs2smps(outoscilFFTfreqs,smps); + for (i=0;i<OSCIL_SIZE;i++) smps[i]*=0.25;//correct the amplitude + }; + + if (Prand<64) return(outpos); + else return(0); +}; + + +/* + * Get the spectrum of the oscillator for the UI + */ +void OscilGen::getspectrum(int n, REALTYPE *spc,int what){ + if (n>OSCIL_SIZE/2) n=OSCIL_SIZE/2; + + for (int i=1;i<n;i++){ + if (what==0){ + spc[i-1]=sqrt(oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i] + +oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]); + } else { + if (Pcurrentbasefunc==0) spc[i-1]=((i==1)?(1.0):(0.0)); + else spc[i-1]=sqrt(basefuncFFTfreqs.c[i]*basefuncFFTfreqs.c[i]+ + basefuncFFTfreqs.s[i]*basefuncFFTfreqs.s[i]); + }; + }; + + if (what==0) { + for (int i=0;i<n;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=spc[i+1]; + for (int i=n;i<OSCIL_SIZE/2;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=0.0; + adaptiveharmonic(outoscilFFTfreqs,0.0); + for (int i=1;i<n;i++) spc[i-1]=outoscilFFTfreqs.s[i]; + adaptiveharmonicpostprocess(spc,n-1); + }; +}; + + +/* + * Convert the oscillator as base function + */ +void OscilGen::useasbase(){ + int i; + + for (i=0;i<OSCIL_SIZE/2;i++) { + basefuncFFTfreqs.c[i]=oscilFFTfreqs.c[i]; + basefuncFFTfreqs.s[i]=oscilFFTfreqs.s[i]; + }; + + oldbasefunc=Pcurrentbasefunc=127; + + prepare(); +}; + + +/* + * Get the base function for UI + */ +void OscilGen::getcurrentbasefunction(REALTYPE *smps){ + if (Pcurrentbasefunc!=0) { + fft->freqs2smps(basefuncFFTfreqs,smps); + } else getbasefunction(smps);//the sine case +}; + + +void OscilGen::add2XML(XMLwrapper *xml){ + xml->addpar("harmonic_mag_type",Phmagtype); + + xml->addpar("base_function",Pcurrentbasefunc); + xml->addpar("base_function_par",Pbasefuncpar); + xml->addpar("base_function_modulation",Pbasefuncmodulation); + xml->addpar("base_function_modulation_par1",Pbasefuncmodulationpar1); + xml->addpar("base_function_modulation_par2",Pbasefuncmodulationpar2); + xml->addpar("base_function_modulation_par3",Pbasefuncmodulationpar3); + + xml->addpar("modulation",Pmodulation); + xml->addpar("modulation_par1",Pmodulationpar1); + xml->addpar("modulation_par2",Pmodulationpar2); + xml->addpar("modulation_par3",Pmodulationpar3); + + xml->addpar("wave_shaping",Pwaveshaping); + xml->addpar("wave_shaping_function",Pwaveshapingfunction); + + xml->addpar("filter_type",Pfiltertype); + xml->addpar("filter_par1",Pfilterpar1); + xml->addpar("filter_par2",Pfilterpar2); + xml->addpar("filter_before_wave_shaping",Pfilterbeforews); + + xml->addpar("spectrum_adjust_type",Psatype); + xml->addpar("spectrum_adjust_par",Psapar); + + xml->addpar("rand",Prand); + xml->addpar("amp_rand_type",Pamprandtype); + xml->addpar("amp_rand_power",Pamprandpower); + + xml->addpar("harmonic_shift",Pharmonicshift); + xml->addparbool("harmonic_shift_first",Pharmonicshiftfirst); + + xml->addpar("adaptive_harmonics",Padaptiveharmonics); + xml->addpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq); + xml->addpar("adaptive_harmonics_power",Padaptiveharmonicspower); + + xml->beginbranch("HARMONICS"); + for (int n=0;n<MAX_AD_HARMONICS;n++){ + if ((Phmag[n]==64)&&(Phphase[n]==64)) continue; + xml->beginbranch("HARMONIC",n+1); + xml->addpar("mag",Phmag[n]); + xml->addpar("phase",Phphase[n]); + xml->endbranch(); + }; + xml->endbranch(); + + if (Pcurrentbasefunc==127){ + REALTYPE max=0.0; + + for (int i=0;i<OSCIL_SIZE/2;i++){ + if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); + if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); + }; + if (max<0.00000001) max=1.0; + + xml->beginbranch("BASE_FUNCTION"); + for (int i=1;i<OSCIL_SIZE/2;i++){ + REALTYPE xc=basefuncFFTfreqs.c[i]/max; + REALTYPE xs=basefuncFFTfreqs.s[i]/max; + if ((fabs(xs)>0.00001)&&(fabs(xs)>0.00001)){ + xml->beginbranch("BF_HARMONIC",i); + xml->addparreal("cos",xc); + xml->addparreal("sin",xs); + xml->endbranch(); + }; + }; + xml->endbranch(); + }; +}; + + +void OscilGen::getfromXML(XMLwrapper *xml){ + + Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); + + Pcurrentbasefunc=xml->getpar127("base_function",Pcurrentbasefunc); + Pbasefuncpar=xml->getpar127("base_function_par",Pbasefuncpar); + + Pbasefuncmodulation=xml->getpar127("base_function_modulation",Pbasefuncmodulation); + Pbasefuncmodulationpar1=xml->getpar127("base_function_modulation_par1",Pbasefuncmodulationpar1); + Pbasefuncmodulationpar2=xml->getpar127("base_function_modulation_par2",Pbasefuncmodulationpar2); + Pbasefuncmodulationpar3=xml->getpar127("base_function_modulation_par3",Pbasefuncmodulationpar3); + + Pmodulation=xml->getpar127("modulation",Pmodulation); + Pmodulationpar1=xml->getpar127("modulation_par1",Pmodulationpar1); + Pmodulationpar2=xml->getpar127("modulation_par2",Pmodulationpar2); + Pmodulationpar3=xml->getpar127("modulation_par3",Pmodulationpar3); + + Pwaveshaping=xml->getpar127("wave_shaping",Pwaveshaping); + Pwaveshapingfunction=xml->getpar127("wave_shaping_function",Pwaveshapingfunction); + + Pfiltertype=xml->getpar127("filter_type",Pfiltertype); + Pfilterpar1=xml->getpar127("filter_par1",Pfilterpar1); + Pfilterpar2=xml->getpar127("filter_par2",Pfilterpar2); + Pfilterbeforews=xml->getpar127("filter_before_wave_shaping",Pfilterbeforews); + + Psatype=xml->getpar127("spectrum_adjust_type",Psatype); + Psapar=xml->getpar127("spectrum_adjust_par",Psapar); + + Prand=xml->getpar127("rand",Prand); + Pamprandtype=xml->getpar127("amp_rand_type",Pamprandtype); + Pamprandpower=xml->getpar127("amp_rand_power",Pamprandpower); + + Pharmonicshift=xml->getpar("harmonic_shift",Pharmonicshift,-64,64); + Pharmonicshiftfirst=xml->getparbool("harmonic_shift_first",Pharmonicshiftfirst); + + Padaptiveharmonics=xml->getpar("adaptive_harmonics",Padaptiveharmonics,0,127); + Padaptiveharmonicsbasefreq=xml->getpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq,0,255); + Padaptiveharmonicspower=xml->getpar("adaptive_harmonics_power",Padaptiveharmonicspower,0,200); + + + if (xml->enterbranch("HARMONICS")){ + Phmag[0]=64;Phphase[0]=64; + for (int n=0;n<MAX_AD_HARMONICS;n++){ + if (xml->enterbranch("HARMONIC",n+1)==0) continue; + Phmag[n]=xml->getpar127("mag",64); + Phphase[n]=xml->getpar127("phase",64); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (Pcurrentbasefunc!=0) changebasefunction(); + + + if (xml->enterbranch("BASE_FUNCTION")){ + for (int i=1;i<OSCIL_SIZE/2;i++){ + if (xml->enterbranch("BF_HARMONIC",i)){ + basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0); + basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0); + xml->exitbranch(); + }; + + + }; + xml->exitbranch(); + + REALTYPE max=0.0; + + basefuncFFTfreqs.c[0]=0.0; + for (int i=0;i<OSCIL_SIZE/2;i++) { + if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); + if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); + }; + if (max<0.00000001) max=1.0; + + for (int i=0;i<OSCIL_SIZE/2;i++) { + if (basefuncFFTfreqs.c[i]) basefuncFFTfreqs.c[i]/=max; + if (basefuncFFTfreqs.s[i]) basefuncFFTfreqs.s[i]/=max; + }; + }; +}; + + + |