/* 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 #include #include #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;ismps2freqs(oscil,freqs); delete(fft); REALTYPE max=0.0; mag[0]=0; phase[0]=0; for (int i=0;i127) 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)0.99999) a=0.99999; x=fmod(x,1); if (x1.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;ipow(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)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 (maxsmps2freqs(tmpsmps,basefuncFFTfreqs); basefuncFFTfreqs.c[0]=0.0; } else { for (int i=0;ifreqs2smps(oscilFFTfreqs,tmpsmps); //Normalize REALTYPE max=0.0; for (i=0;ismps2freqs(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;ifreqs2smps(oscilFFTfreqs,tmpsmps); int extra_points=2; REALTYPE *in=new REALTYPE[OSCIL_SIZE+extra_points]; //Normalize REALTYPE max=0.0; for (i=0;ismps2freqs(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;i1.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)){ 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=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;i1.0) { rap=1.0/rap; down=true; }; for (int i=0;i=(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;iget(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;iOSCIL_SIZE/2) nyquist=OSCIL_SIZE/2; int realnyquist=nyquist; if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2; for (i=1;i64)&&(freqHz>=0.0)&&(!ADvsPAD)){ REALTYPE rnd,angle,a,b,c,d; rnd=PI*pow((Prand-64.0)/64.0,2.0); for (i=1;i0.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;i0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz); //Full RMS normalize REALTYPE sum=0; for (int j=1;j0.1)){//in this case the smps will contain the freqs for (i=1;ifreqs2smps(outoscilFFTfreqs,smps); for (i=0;iOSCIL_SIZE/2) n=OSCIL_SIZE/2; for (int i=1;ifreqs2smps(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;nbeginbranch("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;ibeginbranch("BASE_FUNCTION"); for (int i=1;i0.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;nenterbranch("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;ienterbranch("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