summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2009-12-27 11:30:35 +0000
committerRobert Jonsson <spamatica@gmail.com>2009-12-27 11:30:35 +0000
commitb703eab295330e6f81564fbb39a10a1a2fdd2f54 (patch)
treee46b5c9a6bc22fd661c15d1d2123f5bf631cef80 /muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C
parent5d5fa0fdf913907edbc3d2d29a7548f0cb658c94 (diff)
moved old qt4 branch
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C')
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C438
1 files changed, 438 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C b/muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C
new file mode 100644
index 00000000..b39e41c9
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Effects/Reverb.C
@@ -0,0 +1,438 @@
+/*
+ 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 <stdio.h>
+
+#include <math.h>
+#include <stdlib.h>
+#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;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(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(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;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(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(unsigned char Pidelayfb){
+ this->Pidelayfb=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;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(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<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(int npar,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(int npar){
+ 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"
+};
+
+
+