diff options
author | Robert Jonsson <spamatica@gmail.com> | 2011-03-07 19:01:11 +0000 |
---|---|---|
committer | Robert Jonsson <spamatica@gmail.com> | 2011-03-07 19:01:11 +0000 |
commit | e40fc849149dd97c248866a4a1d026dda5e57b62 (patch) | |
tree | b12b358f3b3a0608001d30403358f8443118ec5f /attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C | |
parent | 1bd4f2e8d9745cabb667b043171cad22c8577768 (diff) |
clean3
Diffstat (limited to 'attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C')
-rw-r--r-- | attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C b/attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C new file mode 100644 index 00000000..fa1b1163 --- /dev/null +++ b/attic/muse_qt4_evolution/synti/zynaddsubfx/Effects/Distorsion.C @@ -0,0 +1,384 @@ +/* + ZynAddSubFX - a software synthesizer + + Distorsion.C - Distorsion effect + 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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "Distorsion.h" + + +/* + * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) + */ + +void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive){ + int i; + REALTYPE ws=drive/127.0; + REALTYPE tmpv; + + switch(type){ + case 1: ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent + for (i=0;i<n;i++) + smps[i]=atan(smps[i]*ws)/atan(ws); + break; + case 2: ws=ws*ws*32.0+0.0001;//Asymmetric + if (ws<1.0) tmpv=sin(ws)+0.1; + else tmpv=1.1; + for (i=0;i<n;i++) { + smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv; + }; + break; + case 3: ws=ws*ws*ws*20.0+0.0001;//Pow + for (i=0;i<n;i++) { + smps[i]*=ws; + if (fabs(smps[i])<1.0) { + smps[i]=(smps[i]-pow(smps[i],3.0))*3.0; + if (ws<1.0) smps[i]/=ws; + } else smps[i]=0.0; + }; + break; + case 4: ws=ws*ws*ws*32.0+0.0001;//Sine + if (ws<1.57) tmpv=sin(ws); + else tmpv=1.0; + for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv; + break; + case 5: ws=ws*ws+0.000001;//Quantisize + for (i=0;i<n;i++) + smps[i]=floor(smps[i]/ws+0.5)*ws; + break; + case 6: ws=ws*ws*ws*32+0.0001;//Zigzag + if (ws<1.0) tmpv=sin(ws); + else tmpv=1.0; + for (i=0;i<n;i++) + smps[i]=asin(sin(smps[i]*ws))/tmpv; + break; + case 7: ws=pow(2.0,-ws*ws*8.0); //Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (fabs(tmp)>ws) { + if (tmp>=0.0) smps[i]=1.0; + else smps[i]=-1.0; + } else smps[i]/=ws; + }; + break; + case 8: ws=pow(2.0,-ws*ws*8.0); //Upper Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (tmp>ws) smps[i]=ws; + smps[i]*=2.0; + }; + break; + case 9: ws=pow(2.0,-ws*ws*8.0); //Lower Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (tmp<-ws) smps[i]=-ws; + smps[i]*=2.0; + }; + break; + case 10:ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (fabs(tmp)>ws) { + if (tmp>=0.0) smps[i]=tmp-ws; + else smps[i]=tmp+ws; + } else smps[i]=0; + }; + break; + case 11:ws=pow(5,ws*ws*1.0)-1.0;//Clip + for (i=0;i<n;i++) + smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999); + break; + case 12:ws=ws*ws*ws*30+0.001;//Asym2 + if (ws<0.3) tmpv=ws; + else tmpv=1.0; + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv; + else smps[i]=0.0; + }; + break; + case 13:ws=ws*ws*ws*32.0+0.0001;//Pow2 + if (ws<1.0) tmpv=ws*(1+ws)/2.0; + else tmpv=1.0; + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv; + else if (tmp>0.0) smps[i]=-1.0; + else smps[i]=-2.0; + }; + break; + case 14:ws=pow(ws,5.0)*80.0+0.0001;//sigmoid + if (ws>10.0) tmpv=0.5; + else tmpv=0.5-1.0/(exp(ws)+1.0); + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if (tmp<-10.0) tmp=-10.0; + else if (tmp>10.0) tmp=10.0; + tmp=0.5-1.0/(exp(tmp)+1.0); + smps[i]=tmp/tmpv; + }; + break; + //update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions + }; + +}; + + +Distorsion::Distorsion(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_){ + efxoutl=efxoutl_; + efxoutr=efxoutr_; + + lpfl=new AnalogFilter(2,22000,1,0); + lpfr=new AnalogFilter(2,22000,1,0); + hpfl=new AnalogFilter(3,20,1,0); + hpfr=new AnalogFilter(3,20,1,0); + + filterpars=NULL; + + insertion=insertion_; + //default values + Ppreset=0; + Pvolume=50; + Plrcross=40; + Pdrive=90; + Plevel=64; + Ptype=0; + Pnegate=0; + Plpf=127; + Phpf=0; + Pstereo=0; + Pprefiltering=0; + + setpreset(Ppreset); + cleanup(); +}; + +Distorsion::~Distorsion(){ + delete (lpfl); + delete (lpfr); + delete (hpfl); + delete (hpfr); + +}; + +/* + * Cleanup the effect + */ +void Distorsion::cleanup(){ + lpfl->cleanup(); + hpfl->cleanup(); + lpfr->cleanup(); + hpfr->cleanup(); +}; + + +/* + * Apply the filters + */ + +void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr){ + lpfl->filterout(efxoutl); + hpfl->filterout(efxoutl); + if (Pstereo!=0){//stereo + lpfr->filterout(efxoutr); + hpfr->filterout(efxoutr); + }; + +}; + + +/* + * Effect output + */ +void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr){ + int i; + REALTYPE l,r,lout,rout; + + REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0); + if (Pnegate!=0) inputvol*=-1.0; + + if (Pstereo!=0){//Stereo + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + efxoutl[i]=smpsl[i]*inputvol*panning; + efxoutr[i]=smpsr[i]*inputvol*(1.0-panning); + }; + } else { + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol; + }; + }; + + if (Pprefiltering!=0) applyfilters(efxoutl,efxoutr); + + //no optimised, yet (no look table) + waveshapesmps(SOUND_BUFFER_SIZE,efxoutl,Ptype+1,Pdrive); + if (Pstereo!=0) waveshapesmps(SOUND_BUFFER_SIZE,efxoutr,Ptype+1,Pdrive); + + if (Pprefiltering==0) applyfilters(efxoutl,efxoutr); + + if (Pstereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) efxoutr[i]=efxoutl[i]; + + REALTYPE level=dB2rap(60.0*Plevel/127.0-40.0); + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + lout=efxoutl[i]; + rout=efxoutr[i]; + l=lout*(1.0-lrcross)+rout*lrcross; + r=rout*(1.0-lrcross)+lout*lrcross; + lout=l;rout=r; + + efxoutl[i]=lout*2.0*level; + efxoutr[i]=rout*2.0*level; + + }; + +}; + + +/* + * Parameter control + */ +void Distorsion::setvolume(unsigned char Pvolume){ + this->Pvolume=Pvolume; + + if (insertion==0) { + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; + } else { + volume=outvolume=Pvolume/127.0; + }; + if (Pvolume==0) cleanup(); + +}; + +void Distorsion::setpanning(unsigned char Ppanning){ + this->Ppanning=Ppanning; + panning=(Ppanning+0.5)/127.0; +}; + + +void Distorsion::setlrcross(unsigned char Plrcross){ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0*1.0; +}; + +void Distorsion::setlpf(unsigned char Plpf){ + this->Plpf=Plpf; + REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; + lpfl->setfreq(fr); + lpfr->setfreq(fr); +}; + +void Distorsion::sethpf(unsigned char Phpf){ + this->Phpf=Phpf; + REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0; + hpfl->setfreq(fr); + hpfr->setfreq(fr); +}; + + +void Distorsion::setpreset(unsigned char npreset){ + const int PRESET_SIZE=11; + const int NUM_PRESETS=6; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Overdrive 1 + {127,64,35,56,70,0,0,96,0,0,0}, + //Overdrive 2 + {127,64,35,29,75,1,0,127,0,0,0}, + //A. Exciter 1 + {64,64,35,75,80,5,0,127,105,1,0}, + //A. Exciter 2 + {64,64,35,85,62,1,0,127,118,1,0}, + //Guitar Amp + {127,64,35,63,75,2,0,55,0,0,0}, + //Quantisize + {127,64,35,88,75,4,0,127,0,1,0}}; + + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); + if (insertion==0) changepar(0,(int) (presets[npreset][0]/1.5));//lower the volume if this is system effect + Ppreset=npreset; + cleanup(); +}; + + +void Distorsion::changepar(int npar,unsigned char value){ + switch (npar){ + case 0: setvolume(value); + break; + case 1: setpanning(value); + break; + case 2: setlrcross(value); + break; + case 3: Pdrive=value; + break; + case 4: Plevel=value; + break; + case 5: if (value>13) value=13;//this must be increased if more distorsion types are added + Ptype=value; + break; + case 6: if (value>1) value=1; + Pnegate=value; + break; + case 7: setlpf(value); + break; + case 8: sethpf(value); + break; + case 9: if (value>1) value=1; + Pstereo=value; + break; + case 10:Pprefiltering=value; + break; + }; +}; + +unsigned char Distorsion::getpar(int npar){ + switch (npar){ + case 0: return(Pvolume); + break; + case 1: return(Ppanning); + break; + case 2: return(Plrcross); + break; + case 3: return(Pdrive); + break; + case 4: return(Plevel); + break; + case 5: return(Ptype); + break; + case 6: return(Pnegate); + break; + case 7: return(Plpf); + break; + case 8: return(Phpf); + break; + case 9: return(Pstereo); + break; + case 10:return(Pprefiltering); + break; + }; + return(0);//in case of bogus parameter number +}; + + + + |