zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 9a559a95148be436a2c0a95826a507341ab479d8
parent 34d0a55b2637f3a0f3105fde43cef3a5057907c9
Author: fundamental <fundamental>
Date:   Fri, 10 Apr 2009 20:01:10 +0000

Preforming more work on Effect code

Diffstat:
Msrc/Effects/Alienwah.C | 77+++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/Effects/Alienwah.h | 13+++++--------
Msrc/Effects/Chorus.C | 18+++++++++++-------
Msrc/Effects/Chorus.h | 40+++++++++++++++++++++++++++++++++++++++-
Msrc/Effects/Distorsion.C | 6++----
Msrc/Effects/Distorsion.h | 2+-
Msrc/Effects/DynamicFilter.C | 8+++++---
Msrc/Effects/DynamicFilter.h | 2+-
Msrc/Effects/EQ.C | 4+---
Msrc/Effects/Echo.C | 7++++---
Msrc/Effects/Echo.h | 17++++++++++-------
Msrc/Effects/Effect.h | 27++++++++++++++++++++-------
Msrc/Effects/EffectLFO.C | 7+++----
Msrc/Effects/EffectLFO.h | 7++++---
Msrc/Effects/EffectMgr.C | 38+++++++++++++++++++++-----------------
Msrc/Effects/EffectMgr.h | 33++++++++++++++++++++++++++-------
Msrc/Effects/Phaser.C | 500++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Effects/Phaser.h | 141++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Reverb.C | 865+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Effects/Reverb.h | 252++++++++++++++++++++++++++++++++++++++++----------------------------------------
20 files changed, 1065 insertions(+), 999 deletions(-)

