| 
							- /*
 -   ZynAddSubFX - a software synthesizer
 - 
 -   Chorus.cpp - 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 the GNU General Public License
 -   as published by the Free Software Foundation; either version 2
 -   of the License, or (at your option) any later version.
 - */
 - 
 - #include <cmath>
 - #include <rtosc/ports.h>
 - #include <rtosc/port-sugar.h>
 - #include "../Misc/Allocator.h"
 - #include "Chorus.h"
 - #include <iostream>
 - using namespace std;
 - 
 - namespace zyncarla {
 - 
 - #define rObject Chorus
 - #define rBegin [](const char *msg, rtosc::RtData &d) {
 - #define rEnd }
 - 
 - rtosc::Ports Chorus::ports = {
 -     {"preset::i", rProp(parameter)
 -                   rOptions(Chorus1, Chorus2, Chorus3, Celeste1, Celeste2,
 -                            Flange1, Flange2, Flange3, Flange4, Flange5)
 -                   rDoc("Instrument Presets"), 0,
 -                   rBegin;
 -                   rObject *o = (rObject*)d.obj;
 -                   if(rtosc_narguments(msg))
 -                       o->setpreset(rtosc_argument(msg, 0).i);
 -                   else
 -                       d.reply(d.loc, "i", o->Ppreset);
 - 
 -                   rEnd},
 -     //Pvolume/Ppanning are common
 -     rEffParVol(rDefault(64)),
 -     rEffParPan(),
 -     rEffPar(Pfreq,    2, rShort("freq"),
 -             rPresets(50, 45, 29, 26, 29, 57, 33, 53, 40, 55),
 -             "Effect Frequency"),
 -     rEffPar(Pfreqrnd, 3, rShort("rand"),
 -             rPreset(4, 117) rPreset(6, 34) rPreset(7, 34) rPreset(9, 105)
 -             rDefault(0), "Frequency Randomness"),
 -     rEffPar(PLFOtype, 4, rShort("shape"),
 -             rOptions(sine, tri),
 -             rPresets(sine, sine, tri, sine, sine, sine, tri, tri, tri, sine)
 -             "LFO Shape"),
 -     rEffPar(PStereo,  5, rShort("stereo"),
 -             rPresets(90, 98, 42, 42, 50, 60, 40, 94, 62), "Stereo Mode"),
 -     rEffPar(Pdepth,   6, rShort("depth"),
 -             rPresets(40, 56, 97, 115, 115, 23, 35, 35, 12), "LFO Depth"),
 -     rEffPar(Pdelay,   7, rShort("delay"),
 -             rPresets(85, 90, 95, 18, 9, 3, 3, 3, 19), "Delay"),
 -     rEffPar(Pfeedback,8, rShort("fb"),
 -             rPresets(64, 64, 90, 90, 31, 62, 109, 54, 97), "Feedback"),
 -     rEffPar(Plrcross, 9, rShort("l/r"), rPresets(119, 19, 127, 127, 127),
 -             rDefault(0), "Left/Right Crossover"),
 -     rEffParTF(Pflangemode, 10, rShort("flange"), rDefault(false),
 -               "Flange Mode"),
 -     rEffParTF(Poutsub, 11, rShort("sub"), rPreset(4, true), rPreset(7, true),
 -               rDefault(false), "Output Subtraction"),
 - };
 - #undef rBegin
 - #undef rEnd
 - #undef rObject
 - 
 - Chorus::Chorus(EffectParams pars)
 -     :Effect(pars),
 -       lfo(pars.srate, pars.bufsize),
 -       maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * samplerate_f)),
 -       delaySample(memory.valloc<float>(maxdelay), memory.valloc<float>(maxdelay))
 - {
 -     dlk = 0;
 -     drk = 0;
 -     setpreset(Ppreset);
 -     changepar(1, 64);
 -     lfo.effectlfoout(&lfol, &lfor);
 -     dl2 = getdelay(lfol);
 -     dr2 = getdelay(lfor);
 -     cleanup();
 - }
 - 
 - Chorus::~Chorus()
 - {
 -     memory.devalloc(delaySample.l);
 -     memory.devalloc(delaySample.r);
 - }
 - 
 - //get the delay value in samples; xlfo is the current lfo value
 - float Chorus::getdelay(float xlfo)
 - {
 -     float result =
 -         (Pflangemode) ? 0 : (delay + xlfo * depth) * samplerate_f;
 - 
 -     //check if delay is too big (caused by bad setdelay() and setdepth()
 -     if((result + 0.5f) >= maxdelay) {
 -         cerr
 -         <<
 -         "WARNING: Chorus.cpp::getdelay(..) too big delay (see setdelay and setdepth funcs.)"
 -         << endl;
 -         result = maxdelay - 1.0f;
 -     }
 -     return result;
 - }
 - 
 - //Apply the effect
 - void Chorus::out(const Stereo<float *> &input)
 - {
 -     dl1 = dl2;
 -     dr1 = dr2;
 -     lfo.effectlfoout(&lfol, &lfor);
 - 
 -     dl2 = getdelay(lfol);
 -     dr2 = getdelay(lfor);
 - 
 -     for(int i = 0; i < buffersize; ++i) {
 -         float inL = input.l[i];
 -         float inR = input.r[i];
 -         //LRcross
 -         Stereo<float> tmpc(inL, inR);
 -         inL = tmpc.l * (1.0f - lrcross) + tmpc.r * lrcross;
 -         inR = tmpc.r * (1.0f - lrcross) + tmpc.l * lrcross;
 - 
 -         //Left channel
 - 
 -         //compute the delay in samples using linear interpolation between the lfo delays
 -         float mdel =
 -             (dl1 * (buffersize - i) + dl2 * i) / buffersize_f;
 -         if(++dlk >= maxdelay)
 -             dlk = 0;
 -         float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from
 - 
 -         dlhi  = (int) tmp;
 -         dlhi %= maxdelay;
 - 
 -         float dlhi2 = (dlhi - 1 + maxdelay) % maxdelay;
 -         float dllo  = 1.0f + floorf(tmp) - tmp;
 -         efxoutl[i] = cinterpolate(delaySample.l, maxdelay, dlhi2) * dllo
 -                      + cinterpolate(delaySample.l, maxdelay,
 -                                     dlhi) * (1.0f - dllo);
 -         delaySample.l[dlk] = inL + efxoutl[i] * fb;
 - 
 -         //Right channel
 - 
 -         //compute the delay in samples using linear interpolation between the lfo delays
 -         mdel = (dr1 * (buffersize - i) + dr2 * i) / buffersize_f;
 -         if(++drk >= maxdelay)
 -             drk = 0;
 -         tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from
 - 
 -         dlhi  = (int) tmp;
 -         dlhi %= maxdelay;
 - 
 -         dlhi2      = (dlhi - 1 + maxdelay) % maxdelay;
 -         dllo       = 1.0f + floorf(tmp) - tmp;
 -         efxoutr[i] = cinterpolate(delaySample.r, maxdelay, dlhi2) * dllo
 -                      + cinterpolate(delaySample.r, maxdelay,
 -                                     dlhi) * (1.0f - dllo);
 -         delaySample.r[dlk] = inR + efxoutr[i] * fb;
 -     }
 - 
 -     if(Poutsub)
 -         for(int i = 0; i < buffersize; ++i) {
 -             efxoutl[i] *= -1.0f;
 -             efxoutr[i] *= -1.0f;
 -         }
 - 
 -     for(int i = 0; i < buffersize; ++i) {
 -         efxoutl[i] *= pangainL;
 -         efxoutr[i] *= pangainR;
 -     }
 - }
 - 
 - //Cleanup the effect
 - void Chorus::cleanup(void)
 - {
 -     memset(delaySample.l, 0, maxdelay * sizeof(float));
 -     memset(delaySample.r, 0, maxdelay * sizeof(float));
 - }
 - 
 - //Parameter control
 - void Chorus::setdepth(unsigned char _Pdepth)
 - {
 -     Pdepth = _Pdepth;
 -     depth  = (powf(8.0f, (Pdepth / 127.0f) * 2.0f) - 1.0f) / 1000.0f; //seconds
 - }
 - 
 - void Chorus::setdelay(unsigned char _Pdelay)
 - {
 -     Pdelay = _Pdelay;
 -     delay  = (powf(10.0f, (Pdelay / 127.0f) * 2.0f) - 1.0f) / 1000.0f; //seconds
 - }
 - 
 - void Chorus::setfb(unsigned char _Pfb)
 - {
 -     Pfb = _Pfb;
 -     fb  = (Pfb - 64.0f) / 64.1f;
 - }
 - 
 - void Chorus::setvolume(unsigned char _Pvolume)
 - {
 -     Pvolume   = _Pvolume;
 -     outvolume = Pvolume / 127.0f;
 -     volume    = (!insertion) ? 1.0f : outvolume;
 - }
 - 
 - 
 - 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:
 -             Pflangemode = (value > 1) ? 1 : value;
 -             break;
 -         case 11:
 -             Poutsub = (value > 1) ? 1 : value;
 -             break;
 -     }
 - }
 - 
 - unsigned char Chorus::getpar(int npar) const
 - {
 -     switch(npar) {
 -         case 0:  return Pvolume;
 -         case 1:  return Ppanning;
 -         case 2:  return lfo.Pfreq;
 -         case 3:  return lfo.Prandomness;
 -         case 4:  return lfo.PLFOtype;
 -         case 5:  return lfo.Pstereo;
 -         case 6:  return Pdepth;
 -         case 7:  return Pdelay;
 -         case 8:  return Pfb;
 -         case 9:  return Plrcross;
 -         case 10: return Pflangemode;
 -         case 11: return Poutsub;
 -         default: return 0;
 -     }
 - }
 - 
 - }
 
 
  |