/* ZynAddSubFX - a software synthesizer EffectMgr.C - Effect manager, an interface betwen the program and effects 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 <stdlib.h> #include <stdio.h> #include "EffectMgr.h" #include "../Misc/Master.h" EffectMgr::EffectMgr(int insertion_,Master* master_){ setpresettype("Peffect"); efx=NULL; nefx=0; insertion=insertion_; master=master_; 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; defaults(); }; EffectMgr::~EffectMgr(){ if (efx!=NULL) delete (efx); delete (efxoutl); delete (efxoutr); }; void EffectMgr::defaults(){ changeeffect(0); setdryonly(false); }; /* * Change the effect */ void EffectMgr::changeeffect(int nefx_){ cleanup(); if (nefx==nefx_) return; nefx=nefx_; for (int i=0;i<SOUND_BUFFER_SIZE;i++){ efxoutl[i]=0.0; efxoutr[i]=0.0; }; if (efx!=NULL) delete (efx); switch (nefx){ 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; case 4:efx=new Phaser(insertion,efxoutl,efxoutr);break; case 5:efx=new Alienwah(insertion,efxoutl,efxoutr);break; case 6:efx=new Distorsion(insertion,efxoutl,efxoutr);break; case 7:efx=new EQ(insertion,efxoutl,efxoutr);break; case 8:efx=new DynamicFilter(insertion,efxoutl,efxoutr);break; //put more effect here default:efx=NULL;break;//no effect (thru) }; if (efx!=NULL) filterpars=efx->filterpars; }; /* * Obtain the effect number */ int EffectMgr::geteffect(){ return (nefx); }; /* * Cleanup the current effect */ void EffectMgr::cleanup(){ if (efx!=NULL) efx->cleanup(); }; /* * Get the preset of the current effect */ unsigned char EffectMgr::getpreset(){ if (efx!=NULL) return(efx->Ppreset); else return(0); }; /* * Change the preset of the current effect */ void EffectMgr::changepreset_nolock(unsigned char npreset){ if (efx!=NULL) efx->setpreset(npreset); }; /* * Change the preset of the current effect(with thread locking) */ void EffectMgr::changepreset(unsigned char npreset){ master->lock(); changepreset_nolock(npreset); master->unlock(); }; /* * Change a parameter of the current effect */ void EffectMgr::seteffectpar_nolock(int npar,unsigned char value){ if (efx==NULL) return; efx->changepar(npar,value); }; /* * Change a parameter of the current effect (with thread locking) */ void EffectMgr::seteffectpar(int npar,unsigned char value){ master->lock(); seteffectpar_nolock(npar,value); master->unlock(); }; /* * Get a parameter of the current effect */ unsigned char EffectMgr::geteffectpar(int npar){ if (efx==NULL) return(0); return(efx->getpar(npar)); }; /* * Apply the effect */ void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr){ int i; if (efx==NULL){ if (insertion==0) for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]=0.0;smpsr[i]=0.0; efxoutl[i]=0.0;efxoutr[i]=0.0; }; return; }; for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]+=denormalkillbuf[i]; smpsr[i]+=denormalkillbuf[i]; efxoutl[i]=0.0; efxoutr[i]=0.0; }; efx->out(smpsl,smpsr); REALTYPE volume=efx->volume; if (nefx==7){//this is need only for the EQ effect for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]=efxoutl[i]; smpsr[i]=efxoutr[i]; }; return; }; //Insertion effect if (insertion!=0) { REALTYPE v1,v2; if (volume<0.5) { v1=1.0; v2=volume*2.0; } else { v1=(1.0-volume)*2.0; v2=1.0; }; if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar if (dryonly){//this is used for instrument effect only for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]*=v1; smpsr[i]*=v1; efxoutl[i]*=v2; efxoutr[i]*=v2; }; }else{//normal instrument/insertion effect for (i=0;i<SOUND_BUFFER_SIZE;i++){ smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2; smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2; }; }; } else {//System effect for (i=0;i<SOUND_BUFFER_SIZE;i++){ efxoutl[i]*=2.0*volume; efxoutr[i]*=2.0*volume; smpsl[i]=efxoutl[i]; smpsr[i]=efxoutr[i]; }; }; }; /* * Get the effect volume for the system effect */ REALTYPE EffectMgr::sysefxgetvolume(){ if (efx==NULL) return (1.0); else return(efx->outvolume); }; /* * Get the EQ response */ REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq){ if (nefx==7) return(efx->getfreqresponse(freq)); else return(0.0); }; void EffectMgr::setdryonly(bool value){ dryonly=value; }; void EffectMgr::add2XML(XMLwrapper *xml){ xml->addpar("type",geteffect()); if ((efx==NULL)||(geteffect()==0)) return; xml->addpar("preset",efx->Ppreset); xml->beginbranch("EFFECT_PARAMETERS"); for (int n=0;n<128;n++){ int par=geteffectpar(n); if (par==0) continue; xml->beginbranch("par_no",n); xml->addpar("par",par); xml->endbranch(); }; if (filterpars!=NULL){ xml->beginbranch("FILTER"); filterpars->add2XML(xml); xml->endbranch(); }; xml->endbranch(); }; void EffectMgr::getfromXML(XMLwrapper *xml){ changeeffect(xml->getpar127("type",geteffect())); if ((efx==NULL)||(geteffect()==0)) return; efx->Ppreset=xml->getpar127("preset",efx->Ppreset); if (xml->enterbranch("EFFECT_PARAMETERS")){ for (int n=0;n<128;n++){ seteffectpar_nolock(n,0);//erase effect parameter if (xml->enterbranch("par_no",n)==0) continue; int par=geteffectpar(n); seteffectpar_nolock(n,xml->getpar127("par",par)); xml->exitbranch(); }; if (filterpars!=NULL){ if (xml->enterbranch("FILTER")){ filterpars->getfromXML(xml); xml->exitbranch(); }; }; xml->exitbranch(); }; cleanup(); };