/* 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 #include #include #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;iws) { 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;iws) smps[i]=ws; smps[i]*=2.0; }; break; case 9: ws=pow(2.0,-ws*ws*8.0); //Lower Limiter for (i=0;iws) { 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-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-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;i10.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;iPvolume=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;n13) 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 };