diff --git a/src/Effects/Alienwah.C b/src/Effects/Alienwah.C @@ -20,17 +20,16 @@ */ -#include <math.h> +#include <cmath> #include "Alienwah.h" -#include <stdio.h> -Alienwah::Alienwah(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) +Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) { setpreset(Ppreset); cleanup(); - oldclfol.a=fb;oldclfol.b=0.0; - oldclfor.a=fb;oldclfor.b=0.0; + oldclfol=complex<REALTYPE>(fb,0.0); + oldclfor=complex<REALTYPE>(fb,0.0); }; Alienwah::~Alienwah(){ @@ -43,39 +42,38 @@ Alienwah::~Alienwah(){ * Apply the effect */ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - REALTYPE lfol,lfor; - COMPLEXTYPE clfol,clfor,out,tmp; - + REALTYPE lfol,lfor; //Left/Right LFOs + complex<REALTYPE> clfol,clfor,out,tmp; + /**\todo Rework, as optimization can be used when the new complex type is + * utilized. + * Before all calculations needed to be done with individual REALTYPE, + * but now they can be done together*/ lfo.effectlfoout(&lfol,&lfor); lfol*=depth*PI*2.0;lfor*=depth*PI*2.0; - clfol.a=cos(lfol+phase)*fb;clfol.b=sin(lfol+phase)*fb; - clfor.a=cos(lfor+phase)*fb;clfor.b=sin(lfor+phase)*fb; + clfol=complex<REALTYPE>(cos(lfol+phase)*fb,sin(lfol+phase)*fb); //rework + clfor=complex<REALTYPE>(cos(lfor+phase)*fb,sin(lfor+phase)*fb); //rework - for (i=0;i<SOUND_BUFFER_SIZE;i++){ + for (int i=0;i<SOUND_BUFFER_SIZE;i++){/**\todo reduce significantly with + * valarray*/ REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE; REALTYPE x1=1.0-x; - //left - tmp.a=clfol.a*x+oldclfol.a*x1; - tmp.b=clfol.b*x+oldclfol.b*x1; - - out.a=tmp.a*oldl[oldk].a-tmp.b*oldl[oldk].b - +(1-fabs(fb))*smpsl[i]*panning; - out.b=tmp.a*oldl[oldk].b+tmp.b*oldl[oldk].a; - oldl[oldk].a=out.a; - oldl[oldk].b=out.b; - REALTYPE l=out.a*10.0*(fb+0.1); + //left + tmp=clfol*x+oldclfol*x1; + + out=tmp*oldl[oldk]; + out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning); + + oldl[oldk]=out; + REALTYPE l=out.real()*10.0*(fb+0.1); //right - tmp.a=clfor.a*x+oldclfor.a*x1; - tmp.b=clfor.b*x+oldclfor.b*x1; + tmp=clfor*x+oldclfor*x1; + + out=tmp*oldr[oldk]; + out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning); - out.a=tmp.a*oldr[oldk].a-tmp.b*oldr[oldk].b - +(1-fabs(fb))*smpsr[i]*(1.0-panning); - out.b=tmp.a*oldr[oldk].b+tmp.b*oldr[oldk].a; - oldr[oldk].a=out.a; - oldr[oldk].b=out.b; - REALTYPE r=out.a*10.0*(fb+0.1); + oldr[oldk]=out; + REALTYPE r=out.real()*10.0*(fb+0.1); if (++oldk>=Pdelay) oldk=0; @@ -84,8 +82,8 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ efxoutr[i]=r*(1.0-lrcross)+l*lrcross; }; - oldclfol.a=clfol.a;oldclfol.b=clfol.b; - oldclfor.a=clfor.a;oldclfor.b=clfor.b; + oldclfol=clfol; + oldclfor=clfor; }; @@ -93,11 +91,9 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ * Cleanup the effect */ void Alienwah::cleanup(){ - for (int i=0;i<Pdelay;i++) { - oldl[i].a=0.0; - oldl[i].b=0.0; - oldr[i].a=0.0; - oldr[i].b=0.0; + for (int i=0;i<Pdelay;i++) { /**\todo reduce with valarray*/ + oldl[i]=complex<REALTYPE>(0.0,0.0); + oldr[i]=complex<REALTYPE>(0.0,0.0); }; oldk=0; }; @@ -147,8 +143,8 @@ void Alienwah::setdelay(const unsigned char &Pdelay){ if (oldr!=NULL) delete [] oldr; if (Pdelay>=MAX_ALIENWAH_DELAY) this->Pdelay=MAX_ALIENWAH_DELAY; else this->Pdelay=Pdelay; - oldl=new COMPLEXTYPE[Pdelay]; - oldr=new COMPLEXTYPE[Pdelay]; + oldl=new complex<REALTYPE>[Pdelay]; + oldr=new complex<REALTYPE>[Pdelay]; cleanup(); }; @@ -232,6 +228,3 @@ unsigned char Alienwah::getpar(const int &npar)const{ }; - - - diff --git a/src/Effects/Alienwah.h b/src/Effects/Alienwah.h @@ -22,17 +22,15 @@ #ifndef ALIENWAH_H #define ALIENWAH_H +#include <complex> #include "../globals.h" #include "Effect.h" #include "EffectLFO.h" +using namespace std; #define MAX_ALIENWAH_DELAY 100 -struct COMPLEXTYPE { - REALTYPE a,b; -}; - /**"AlienWah" Effect*/ class Alienwah:public Effect { public: @@ -43,7 +41,7 @@ class Alienwah:public Effect { * @param efxoutr_ Pointer to Alienwah's left channel output buffer * @return Initialized Alienwah */ - Alienwah(int insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); + Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); ~Alienwah(); void out(REALTYPE *const smpsl,REALTYPE *const smpsr); @@ -74,10 +72,9 @@ class Alienwah:public Effect { void setphase(const unsigned char &Pphase); //Internal Values - //const int insertion; //value inherited REALTYPE panning,fb,depth,lrcross,phase; - COMPLEXTYPE *oldl,*oldr; - COMPLEXTYPE oldclfol,oldclfor; + complex<REALTYPE> *oldl,*oldr; + complex<REALTYPE> oldclfol,oldclfor; int oldk; }; diff --git a/src/Effects/Chorus.C b/src/Effects/Chorus.C @@ -20,9 +20,11 @@ */ -#include <math.h> +#include <cmath> #include "Chorus.h" -#include <stdio.h> +#include <iostream> + +using namespace std; Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) @@ -54,9 +56,10 @@ REALTYPE Chorus::getdelay(REALTYPE xlfo){ result=(delay+xlfo*depth)*SAMPLE_RATE; } else result=0; - //check if it is too big delay(caused bu errornous setdelay() and setdepth() + //check if it is too big delay(caused bu errornous setdelay() and setdepth() + /**\todo fix setdelay() and setdepth(), so this error cannot occur*/ if ((result+0.5)>=maxdelay) { - fprintf(stderr,"%s","WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"); + cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; result=maxdelay-1.0; }; return(result); @@ -67,6 +70,7 @@ REALTYPE Chorus::getdelay(REALTYPE xlfo){ */ void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){ int i; + const REALTYPE one=1.0; dl1=dl2;dr1=dr2; lfo.effectlfoout(&lfol,&lfor); @@ -93,7 +97,7 @@ void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){ dlhi%=maxdelay; dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,1.0); + dllo=1.0-fmod(tmp,one); efxoutl[i]=delayl[dlhi2]*dllo+delayl[dlhi]*(1.0-dllo); delayl[dlk]=inl+efxoutl[i]*fb; @@ -102,13 +106,13 @@ void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){ //compute the delay in samples using linear interpolation between the lfo delays mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE; if (++drk>=maxdelay) drk=0; - tmp=drk-mdel+maxdelay*2.0;//where should I get the sample from + tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from F2I(tmp,dlhi); dlhi%=maxdelay; dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,1.0); + dllo=1.0-fmod(tmp,one); efxoutr[i]=delayr[dlhi2]*dllo+delayr[dlhi]*(1.0-dllo); delayr[dlk]=inr+efxoutr[i]*fb; diff --git a/src/Effects/Chorus.h b/src/Effects/Chorus.h @@ -28,13 +28,51 @@ #define MAX_CHORUS_DELAY 250.0 //ms +/**Chorus and Flange effects*/ class Chorus:public Effect { public: Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + /**Destructor*/ ~Chorus(); void out(REALTYPE *smpsl,REALTYPE *smpsr); void setpreset(unsigned char npreset); + /** + * Sets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @param value the new value + */ void changepar(const int &npar,const unsigned char &value); + /** + * Gets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @return the value of the parameter + */ unsigned char getpar(const int &npar)const; void cleanup(); @@ -51,7 +89,7 @@ class Chorus:public Effect { unsigned char Poutsub;//if I wish to substract the output instead of the adding it - //Control Parametrii + //Parameter Controls void setvolume(const unsigned char &Pvolume); void setpanning(const unsigned char &Ppanning); void setdepth(const unsigned char &Pdepth); diff --git a/src/Effects/Distorsion.C b/src/Effects/Distorsion.C @@ -20,9 +20,7 @@ */ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> +#include <cmath> #include "Distorsion.h" @@ -137,7 +135,7 @@ void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive){ smps[i]=tmp/tmpv; }; break; - //update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions + /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ }; }; diff --git a/src/Effects/Distorsion.h b/src/Effects/Distorsion.h @@ -29,7 +29,7 @@ //Waveshaping(called by Distorsion effect and waveshape from OscilGen) void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive); - +/**Distortion Effect*/ class Distorsion:public Effect{ public: Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_); diff --git a/src/Effects/DynamicFilter.C b/src/Effects/DynamicFilter.C @@ -20,9 +20,8 @@ */ -#include <math.h> +#include <cmath> #include "DynamicFilter.h" -#include <stdio.h> DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) :Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0), @@ -127,7 +126,10 @@ void DynamicFilter::setpanning(const unsigned char &Ppanning){ void DynamicFilter::setampsns(const unsigned char &Pampsns){ ampsns=pow(Pampsns/127.0,2.5)*10.0; if (Pampsnsinv!=0) ampsns=-ampsns; - ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99; + ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99;/**\todo currently Pampsmooth is + * uninitialized when this is + * called. Please fix. + */ this->Pampsns=Pampsns; }; diff --git a/src/Effects/DynamicFilter.h b/src/Effects/DynamicFilter.h @@ -27,7 +27,7 @@ #include "EffectLFO.h" #include "../DSP/Filter.h" - +/**DynamicFilter Effect*/ class DynamicFilter:public Effect { public: DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); diff --git a/src/Effects/EQ.C b/src/Effects/EQ.C @@ -20,9 +20,7 @@ */ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> +#include <cmath> #include "EQ.h" EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) diff --git a/src/Effects/Echo.C b/src/Effects/Echo.C @@ -150,6 +150,7 @@ void Echo::sethidamp(const unsigned char & Phidamp){ } void Echo::setpreset(unsigned char npreset){ + /**\todo see if the preset array can be replaced with a struct or a class*/ const int PRESET_SIZE=7; const int NUM_PRESETS=9; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ @@ -175,12 +176,13 @@ void Echo::setpreset(unsigned char npreset){ 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,presets[npreset][0]/2);//lower the volume if this is insertion effect + if (insertion!=0) setvolume(presets[npreset][0]/2);//lower the volume if this is insertion effect Ppreset=npreset; } void Echo::changepar(const int & npar,const unsigned char & value){ + /**\todo get rid of this leaky abstraction*/ switch (npar){ case 0: setvolume(value); break; @@ -197,11 +199,10 @@ void Echo::changepar(const int & npar,const unsigned char & value){ case 6: sethidamp(value); break; }; - /**\todo in case of bogus parameter number print error to find depreciated - *calls*/ } unsigned char Echo::getpar(const int & npar)const{ + /**\todo get rid of this leaky abstraction*/ switch (npar){ case 0: return(Pvolume); break; diff --git a/src/Effects/Echo.h b/src/Effects/Echo.h @@ -49,6 +49,8 @@ class Echo:public Effect{ * Outputs the echo to efxoutl and efxoutr * @param smpsl Sample from Left channel * @param smpsr Sample from Right channel + * \todo try to figure out if smpsl should be const *const + * or not */ void out(REALTYPE *const smpsl,REALTYPE *const smpr); @@ -99,14 +101,15 @@ class Echo:public Effect{ /**\todo This function needs to be implemented or the prototype should be removed*/ void setdryonly(); private: + /**\todo remove all of these once they have been depreciated*/ //Parameters - unsigned char Pvolume;/**< Volume or Dry/Wetness*/ - unsigned char Ppanning;/**< Panning*/ - unsigned char Pdelay;/**< Delay of the Echo*/ - unsigned char Plrdelay;/**< L/R delay difference*/ - unsigned char Plrcross;/**< L/R Mixing*/ - unsigned char Pfb;/**<Feedback*/ - unsigned char Phidamp;/**<Dampening of the Echo*/ + unsigned char Pvolume;/**<#1 Volume or Dry/Wetness*/ + unsigned char Ppanning;/**<#2 Panning*/ + unsigned char Pdelay;/**<#3 Delay of the Echo*/ + unsigned char Plrdelay;/**<#4 L/R delay difference*/ + unsigned char Plrcross;/**<#5 L/R Mixing*/ + unsigned char Pfb;/**<#6Feedback*/ + unsigned char Phidamp;/**<#7Dampening of the Echo*/ void setvolume(const unsigned char & Pvolume); void setpanning(const unsigned char & Ppanning); diff --git a/src/Effects/Effect.h b/src/Effects/Effect.h @@ -23,7 +23,7 @@ #ifndef EFFECT_H #define EFFECT_H -#include <pthread.h> +#include <valarray> #include "../Misc/Util.h" #include "../globals.h" #include "../Params/FilterParams.h" @@ -44,30 +44,43 @@ class Effect{ Effect(const int & insertion_,REALTYPE *const efxoutl_, REALTYPE *const efxoutr_,FilterParams *filterpars_, const unsigned char & Ppreset_); - /**Deconstructor*/ + /**Deconstructor + * + * Deconstructs the Effect and releases any resouces that it has + * allocated for itself*/ virtual ~Effect(){}; /** * Choose a preset * @param npreset number of chosen preset*/ - virtual void setpreset(unsigned char npreset){}; + virtual void setpreset(unsigned char npreset)=0; /**Change parameter npar to value * @param npar chosen parameter * @param value chosen new value*/ - virtual void changepar(const int &npar,const unsigned char &value){}; + virtual void changepar(const int &npar,const unsigned char &value)=0; /**Get the value of parameter npar * @param npar chosen parameter * @return the value of the parameter in an unsigned char or 0 if it * does not exist*/ - virtual unsigned char getpar(const int &npar)const {return(0);}; - virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr){}; + virtual unsigned char getpar(const int &npar)const=0; + /**Output result of effect based on the given buffers + * + * This method should result in the effect generating its results + * and placing them into the efxoutl and efxoutr buffers. + * Every Effect should overide this method. + * + * @param smpsl Input buffer for the Left channel + * @param smpsr Input buffer for the Right channel + */ + virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0; /**Reset the state of the effect*/ virtual void cleanup(){}; /**This is only used for EQ (for user interface)*/ virtual REALTYPE getfreqresponse(REALTYPE freq){return (0);}; - unsigned char Ppreset; + unsigned char Ppreset;/**<Currently used preset*/ REALTYPE *const efxoutl;/**<Effect out Left Channel*/ REALTYPE *const efxoutr;/**<Effect out Right Channel*/ + /**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/ REALTYPE outvolume;/**<This is the volume of effect and is public because * it is needed in system effects. diff --git a/src/Effects/EffectLFO.C b/src/Effects/EffectLFO.C @@ -20,9 +20,8 @@ */ -#include <stdlib.h> -#include <stdio.h> -#include <math.h> +#include <cstdlib> +#include <cmath> #include "EffectLFO.h" @@ -75,7 +74,7 @@ REALTYPE EffectLFO::getlfoshape(REALTYPE x){ else if ((x>0.25)&&(x<0.75)) out=2-4*x; else out=4.0*x-4.0; break; - //more to be added here; also ::updateparams() need to be updated (to allow more lfotypes) + /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ default:out=cos(x*2*PI);//EffectLFO_SINE }; return(out); diff --git a/src/Effects/EffectLFO.h b/src/Effects/EffectLFO.h @@ -24,7 +24,7 @@ #define EFFECT_LFO_H #include "../globals.h" - +/**LFO for some of the Effect objects*/ class EffectLFO{ public: EffectLFO(); @@ -40,11 +40,12 @@ class EffectLFO{ REALTYPE xl,xr; REALTYPE incx; - REALTYPE ampl1,ampl2,ampr1,ampr2;//necesar pentru "randomness" + REALTYPE ampl1,ampl2,ampr1,ampr2;//necessary for "randomness" REALTYPE lfointensity; REALTYPE lfornd; - char lfotype; + char lfotype; /**\todo GET RID OF CHAR (use a subclass if types are needed)*/ }; #endif + diff --git a/src/Effects/EffectMgr.C b/src/Effects/EffectMgr.C @@ -20,30 +20,34 @@ */ -#include <stdlib.h> -#include <stdio.h> #include "EffectMgr.h" -EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_){ - setpresettype("Peffect"); - efx=NULL; - nefx=0; - insertion=insertion_; - mutex=mutex_; - efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; - efxoutr=new REALTYPE[SOUND_BUFFER_SIZE];; +EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) + :insertion(insertion_), + efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), + efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), + filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false) +{ + setpresettype("Peffect"); /**\todo Figure out what this is doing + * , as it might be another leaky abstraction.*/ +// efx=NULL; +// nefx=0; +// insertion=insertion_; +// mutex=mutex_; +// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; +// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE]; for (int i=0;i<SOUND_BUFFER_SIZE;i++){ efxoutl[i]=0.0; efxoutr[i]=0.0; }; - filterpars=NULL; - dryonly=false; +// filterpars=NULL; +// dryonly=false; defaults(); } EffectMgr::~EffectMgr(){ - if (efx!=NULL) delete (efx); + if (efx!=NULL) delete efx; delete []efxoutl; delete []efxoutr; } @@ -66,7 +70,7 @@ void EffectMgr::changeeffect(int nefx_){ }; if (efx!=NULL) delete efx; - switch (nefx){ + switch (nefx){ /**\todo replace leaky abstraction*/ case 1:efx=new Reverb(insertion,efxoutl,efxoutr);break; case 2:efx=new Echo(insertion,efxoutl,efxoutr);break; case 3:efx=new Chorus(insertion,efxoutl,efxoutr);break; @@ -173,6 +177,7 @@ void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr){ REALTYPE volume=efx->volume; if (nefx==7){//this is need only for the EQ effect + /**\todo figure out why*/ for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]=efxoutl[i]; smpsr[i]=efxoutr[i]; @@ -245,7 +250,8 @@ void EffectMgr::add2XML(XMLwrapper *xml){ xml->addpar("preset",efx->Ppreset); xml->beginbranch("EFFECT_PARAMETERS"); - for (int n=0;n<128;n++){ + for (int n=0;n<128;n++){ /**\todo evaluate who should oversee saving + * and loading of parameters*/ int par=geteffectpar(n); if (par==0) continue; xml->beginbranch("par_no",n); @@ -287,5 +293,3 @@ void EffectMgr::getfromXML(XMLwrapper *xml){ cleanup(); } - - diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h @@ -17,7 +17,6 @@ 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 - */ #ifndef EFFECTMGR_H @@ -57,19 +56,41 @@ class EffectMgr:public Presets{ REALTYPE sysefxgetvolume(); void cleanup();/**<cleanup the effect*/ - + + /**change effect to the given int + * @param nefx_ the number of the effect*/ void changeeffect(int nefx_); + /**Get the number of the effect + * @return the number + * \todo try to fix abstraction failure*/ int geteffect(); + /** + * Change the preset to the given one + * @param npreset number of the chosen preset + * \todo figure out why this is binary + */ void changepreset(unsigned char npreset); + /** + * Change the preset to the given one without locking the thread + * @param npreset number of the chosen preset + * \todo figure out why this is binary + */ void changepreset_nolock(unsigned char npreset); + /** + * Get the current preset + * @return the current preset*/ unsigned char getpreset(); + /**sets the effect par*/ void seteffectpar(int npar,unsigned char value); - void seteffectpar_nolock(int npar,unsigned char value);/**<sets the effect par without thread lock*/ + /**<sets the effect par without thread lock*/ + void seteffectpar_nolock(int npar,unsigned char value); unsigned char geteffectpar(int npar); - int insertion;/**<1 if the effect is connected as insertion effect*/ + int insertion;/**<1 if the effect is connected as insertion effect + * \todo figure out why this is not a bool*/ REALTYPE *efxoutl,*efxoutr; - //used by UI + /**used by UI + * \todo needs to be decoupled*/ REALTYPE getEQfreqresponse(REALTYPE freq); FilterParams *filterpars; @@ -83,5 +104,3 @@ class EffectMgr:public Presets{ #endif - - diff --git a/src/Effects/Phaser.C b/src/Effects/Phaser.C @@ -1,250 +1,250 @@ -/* - ZynAddSubFX - a software synthesizer - - Phaser.C - Phaser 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 or later) 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 <math.h> -#include "Phaser.h" -#include <stdio.h> -#define PHASER_LFO_SHAPE 2 - -Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) -{ - setpreset(Ppreset); - cleanup(); -}; - -Phaser::~Phaser(){ - if (oldl!=NULL) delete [] oldl; - if (oldr!=NULL) delete [] oldr; -}; - - -/* - * Effect output - */ -void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i,j; - REALTYPE lfol,lfor,lgain,rgain,tmp; - - lfo.effectlfoout(&lfol,&lfor); - lgain=lfol; - rgain=lfor; - lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); - rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); - - - lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth; - rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth; - - if (lgain>1.0) lgain=1.0;else if (lgain<0.0) lgain=0.0; - if (rgain>1.0) rgain=1.0;else if (rgain<0.0) rgain=0.0; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE; - REALTYPE x1=1.0-x; - REALTYPE gl=lgain*x+oldlgain*x1; - REALTYPE gr=rgain*x+oldrgain*x1; - REALTYPE inl=smpsl[i]*panning+fbl; - REALTYPE inr=smpsr[i]*(1.0-panning)+fbr; - - //Left channel - for (j=0;j<Pstages*2;j++){//Phasing routine - tmp=oldl[j]; - oldl[j]=gl*tmp+inl; - inl=tmp-gl*oldl[j]; - }; - //Right channel - for (j=0;j<Pstages*2;j++){//Phasing routine - tmp=oldr[j]; - oldr[j]=gr*tmp+inr; - inr=tmp-gr*oldr[j]; - }; - //Left/Right crossing - REALTYPE l=inl; - REALTYPE r=inr; - inl=l*(1.0-lrcross)+r*lrcross; - inr=r*(1.0-lrcross)+l*lrcross; - - fbl=inl*fb; - fbr=inr*fb; - efxoutl[i]=inl; - efxoutr[i]=inr; - - }; - - oldlgain=lgain; oldrgain=rgain; - - if (Poutsub!=0) - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]*= -1.0; - efxoutr[i]*= -1.0; - }; - -}; - -/* - * Cleanup the effect - */ -void Phaser::cleanup(){ - fbl=0.0;fbr=0.0; - oldlgain=0.0; - oldrgain=0.0; - for (int i=0;i<Pstages*2;i++) { - oldl[i]=0.0; - oldr[i]=0.0; - }; -}; - -/* - * Parameter control - */ -void Phaser::setdepth(const unsigned char &Pdepth){ - this->Pdepth=Pdepth; - depth=(Pdepth/127.0); -}; - - -void Phaser::setfb(const unsigned char &Pfb){ - this->Pfb=Pfb; - fb=(Pfb-64.0)/64.1; -}; - -void Phaser::setvolume(const unsigned char &Pvolume){ - this->Pvolume=Pvolume; - outvolume=Pvolume/127.0; - if (insertion==0) volume=1.0; - else volume=outvolume; -}; - -void Phaser::setpanning(const unsigned char &Ppanning){ - this->Ppanning=Ppanning; - panning=Ppanning/127.0; -}; - -void Phaser::setlrcross(const unsigned char &Plrcross){ - this->Plrcross=Plrcross; - lrcross=Plrcross/127.0; -}; - -void Phaser::setstages(const unsigned char &Pstages){ - if (oldl!=NULL) delete [] oldl; - if (oldr!=NULL) delete [] oldr; - if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1; - else this->Pstages=Pstages; - oldl=new REALTYPE[Pstages*2]; - oldr=new REALTYPE[Pstages*2]; - cleanup(); -}; - -void Phaser::setphase(const unsigned char &Pphase){ - this->Pphase=Pphase; - phase=(Pphase/127.0); -}; - - -void Phaser::setpreset(unsigned char npreset){ - const int PRESET_SIZE=12; - const int NUM_PRESETS=6; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Phaser1 - {64,64,36,0,0,64,110,64,1,0,0,20}, - //Phaser2 - {64,64,35,0,0,88,40,64,3,0,0,20}, - //Phaser3 - {64,64,31,0,0,66,68,107,2,0,0,20}, - //Phaser4 - {39,64,22,0,0,66,67,10,5,0,1,20}, - //Phaser5 - {64,64,20,0,1,110,67,78,10,0,0,20}, - //Phaser6 - {64,64,53,100,0,58,37,78,3,0,0,20}}; - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); - Ppreset=npreset; -}; - - -void Phaser::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setfb(value); - break; - case 8: setstages(value); - break; - case 9: setlrcross(value); - break; - case 10:if (value>1) Poutsub=1; - else Poutsub=value; - break; - case 11:setphase(value); - break; - }; -}; - -unsigned char Phaser::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pfb); - break; - case 8: return(Pstages); - break; - case 9: return(Plrcross); - break; - case 10:return(Poutsub); - break; - case 11:return(Pphase); - break; - default:return (0); - }; - -}; - +/* + ZynAddSubFX - a software synthesizer + + Phaser.C - Phaser 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 or later) 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 <cmath> +#include "Phaser.h" +/**\todo figure out why this define was made*/ +#define PHASER_LFO_SHAPE 2 + +Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) +{ + setpreset(Ppreset); + cleanup(); +}; + +Phaser::~Phaser(){ + if (oldl!=NULL) delete [] oldl; + if (oldr!=NULL) delete [] oldr; +}; + + +/* + * Effect output + */ +void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){ + int i,j; + REALTYPE lfol,lfor,lgain,rgain,tmp; + + lfo.effectlfoout(&lfol,&lfor); + lgain=lfol; + rgain=lfor; + lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); + rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); + + + lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth; + rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth; + + if (lgain>1.0) lgain=1.0;else if (lgain<0.0) lgain=0.0; + if (rgain>1.0) rgain=1.0;else if (rgain<0.0) rgain=0.0; + + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE; + REALTYPE x1=1.0-x; + REALTYPE gl=lgain*x+oldlgain*x1; + REALTYPE gr=rgain*x+oldrgain*x1; + REALTYPE inl=smpsl[i]*panning+fbl; + REALTYPE inr=smpsr[i]*(1.0-panning)+fbr; + + //Left channel + for (j=0;j<Pstages*2;j++){//Phasing routine + tmp=oldl[j]; + oldl[j]=gl*tmp+inl; + inl=tmp-gl*oldl[j]; + }; + //Right channel + for (j=0;j<Pstages*2;j++){//Phasing routine + tmp=oldr[j]; + oldr[j]=gr*tmp+inr; + inr=tmp-gr*oldr[j]; + }; + //Left/Right crossing + REALTYPE l=inl; + REALTYPE r=inr; + inl=l*(1.0-lrcross)+r*lrcross; + inr=r*(1.0-lrcross)+l*lrcross; + + fbl=inl*fb; + fbr=inr*fb; + efxoutl[i]=inl; + efxoutr[i]=inr; + + }; + + oldlgain=lgain; oldrgain=rgain; + + if (Poutsub!=0) + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + efxoutl[i]*= -1.0; + efxoutr[i]*= -1.0; + }; + +}; + +/* + * Cleanup the effect + */ +void Phaser::cleanup(){ + fbl=0.0;fbr=0.0; + oldlgain=0.0; + oldrgain=0.0; + for (int i=0;i<Pstages*2;i++) { + oldl[i]=0.0; + oldr[i]=0.0; + }; +}; + +/* + * Parameter control + */ +void Phaser::setdepth(const unsigned char &Pdepth){ + this->Pdepth=Pdepth; + depth=(Pdepth/127.0); +}; + + +void Phaser::setfb(const unsigned char &Pfb){ + this->Pfb=Pfb; + fb=(Pfb-64.0)/64.1; +}; + +void Phaser::setvolume(const unsigned char &Pvolume){ + this->Pvolume=Pvolume; + outvolume=Pvolume/127.0; + if (insertion==0) volume=1.0; + else volume=outvolume; +}; + +void Phaser::setpanning(const unsigned char &Ppanning){ + this->Ppanning=Ppanning; + panning=Ppanning/127.0; +}; + +void Phaser::setlrcross(const unsigned char &Plrcross){ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0; +}; + +void Phaser::setstages(const unsigned char &Pstages){ + if (oldl!=NULL) delete [] oldl; + if (oldr!=NULL) delete [] oldr; + if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1; + else this->Pstages=Pstages; + oldl=new REALTYPE[Pstages*2]; + oldr=new REALTYPE[Pstages*2]; + cleanup(); +}; + +void Phaser::setphase(const unsigned char &Pphase){ + this->Pphase=Pphase; + phase=(Pphase/127.0); +}; + + +void Phaser::setpreset(unsigned char npreset){ + const int PRESET_SIZE=12; + const int NUM_PRESETS=6; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Phaser1 + {64,64,36,0,0,64,110,64,1,0,0,20}, + //Phaser2 + {64,64,35,0,0,88,40,64,3,0,0,20}, + //Phaser3 + {64,64,31,0,0,66,68,107,2,0,0,20}, + //Phaser4 + {39,64,22,0,0,66,67,10,5,0,1,20}, + //Phaser5 + {64,64,20,0,1,110,67,78,10,0,0,20}, + //Phaser6 + {64,64,53,100,0,58,37,78,3,0,0,20}}; + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); + Ppreset=npreset; +}; + + +void Phaser::changepar(const int &npar,const unsigned char &value){ + switch(npar){ + case 0: setvolume(value); + break; + case 1: setpanning(value); + break; + case 2: lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: setdepth(value); + break; + case 7: setfb(value); + break; + case 8: setstages(value); + break; + case 9: setlrcross(value); + break; + case 10:if (value>1) Poutsub=1; + else Poutsub=value; + break; + case 11:setphase(value); + break; + }; +}; + +unsigned char Phaser::getpar(const int &npar)const{ + switch (npar){ + case 0: return(Pvolume); + break; + case 1: return(Ppanning); + break; + case 2: return(lfo.Pfreq); + break; + case 3: return(lfo.Prandomness); + break; + case 4: return(lfo.PLFOtype); + break; + case 5: return(lfo.Pstereo); + break; + case 6: return(Pdepth); + break; + case 7: return(Pfb); + break; + case 8: return(Pstages); + break; + case 9: return(Plrcross); + break; + case 10:return(Poutsub); + break; + case 11:return(Pphase); + break; + default:return (0); + }; + +}; + diff --git a/src/Effects/Phaser.h b/src/Effects/Phaser.h @@ -1,70 +1,71 @@ -/* - ZynAddSubFX - a software synthesizer - - Phaser.h - Phaser 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 or later) 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 - -*/ - -#ifndef PHASER_H -#define PHASER_H -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" - -#define MAX_PHASER_STAGES 12 -class Phaser:public Effect { - public: - Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Phaser(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - void setdryonly(); - - private: - //Parametrii Phaser - EffectLFO lfo;/**<lfo-ul Phaser*/ - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;/**<the depth of the Phaser*/ - unsigned char Pfb;/**<feedback*/ - unsigned char Plrcross;/**<feedback*/ - unsigned char Pstages; - unsigned char Poutsub;/**<if I wish to substract the output instead of the adding it*/ - unsigned char Pphase; - - //Control Parametrii - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setfb(const unsigned char &Pfb); - void setlrcross(const unsigned char &Plrcross); - void setstages(const unsigned char &Pstages); - void setphase(const unsigned char &Pphase); - - //Internal Values - //int insertion; //inherited from Effect - REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase; - REALTYPE *oldl,*oldr; - REALTYPE oldlgain,oldrgain; -}; - -#endif - +/* + ZynAddSubFX - a software synthesizer + + Phaser.h - Phaser 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 or later) 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 + +*/ + +#ifndef PHASER_H +#define PHASER_H +#include "../globals.h" +#include "Effect.h" +#include "EffectLFO.h" + +#define MAX_PHASER_STAGES 12 +/**Phaser Effect*/ +class Phaser:public Effect { + public: + Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~Phaser(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + void setdryonly(); + + private: + //Parametrii Phaser + EffectLFO lfo;/**<lfo-ul Phaser*/ + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;/**<the depth of the Phaser*/ + unsigned char Pfb;/**<feedback*/ + unsigned char Plrcross;/**<feedback*/ + unsigned char Pstages; + unsigned char Poutsub;/**<if I wish to substract the output instead of the adding it*/ + unsigned char Pphase; + + //Control Parametrii + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); + void setstages(const unsigned char &Pstages); + void setphase(const unsigned char &Pphase); + + //Internal Values + //int insertion; //inherited from Effect + REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase; + REALTYPE *oldl,*oldr; + REALTYPE oldlgain,oldrgain; +}; + +#endif + diff --git a/src/Effects/Reverb.C b/src/Effects/Reverb.C @@ -1,435 +1,430 @@ -/* - ZynAddSubFX - a software synthesizer - - Reverb.C - Reverberation 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 or later) 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 <math.h> -#include <stdlib.h> -#include "Reverb.h" - -/**\todo: EarlyReflections,Prdelay,Perbalance */ - -Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) -{ - inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; - - //defaults - Pvolume=48; - Ppan=64; - Ptime=64; - Pidelay=40; - Pidelayfb=0; - Prdelay=0; - Plpf=127; - Phpf=0; - Perbalance=64; - Plohidamp=80; - Ptype=1; - Proomsize=64;roomsize=1.0;rs=1.0; - - for (int i=0;i<REV_COMBS*2;i++) { - comblen[i]=800+(int)(RND*1400); - combk[i]=0; - lpcomb[i]=0; - combfb[i]=-0.97; - comb[i]=NULL; - }; - - for (int i=0;i<REV_APS*2;i++) { - aplen[i]=500+(int)(RND*500); - apk[i]=0; - ap[i]=NULL; - }; - - lpf=NULL;hpf=NULL;//no filter - idelay=NULL; - - setpreset(Ppreset); - cleanup();//do not call this before the comb initialisation -}; - - -Reverb::~Reverb(){ - int i; - if (idelay!=NULL) delete []idelay; - if (hpf!=NULL) delete hpf; - if (lpf!=NULL) delete lpf; - - for (i=0;i<REV_APS*2;i++) delete [] ap[i]; - for (i=0;i<REV_COMBS*2;i++) delete [] comb[i]; - - delete [] inputbuf; -}; - -/* - * Cleanup the effect - */ -void Reverb::cleanup(){ - int i,j; - for (i=0;i<REV_COMBS*2;i++){ - lpcomb[i]=0.0; - for (j=0;j<comblen[i];j++) comb[i][j]=0.0; - }; - - for (i=0;i<REV_APS*2;i++) - for (j=0;j<aplen[i];j++) ap[i][j]=0.0; - - if (idelay!=NULL) for (i=0;i<idelaylen;i++) idelay[i]=0.0; - - if (hpf!=NULL) hpf->cleanup(); - if (lpf!=NULL) lpf->cleanup(); - -}; - -/* - * Process one channel; 0=left,1=right - */ -void Reverb::processmono(int ch,REALTYPE *output){ - int i,j; - REALTYPE fbout,tmp; - /**\todo: implement the high part from lohidamp*/ - - for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++){ - - int ck=combk[j]; - int comblength=comblen[j]; - REALTYPE lpcombj=lpcomb[j]; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - fbout=comb[j][ck]*combfb[j]; - fbout=fbout*(1.0-lohifb)+lpcombj*lohifb; - lpcombj=fbout; - - comb[j][ck]=inputbuf[i]+fbout; - output[i]+=fbout; - - if ((++ck)>=comblength) ck=0; - }; - - combk[j]=ck; - lpcomb[j]=lpcombj; - }; - - for (j=REV_APS*ch;j<REV_APS*(1+ch);j++){ - int ak=apk[j]; - int aplength=aplen[j]; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - tmp=ap[j][ak]; - ap[j][ak]=0.7*tmp+output[i]; - output[i]=tmp-0.7*ap[j][ak]; - if ((++ak)>=aplength) ak=0; - }; - apk[j]=ak; - }; -}; - -/* - * Effect output - */ -void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ - int i; - if ((Pvolume==0)&&(insertion!=0)) return; - - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - inputbuf[i]=(smps_l[i]+smps_r[i])/2.0; - //Initial delay r - if (idelay!=NULL){ - REALTYPE tmp=inputbuf[i]+idelay[idelayk]*idelayfb; - inputbuf[i]=idelay[idelayk]; - idelay[idelayk]=tmp; - idelayk++;if (idelayk>=idelaylen) idelayk=0; - }; - }; - - if (lpf!=NULL) lpf->filterout(inputbuf); - if (hpf!=NULL) hpf->filterout(inputbuf); - - processmono(0,efxoutl);//left - processmono(1,efxoutr);//right - - REALTYPE lvol=rs/REV_COMBS*pan; - REALTYPE rvol=rs/REV_COMBS*(1.0-pan); - if (insertion!=0){ - lvol*=2;rvol*=2; - }; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]*=lvol; - efxoutr[i]*=rvol; - }; -}; - - -/* - * Parameter control - */ -void Reverb::setvolume(const 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 Reverb::setpan(const unsigned char &Ppan){ - this->Ppan=Ppan; - pan=(REALTYPE)Ppan/127.0; -}; - -void Reverb::settime(const unsigned char &Ptime){ - int i; - REALTYPE t; - this->Ptime=Ptime; - t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; - - for (i=0;i<REV_COMBS*2;i++){ - combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t); - //the feedback is negative because it removes the DC - }; -}; - -void Reverb::setlohidamp(unsigned char Plohidamp){ - REALTYPE x; - - if (Plohidamp<64) Plohidamp=64;//remove this when the high part from lohidamp will be added - - this->Plohidamp=Plohidamp; - if (Plohidamp==64) { - lohidamptype=0; - lohifb=0.0; - } else { - if (Plohidamp<64) lohidamptype=1; - if (Plohidamp>64) lohidamptype=2; - x=fabs((REALTYPE)(Plohidamp-64)/64.1); - lohifb=x*x; - }; -}; - -void Reverb::setidelay(const unsigned char &Pidelay){ - REALTYPE delay; - this->Pidelay=Pidelay; - delay=pow(50*Pidelay/127.0,2)-1.0; - - if (idelay!=NULL) delete []idelay; - idelay=NULL; - - idelaylen=(int) (SAMPLE_RATE*delay/1000); - if (idelaylen>1) { - idelayk=0; - idelay=new REALTYPE[idelaylen]; - for (int i=0;i<idelaylen;i++) idelay[i]=0.0; - }; -}; - -void Reverb::setidelayfb(const unsigned char &Pidelayfb){ - this->Pidelayfb=Pidelayfb; - idelayfb=Pidelayfb/128.0; -}; - -void Reverb::sethpf(const unsigned char &Phpf){ - this->Phpf=Phpf; - if (Phpf==0) {//No HighPass - if (hpf!=NULL) delete(hpf); - hpf=NULL; - } - else{ - REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0; - if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); - else hpf->setfreq(fr); - }; -}; - -void Reverb::setlpf(const unsigned char &Plpf){ - this->Plpf=Plpf; - if (Plpf==127) {//No LowPass - if (lpf!=NULL) delete(lpf); - lpf=NULL; - } - else{ - REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; - if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); - else lpf->setfreq(fr); - }; -}; - -void Reverb::settype(unsigned char Ptype){ - const int NUM_TYPES=2; - int combtunings[NUM_TYPES][REV_COMBS]={ - //this is unused (for random) - {0,0,0,0,0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {1116,1188,1277,1356,1422,1491,1557,1617} - }; - int aptunings[NUM_TYPES][REV_APS]={ - //this is unused (for random) - {0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {225,341,441,556} - }; - - if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1; - this->Ptype=Ptype; - - REALTYPE tmp; - for (int i=0;i<REV_COMBS*2;i++) { - if (Ptype==0) tmp=800.0+(int)(RND*1400.0); - else tmp=combtunings[Ptype][i%REV_COMBS]; - tmp*=roomsize; - if (i>REV_COMBS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - - comblen[i]=(int) tmp; - combk[i]=0; - lpcomb[i]=0; - if (comb[i]!=NULL) delete []comb[i]; - comb[i]=new REALTYPE[comblen[i]]; - }; - - for (int i=0;i<REV_APS*2;i++) { - if (Ptype==0) tmp=500+(int)(RND*500); - else tmp=aptunings[Ptype][i%REV_APS]; - tmp*=roomsize; - if (i>REV_APS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - aplen[i]=(int) tmp; - apk[i]=0; - if (ap[i]!=NULL) delete []ap[i]; - ap[i]=new REALTYPE[aplen[i]]; - }; - settime(Ptime); - cleanup(); -}; - -void Reverb::setroomsize(const unsigned char &Proomsize){ - this->Proomsize=Proomsize; - if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0 - roomsize=(this->Proomsize-64.0)/64.0; - if (roomsize>0.0) roomsize*=2.0; - roomsize=pow(10.0,roomsize); - rs=sqrt(roomsize); - settype(Ptype); -}; - -void Reverb::setpreset(unsigned char npreset){ - const int PRESET_SIZE=12; - const int NUM_PRESETS=13; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Cathedral1 - {80,64,63,24,0,0,0,85,5,83,1,64}, - //Cathedral2 - {80,64,69,35,0,0,0,127,0,71,0,64}, - //Cathedral3 - {80,64,69,24,0,0,0,127,75,78,1,85}, - //Hall1 - {90,64,51,10,0,0,0,127,21,78,1,64}, - //Hall2 - {90,64,53,20,0,0,0,127,75,71,1,64}, - //Room1 - {100,64,33,0,0,0,0,127,0,106,0,30}, - //Room2 - {100,64,21,26,0,0,0,62,0,77,1,45}, - //Basement - {110,64,14,0,0,0,0,127,5,71,0,25}, - //Tunnel - {85,80,84,20,42,0,0,51,0,78,1,105}, - //Echoed1 - {95,64,26,60,71,0,0,114,0,64,1,64}, - //Echoed2 - {90,64,40,88,71,0,0,114,0,88,1,64}, - //VeryLong1 - {90,64,93,15,0,0,0,114,0,77,0,95}, - //VeryLong2 - {90,64,111,30,0,0,0,114,90,74,1,80}}; - - 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,presets[npreset][0]/2);//lower the volume if reverb is insertion effect - Ppreset=npreset; -}; - - -void Reverb::changepar(const int &npar,const unsigned char &value){ - switch (npar){ - case 0: setvolume(value); - break; - case 1: setpan(value); - break; - case 2: settime(value); - break; - case 3: setidelay(value); - break; - case 4: setidelayfb(value); - break; -// case 5: setrdelay(value); -// break; -// case 6: seterbalance(value); -// break; - case 7: setlpf(value); - break; - case 8: sethpf(value); - break; - case 9: setlohidamp(value); - break; - case 10:settype(value); - break; - case 11:setroomsize(value); - break; - }; -}; - -unsigned char Reverb::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppan); - break; - case 2: return(Ptime); - break; - case 3: return(Pidelay); - break; - case 4: return(Pidelayfb); - break; -// case 5: return(Prdelay); -// break; -// case 6: return(Perbalance); -// break; - case 7: return(Plpf); - break; - case 8: return(Phpf); - break; - case 9: return(Plohidamp); - break; - case 10:return(Ptype); - break; - case 11:return(Proomsize); - break; - }; - return(0);//in case of bogus "parameter" -}; - - - +/* + ZynAddSubFX - a software synthesizer + + Reverb.C - Reverberation 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 or later) 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 <cmath> +#include "Reverb.h" + +/**\todo: EarlyReflections,Prdelay,Perbalance */ + +Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) +{ + inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; + + //defaults + Pvolume=48; + Ppan=64; + Ptime=64; + Pidelay=40; + Pidelayfb=0; + Prdelay=0; + Plpf=127; + Phpf=0; + Perbalance=64; + Plohidamp=80; + Ptype=1; + Proomsize=64;roomsize=1.0;rs=1.0; + + for (int i=0;i<REV_COMBS*2;i++) { + comblen[i]=800+(int)(RND*1400); + combk[i]=0; + lpcomb[i]=0; + combfb[i]=-0.97; + comb[i]=NULL; + }; + + for (int i=0;i<REV_APS*2;i++) { + aplen[i]=500+(int)(RND*500); + apk[i]=0; + ap[i]=NULL; + }; + + lpf=NULL;hpf=NULL;//no filter + idelay=NULL; + + setpreset(Ppreset); + cleanup();//do not call this before the comb initialisation +}; + + +Reverb::~Reverb(){ + int i; + if (idelay!=NULL) delete []idelay; + if (hpf!=NULL) delete hpf; + if (lpf!=NULL) delete lpf; + + for (i=0;i<REV_APS*2;i++) delete [] ap[i]; + for (i=0;i<REV_COMBS*2;i++) delete [] comb[i]; + + delete [] inputbuf; +}; + +/* + * Cleanup the effect + */ +void Reverb::cleanup(){ + int i,j; + for (i=0;i<REV_COMBS*2;i++){ + lpcomb[i]=0.0; + for (j=0;j<comblen[i];j++) comb[i][j]=0.0; + }; + + for (i=0;i<REV_APS*2;i++) + for (j=0;j<aplen[i];j++) ap[i][j]=0.0; + + if (idelay!=NULL) for (i=0;i<idelaylen;i++) idelay[i]=0.0; + + if (hpf!=NULL) hpf->cleanup(); + if (lpf!=NULL) lpf->cleanup(); + +}; + +/* + * Process one channel; 0=left,1=right + */ +void Reverb::processmono(int ch,REALTYPE *output){ + int i,j; + REALTYPE fbout,tmp; + /**\todo: implement the high part from lohidamp*/ + + for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++){ + + int ck=combk[j]; + int comblength=comblen[j]; + REALTYPE lpcombj=lpcomb[j]; + + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + fbout=comb[j][ck]*combfb[j]; + fbout=fbout*(1.0-lohifb)+lpcombj*lohifb; + lpcombj=fbout; + + comb[j][ck]=inputbuf[i]+fbout; + output[i]+=fbout; + + if ((++ck)>=comblength) ck=0; + }; + + combk[j]=ck; + lpcomb[j]=lpcombj; + }; + + for (j=REV_APS*ch;j<REV_APS*(1+ch);j++){ + int ak=apk[j]; + int aplength=aplen[j]; + for (i=0;i<SOUND_BUFFER_SIZE;i++){ + tmp=ap[j][ak]; + ap[j][ak]=0.7*tmp+output[i]; + output[i]=tmp-0.7*ap[j][ak]; + if ((++ak)>=aplength) ak=0; + }; + apk[j]=ak; + }; +}; + +/* + * Effect output + */ +void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ + int i; + if ((Pvolume==0)&&(insertion!=0)) return; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + inputbuf[i]=(smps_l[i]+smps_r[i])/2.0; + //Initial delay r + if (idelay!=NULL){ + REALTYPE tmp=inputbuf[i]+idelay[idelayk]*idelayfb; + inputbuf[i]=idelay[idelayk]; + idelay[idelayk]=tmp; + idelayk++;if (idelayk>=idelaylen) idelayk=0; + }; + }; + + if (lpf!=NULL) lpf->filterout(inputbuf); + if (hpf!=NULL) hpf->filterout(inputbuf); + + processmono(0,efxoutl);//left + processmono(1,efxoutr);//right + + REALTYPE lvol=rs/REV_COMBS*pan; + REALTYPE rvol=rs/REV_COMBS*(1.0-pan); + if (insertion!=0){ + lvol*=2;rvol*=2; + }; + for (int i=0;i<SOUND_BUFFER_SIZE;i++){ + efxoutl[i]*=lvol; + efxoutr[i]*=rvol; + }; +}; + + +/* + * Parameter control + */ +void Reverb::setvolume(const 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 Reverb::setpan(const unsigned char &Ppan){ + this->Ppan=Ppan; + pan=(REALTYPE)Ppan/127.0; +}; + +void Reverb::settime(const unsigned char &Ptime){ + int i; + REALTYPE t; + this->Ptime=Ptime; + t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; + + for (i=0;i<REV_COMBS*2;i++){ + combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t); + //the feedback is negative because it removes the DC + }; +}; + +void Reverb::setlohidamp(unsigned char Plohidamp){ + REALTYPE x; + + if (Plohidamp<64) Plohidamp=64;//remove this when the high part from lohidamp will be added + + this->Plohidamp=Plohidamp; + if (Plohidamp==64) { + lohidamptype=0; + lohifb=0.0; + } else { + if (Plohidamp<64) lohidamptype=1; + if (Plohidamp>64) lohidamptype=2; + x=fabs((REALTYPE)(Plohidamp-64)/64.1); + lohifb=x*x; + }; +}; + +void Reverb::setidelay(const unsigned char &Pidelay){ + REALTYPE delay; + this->Pidelay=Pidelay; + delay=pow(50*Pidelay/127.0,2)-1.0; + + if (idelay!=NULL) delete []idelay; + idelay=NULL; + + idelaylen=(int) (SAMPLE_RATE*delay/1000); + if (idelaylen>1) { + idelayk=0; + idelay=new REALTYPE[idelaylen]; + for (int i=0;i<idelaylen;i++) idelay[i]=0.0; + }; +}; + +void Reverb::setidelayfb(const unsigned char &Pidelayfb){ + this->Pidelayfb=Pidelayfb; + idelayfb=Pidelayfb/128.0; +}; + +void Reverb::sethpf(const unsigned char &Phpf){ + this->Phpf=Phpf; + if (Phpf==0) {//No HighPass + if (hpf!=NULL) delete hpf; + hpf=NULL; + } + else{ + REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0; + if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); + else hpf->setfreq(fr); + }; +}; + +void Reverb::setlpf(const unsigned char &Plpf){ + this->Plpf=Plpf; + if (Plpf==127) {//No LowPass + if (lpf!=NULL) delete lpf; + lpf=NULL; + } + else{ + REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; + if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); + else lpf->setfreq(fr); + }; +}; + +void Reverb::settype(unsigned char Ptype){ + const int NUM_TYPES=2; + int combtunings[NUM_TYPES][REV_COMBS]={ + //this is unused (for random) + {0,0,0,0,0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {1116,1188,1277,1356,1422,1491,1557,1617} + }; + int aptunings[NUM_TYPES][REV_APS]={ + //this is unused (for random) + {0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {225,341,441,556} + }; + + if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1; + this->Ptype=Ptype; + + REALTYPE tmp; + for (int i=0;i<REV_COMBS*2;i++) { + if (Ptype==0) tmp=800.0+(int)(RND*1400.0); + else tmp=combtunings[Ptype][i%REV_COMBS]; + tmp*=roomsize; + if (i>REV_COMBS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + + comblen[i]=(int) tmp; + combk[i]=0; + lpcomb[i]=0; + if (comb[i]!=NULL) delete []comb[i]; + comb[i]=new REALTYPE[comblen[i]]; + }; + + for (int i=0;i<REV_APS*2;i++) { + if (Ptype==0) tmp=500+(int)(RND*500); + else tmp=aptunings[Ptype][i%REV_APS]; + tmp*=roomsize; + if (i>REV_APS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + aplen[i]=(int) tmp; + apk[i]=0; + if (ap[i]!=NULL) delete []ap[i]; + ap[i]=new REALTYPE[aplen[i]]; + }; + settime(Ptime); + cleanup(); +}; + +void Reverb::setroomsize(const unsigned char &Proomsize){ + this->Proomsize=Proomsize; + if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0 + roomsize=(this->Proomsize-64.0)/64.0; + if (roomsize>0.0) roomsize*=2.0; + roomsize=pow(10.0,roomsize); + rs=sqrt(roomsize); + settype(Ptype); +}; + +void Reverb::setpreset(unsigned char npreset){ + const int PRESET_SIZE=12; + const int NUM_PRESETS=13; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Cathedral1 + {80,64,63,24,0,0,0,85,5,83,1,64}, + //Cathedral2 + {80,64,69,35,0,0,0,127,0,71,0,64}, + //Cathedral3 + {80,64,69,24,0,0,0,127,75,78,1,85}, + //Hall1 + {90,64,51,10,0,0,0,127,21,78,1,64}, + //Hall2 + {90,64,53,20,0,0,0,127,75,71,1,64}, + //Room1 + {100,64,33,0,0,0,0,127,0,106,0,30}, + //Room2 + {100,64,21,26,0,0,0,62,0,77,1,45}, + //Basement + {110,64,14,0,0,0,0,127,5,71,0,25}, + //Tunnel + {85,80,84,20,42,0,0,51,0,78,1,105}, + //Echoed1 + {95,64,26,60,71,0,0,114,0,64,1,64}, + //Echoed2 + {90,64,40,88,71,0,0,114,0,88,1,64}, + //VeryLong1 + {90,64,93,15,0,0,0,114,0,77,0,95}, + //VeryLong2 + {90,64,111,30,0,0,0,114,90,74,1,80}}; + + 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,presets[npreset][0]/2);//lower the volume if reverb is insertion effect + Ppreset=npreset; +}; + + +void Reverb::changepar(const int &npar,const unsigned char &value){ + switch (npar){ + case 0: setvolume(value); + break; + case 1: setpan(value); + break; + case 2: settime(value); + break; + case 3: setidelay(value); + break; + case 4: setidelayfb(value); + break; +// case 5: setrdelay(value); +// break; +// case 6: seterbalance(value); +// break; + case 7: setlpf(value); + break; + case 8: sethpf(value); + break; + case 9: setlohidamp(value); + break; + case 10:settype(value); + break; + case 11:setroomsize(value); + break; + }; +}; + +unsigned char Reverb::getpar(const int &npar)const{ + switch (npar){ + case 0: return(Pvolume); + break; + case 1: return(Ppan); + break; + case 2: return(Ptime); + break; + case 3: return(Pidelay); + break; + case 4: return(Pidelayfb); + break; +// case 5: return(Prdelay); +// break; +// case 6: return(Perbalance); +// break; + case 7: return(Plpf); + break; + case 8: return(Phpf); + break; + case 9: return(Plohidamp); + break; + case 10:return(Ptype); + break; + case 11:return(Proomsize); + break; + }; + return(0);//in case of bogus "parameter" +}; + diff --git a/src/Effects/Reverb.h b/src/Effects/Reverb.h @@ -1,126 +1,126 @@ -/* - ZynAddSubFX - a software synthesizer - - Reverb.h - Reverberation 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 or later) 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 - -*/ - -#ifndef REVERB_H -#define REVERB_H - - -#include "../globals.h" -#include "../DSP/AnalogFilter.h" -#include "Effect.h" - -#define REV_COMBS 8 -#define REV_APS 4 - -/**Creates Reverberation Effects*/ -class Reverb:public Effect { - public: - Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Reverb(); - void out(REALTYPE *smps_l,REALTYPE *smps_r); - void cleanup(); - - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - - private: - //Parametrii - /**Amount of the reverb*/ - unsigned char Pvolume; - - /**Left/Right Panning*/ - unsigned char Ppan; - - /**duration of reverb*/ - unsigned char Ptime; - - /**Initial delay*/ - unsigned char Pidelay; - - /**Initial delay feedback*/ - unsigned char Pidelayfb; - - /**delay between ER/Reverbs*/ - unsigned char Prdelay; - - /**EarlyReflections/Reverb Balance*/ - unsigned char Perbalance; - - /**HighPassFilter*/ - unsigned char Plpf; - - /**LowPassFilter*/ - unsigned char Phpf; - - /**Low/HighFrequency Damping - * \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/ - unsigned char Plohidamp; - - /**Reverb type*/ - unsigned char Ptype; - - /**Room Size*/ - unsigned char Proomsize; - - //parameter control - void setvolume(const unsigned char &Pvolume); - void setpan(const unsigned char &Ppan); - void settime(const unsigned char &Ptime); - void setlohidamp(unsigned char Plohidamp); - void setidelay(const unsigned char &Pidelay); - void setidelayfb(const unsigned char &Pidelayfb); - void sethpf(const unsigned char &Phpf); - void setlpf(const unsigned char &Plpf); - void settype( unsigned char Ptype); - void setroomsize(const unsigned char &Proomsize); - - REALTYPE pan,erbalance; - //Parametrii 2 - int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/ - int idelaylen,rdelaylen; - int idelayk; - REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize - int comblen[REV_COMBS*2]; - int aplen[REV_APS*2]; - - //Internal Variables - - REALTYPE *comb[REV_COMBS*2]; - - int combk[REV_COMBS*2]; - REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/ - REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/ - - REALTYPE *ap[REV_APS*2]; - - int apk[REV_APS*2]; - - REALTYPE *idelay; - AnalogFilter *lpf,*hpf;//filters - REALTYPE *inputbuf; - - void processmono(int ch,REALTYPE *output); -}; - -#endif - +/* + ZynAddSubFX - a software synthesizer + + Reverb.h - Reverberation 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 or later) 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 + +*/ + +#ifndef REVERB_H +#define REVERB_H + + +#include "../globals.h" +#include "../DSP/AnalogFilter.h" +#include "Effect.h" + +#define REV_COMBS 8 +#define REV_APS 4 + +/**Creates Reverberation Effects*/ +class Reverb:public Effect { + public: + Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~Reverb(); + void out(REALTYPE *smps_l,REALTYPE *smps_r); + void cleanup(); + + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + + private: + //Parametrii + /**Amount of the reverb*/ + unsigned char Pvolume; + + /**Left/Right Panning*/ + unsigned char Ppan; + + /**duration of reverb*/ + unsigned char Ptime; + + /**Initial delay*/ + unsigned char Pidelay; + + /**Initial delay feedback*/ + unsigned char Pidelayfb; + + /**delay between ER/Reverbs*/ + unsigned char Prdelay; + + /**EarlyReflections/Reverb Balance*/ + unsigned char Perbalance; + + /**HighPassFilter*/ + unsigned char Plpf; + + /**LowPassFilter*/ + unsigned char Phpf; + + /**Low/HighFrequency Damping + * \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/ + unsigned char Plohidamp; + + /**Reverb type*/ + unsigned char Ptype; + + /**Room Size*/ + unsigned char Proomsize; + + //parameter control + void setvolume(const unsigned char &Pvolume); + void setpan(const unsigned char &Ppan); + void settime(const unsigned char &Ptime); + void setlohidamp(unsigned char Plohidamp); + void setidelay(const unsigned char &Pidelay); + void setidelayfb(const unsigned char &Pidelayfb); + void sethpf(const unsigned char &Phpf); + void setlpf(const unsigned char &Plpf); + void settype( unsigned char Ptype); + void setroomsize(const unsigned char &Proomsize); + + REALTYPE pan,erbalance; + //Parametrii 2 + int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/ + int idelaylen,rdelaylen; + int idelayk; + REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize + int comblen[REV_COMBS*2]; + int aplen[REV_APS*2]; + + //Internal Variables + + REALTYPE *comb[REV_COMBS*2]; + + int combk[REV_COMBS*2]; + REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/ + REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/ + + REALTYPE *ap[REV_APS*2]; + + int apk[REV_APS*2]; + + REALTYPE *idelay; + AnalogFilter *lpf,*hpf;//filters + REALTYPE *inputbuf; + + void processmono(int ch,REALTYPE *output); +}; + +#endif +