/* 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; }; }; };