summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C')
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C277
1 files changed, 277 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C b/muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C
new file mode 100644
index 00000000..fb40c93b
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Effects/Chorus.C
@@ -0,0 +1,277 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Chorus.C - Chorus and Flange 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 <math.h>
+#include "Chorus.h"
+#include <stdio.h>
+
+Chorus::Chorus(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_){
+ efxoutl=efxoutl_;
+ efxoutr=efxoutr_;
+ dlk=0;drk=0;
+ maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
+ delayl=new REALTYPE[maxdelay];
+ delayr=new REALTYPE[maxdelay];
+ insertion=insertion_;
+
+ filterpars=NULL;
+ Ppreset=0;
+ setpreset(Ppreset);
+
+ lfo.effectlfoout(&lfol,&lfor);
+ dl2=getdelay(lfol);
+ dr2=getdelay(lfor);
+ cleanup();
+};
+
+Chorus::~Chorus(){
+ delete [] delayl;
+ delete [] delayr;
+};
+
+/*
+ * get the delay value in samples; xlfo is the current lfo value
+ */
+REALTYPE Chorus::getdelay(REALTYPE xlfo){
+ REALTYPE result;
+ if (Pflangemode==0){
+ result=(delay+xlfo*depth)*SAMPLE_RATE;
+ } else result=0;
+
+ //check if it is too big delay(caused bu errornous setdelay() and setdepth()
+ if ((result+0.5)>=maxdelay) {
+ fprintf(stderr,"%s","WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n");
+ result=maxdelay-1.0;
+ };
+ return(result);
+};
+
+/*
+ * Apply the effect
+ */
+void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){
+ int i;
+ dl1=dl2;dr1=dr2;
+ lfo.effectlfoout(&lfol,&lfor);
+
+ dl2=getdelay(lfol);
+ dr2=getdelay(lfor);
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE inl=smpsl[i];
+ REALTYPE inr=smpsr[i];
+ //LRcross
+ REALTYPE l=inl;
+ REALTYPE r=inr;
+ inl=l*(1.0-lrcross)+r*lrcross;
+ inr=r*(1.0-lrcross)+l*lrcross;
+
+ //Left channel
+
+ //compute the delay in samples using linear interpolation between the lfo delays
+ mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE;
+ if (++dlk>=maxdelay) dlk=0;
+ REALTYPE tmp=dlk-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);
+ efxoutl[i]=delayl[dlhi2]*dllo+delayl[dlhi]*(1.0-dllo);
+ delayl[dlk]=inl+efxoutl[i]*fb;
+
+ //Right channel
+
+ //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
+
+ F2I(tmp,dlhi);
+ dlhi%=maxdelay;
+
+ dlhi2=(dlhi-1+maxdelay)%maxdelay;
+ dllo=1.0-fmod(tmp,1.0);
+ efxoutr[i]=delayr[dlhi2]*dllo+delayr[dlhi]*(1.0-dllo);
+ delayr[dlk]=inr+efxoutr[i]*fb;
+
+ };
+
+ if (Poutsub!=0)
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ efxoutl[i] *= -1.0;
+ efxoutr[i] *= -1.0;
+ };
+
+
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ efxoutl[i]*=panning;
+ efxoutr[i]*=(1.0-panning);
+ };
+};
+
+/*
+ * Cleanup the effect
+ */
+void Chorus::cleanup(){
+ for (int i=0;i<maxdelay;i++){
+ delayl[i]=0.0;
+ delayr[i]=0.0;
+ };
+
+};
+
+/*
+ * Parameter control
+ */
+void Chorus::setdepth(unsigned char Pdepth){
+ this->Pdepth=Pdepth;
+ depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds
+};
+
+void Chorus::setdelay(unsigned char Pdelay){
+ this->Pdelay=Pdelay;
+ delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds
+};
+
+void Chorus::setfb(unsigned char Pfb){
+ this->Pfb=Pfb;
+ fb=(Pfb-64.0)/64.1;
+};
+void Chorus::setvolume(unsigned char Pvolume){
+ this->Pvolume=Pvolume;
+ outvolume=Pvolume/127.0;
+ if (insertion==0) volume=1.0;
+ else volume=outvolume;
+};
+
+void Chorus::setpanning(unsigned char Ppanning){
+ this->Ppanning=Ppanning;
+ panning=Ppanning/127.0;
+};
+
+void Chorus::setlrcross(unsigned char Plrcross){
+ this->Plrcross=Plrcross;
+ lrcross=Plrcross/127.0;
+};
+
+void Chorus::setpreset(unsigned char npreset){
+ const int PRESET_SIZE=12;
+ const int NUM_PRESETS=10;
+ unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
+ //Chorus1
+ {64,64,50,0,0,90,40,85,64,119,0,0},
+ //Chorus2
+ {64,64,45,0,0,98,56,90,64,19,0,0},
+ //Chorus3
+ {64,64,29,0,1,42,97,95,90,127,0,0},
+ //Celeste1
+ {64,64,26,0,0,42,115,18,90,127,0,0},
+ //Celeste2
+ {64,64,29,117,0,50,115,9,31,127,0,1},
+ //Flange1
+ {64,64,57,0,0,60,23,3,62,0,0,0},
+ //Flange2
+ {64,64,33,34,1,40,35,3,109,0,0,0},
+ //Flange3
+ {64,64,53,34,1,94,35,3,54,0,0,1},
+ //Flange4
+ {64,64,40,0,1,62,12,19,97,0,0,0},
+ //Flange5
+ {64,64,55,105,0,24,39,19,17,0,0,1}};
+
+ if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
+ for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
+ Ppreset=npreset;
+};
+
+
+void Chorus::changepar(int npar,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: setdelay(value);
+ break;
+ case 8: setfb(value);
+ break;
+ case 9: setlrcross(value);
+ break;
+ case 10:if (value>1) value=1;
+ Pflangemode=value;
+ break;
+ case 11:if (value>1) value=1;
+ Poutsub=value;
+ break;
+ };
+};
+
+unsigned char Chorus::getpar(int npar){
+ 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(Pdelay);
+ break;
+ case 8: return(Pfb);
+ break;
+ case 9: return(Plrcross);
+ break;
+ case 10:return(Pflangemode);
+ break;
+ case 11:return(Poutsub);
+ break;
+ default:return (0);
+ };
+
+};
+
+
+
+