/* 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) 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 "Reverb.h" /*TODO: EarlyReflections,Prdelay,Perbalance */ Reverb::Reverb(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_){ efxoutl=efxoutl_; efxoutr=efxoutr_; inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; filterpars=NULL; insertion=insertion_; //defaults Ppreset=0; 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;icleanup(); 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=comblength) ck=0; }; combk[j]=ck; lpcomb[j]=lpcombj; }; for (j=REV_APS*ch;j=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=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;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 Reverb::setpan(unsigned char Ppan){ this->Ppan=Ppan; pan=(REALTYPE)Ppan/127.0; }; void Reverb::settime(unsigned char Ptime){ int i; REALTYPE t; this->Ptime=Ptime; t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; for (i=0;iPlohidamp=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(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;iPidelayfb=Pidelayfb; idelayfb=Pidelayfb/128.0; }; void Reverb::sethpf(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(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;iREV_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;iREV_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(unsigned char Proomsize){ if (Proomsize==0) Proomsize=64;//this is because the older versions consider roomsize=0 this->Proomsize=Proomsize; roomsize=(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