| 
							- /*
 -   ZynAddSubFX - a software synthesizer
 - 
 -   Echo.cpp - Echo effect
 -   Copyright (C) 2002-2005 Nasca Octavian Paul
 -   Copyright (C) 2009-2010 Mark McCurry
 -   Author: Nasca Octavian Paul
 -           Mark McCurry
 - 
 -   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 "Echo.h"
 - 
 - #define MAX_DELAY 2
 - 
 - Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_)
 -     :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
 -       Pvolume(50),
 -       Pdelay(60),
 -       Plrdelay(100),
 -       Pfb(40),
 -       Phidamp(60),
 -       delayTime(1),
 -       lrdelay(0),
 -       avgDelay(0),
 -       delay(new float[(int)(MAX_DELAY * synth->samplerate)],
 -             new float[(int)(MAX_DELAY * synth->samplerate)]),
 -       old(0.0f),
 -       pos(0),
 -       delta(1),
 -       ndelta(1)
 - {
 -     initdelays();
 -     setpreset(Ppreset);
 - }
 - 
 - Echo::~Echo()
 - {
 -     delete[] delay.l;
 -     delete[] delay.r;
 - }
 - 
 - //Cleanup the effect
 - void Echo::cleanup(void)
 - {
 -     memset(delay.l, 0, MAX_DELAY * synth->samplerate * sizeof(float));
 -     memset(delay.r, 0, MAX_DELAY * synth->samplerate * sizeof(float));
 -     old = Stereo<float>(0.0f);
 - }
 - 
 - inline int max(int a, int b)
 - {
 -     return a > b ? a : b;
 - }
 - 
 - //Initialize the delays
 - void Echo::initdelays(void)
 - {
 -     cleanup();
 -     //number of seconds to delay left chan
 -     float dl = avgDelay - lrdelay;
 - 
 -     //number of seconds to delay right chan
 -     float dr = avgDelay + lrdelay;
 - 
 -     ndelta.l = max(1, (int) (dl * synth->samplerate));
 -     ndelta.r = max(1, (int) (dr * synth->samplerate));
 - }
 - 
 - //Effect output
 - void Echo::out(const Stereo<float *> &input)
 - {
 -     for(int i = 0; i < synth->buffersize; ++i) {
 -         float ldl = delay.l[pos.l];
 -         float rdl = delay.r[pos.r];
 -         ldl = ldl * (1.0f - lrcross) + rdl * lrcross;
 -         rdl = rdl * (1.0f - lrcross) + ldl * lrcross;
 - 
 -         efxoutl[i] = ldl * 2.0f;
 -         efxoutr[i] = rdl * 2.0f;
 - 
 -         ldl = input.l[i] * pangainL - ldl * fb;
 -         rdl = input.r[i] * pangainR - rdl * fb;
 - 
 -         //LowPass Filter
 -         old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * synth->samplerate)] =
 -                     ldl * hidamp + old.l * (1.0f - hidamp);
 -         old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * synth->samplerate)] =
 -                     rdl * hidamp + old.r * (1.0f - hidamp);
 - 
 -         //increment
 -         ++pos.l; // += delta.l;
 -         ++pos.r; // += delta.r;
 - 
 -         //ensure that pos is still in bounds
 -         pos.l %= MAX_DELAY * synth->samplerate;
 -         pos.r %= MAX_DELAY * synth->samplerate;
 - 
 -         //adjust delay if needed
 -         delta.l = (15 * delta.l + ndelta.l) / 16;
 -         delta.r = (15 * delta.r + ndelta.r) / 16;
 -     }
 - }
 - 
 - 
 - //Parameter control
 - void Echo::setvolume(unsigned char _Pvolume)
 - {
 -     Pvolume = _Pvolume;
 - 
 -     if(insertion == 0) {
 -         outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
 -         volume    = 1.0f;
 -     }
 -     else
 -         volume = outvolume = Pvolume / 127.0f;
 -     if(Pvolume == 0)
 -         cleanup();
 - }
 - 
 - void Echo::setdelay(unsigned char _Pdelay)
 - {
 -     Pdelay   = _Pdelay;
 -     avgDelay = (Pdelay / 127.0f * 1.5f); //0 .. 1.5 sec
 -     initdelays();
 - }
 - 
 - void Echo::setlrdelay(unsigned char _Plrdelay)
 - {
 -     float tmp;
 -     Plrdelay = _Plrdelay;
 -     tmp      =
 -         (powf(2.0f, fabsf(Plrdelay - 64.0f) / 64.0f * 9.0f) - 1.0f) / 1000.0f;
 -     if(Plrdelay < 64.0f)
 -         tmp = -tmp;
 -     lrdelay = tmp;
 -     initdelays();
 - }
 - 
 - void Echo::setfb(unsigned char _Pfb)
 - {
 -     Pfb = _Pfb;
 -     fb  = Pfb / 128.0f;
 - }
 - 
 - void Echo::sethidamp(unsigned char _Phidamp)
 - {
 -     Phidamp = _Phidamp;
 -     hidamp  = 1.0f - Phidamp / 127.0f;
 - }
 - 
 - void Echo::setpreset(unsigned char npreset)
 - {
 -     const int     PRESET_SIZE = 7;
 -     const int     NUM_PRESETS = 9;
 -     unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
 -         {67, 64, 35,  64,  30,  59, 0 }, //Echo 1
 -         {67, 64, 21,  64,  30,  59, 0 }, //Echo 2
 -         {67, 75, 60,  64,  30,  59, 10}, //Echo 3
 -         {67, 60, 44,  64,  30,  0,  0 }, //Simple Echo
 -         {67, 60, 102, 50,  30,  82, 48}, //Canyon
 -         {67, 64, 44,  17,  0,   82, 24}, //Panning Echo 1
 -         {81, 60, 46,  118, 100, 68, 18}, //Panning Echo 2
 -         {81, 60, 26,  100, 127, 67, 36}, //Panning Echo 3
 -         {62, 64, 28,  64,  100, 90, 55}  //Feedback Echo
 -     };
 - 
 -     if(npreset >= NUM_PRESETS)
 -         npreset = NUM_PRESETS - 1;
 -     for(int n = 0; n < PRESET_SIZE; ++n)
 -         changepar(n, presets[npreset][n]);
 -     if(insertion)
 -         setvolume(presets[npreset][0] / 2);  //lower the volume if this is insertion effect
 -     Ppreset = npreset;
 - }
 - 
 - 
 - void Echo::changepar(int npar, unsigned char value)
 - {
 -     switch(npar) {
 -         case 0:
 -             setvolume(value);
 -             break;
 -         case 1:
 -             setpanning(value);
 -             break;
 -         case 2:
 -             setdelay(value);
 -             break;
 -         case 3:
 -             setlrdelay(value);
 -             break;
 -         case 4:
 -             setlrcross(value);
 -             break;
 -         case 5:
 -             setfb(value);
 -             break;
 -         case 6:
 -             sethidamp(value);
 -             break;
 -     }
 - }
 - 
 - unsigned char Echo::getpar(int npar) const
 - {
 -     switch(npar) {
 -         case 0:  return Pvolume;
 -         case 1:  return Ppanning;
 -         case 2:  return Pdelay;
 -         case 3:  return Plrdelay;
 -         case 4:  return Plrcross;
 -         case 5:  return Pfb;
 -         case 6:  return Phidamp;
 -         default: return 0; // in case of bogus parameter number
 -     }
 - }
 
 
  |