| 
							- /*
 -   ZynAddSubFX - a software synthesizer
 - 
 -   EffectMgr.cpp - 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 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 <rtosc/ports.h>
 - #include <rtosc/port-sugar.h>
 - #include <iostream>
 - #include <cassert>
 - 
 - 
 - #include "EffectMgr.h"
 - #include "Effect.h"
 - #include "Alienwah.h"
 - #include "Reverb.h"
 - #include "Echo.h"
 - #include "Chorus.h"
 - #include "Distorsion.h"
 - #include "EQ.h"
 - #include "DynamicFilter.h"
 - #include "Phaser.h"
 - #include "../Misc/XMLwrapper.h"
 - #include "../Misc/Util.h"
 - #include "../Params/FilterParams.h"
 - #include "../Misc/Allocator.h"
 - 
 - 
 - #define rObject EffectMgr
 - #define rSubtype(name) \
 -     {STRINGIFY(name)"/", NULL, &name::ports,\
 -         [](const char *msg, rtosc::RtData &data){\
 -             rObject &o = *(rObject*)data.obj; \
 -             data.obj = o.efx; \
 -             if(!dynamic_cast<name*>(o.efx)) \
 -                 return; \
 -             SNIP \
 -             name::ports.dispatch(msg, data); \
 -         }}
 - static const rtosc::Ports local_ports = {
 -     rSelf(EffectMgr),
 -     rPaste,
 -     rRecurp(filterpars, "Filter Parameter for Dynamic Filter"),
 -     {"Pvolume::i", rProp(parameter) rLinear(0,127) rShort("amt") rDoc("amount of effect"),
 -         0,
 -         [](const char *msg, rtosc::RtData &d)
 -         {
 -             EffectMgr *eff = (EffectMgr*)d.obj;
 -             if(!rtosc_narguments(msg))
 -                 d.reply(d.loc, "i", eff->geteffectparrt(0));
 -             else if(rtosc_type(msg, 0) == 'i'){
 -                 eff->seteffectparrt(0, rtosc_argument(msg, 0).i);
 -                 d.broadcast(d.loc, "i", eff->geteffectparrt(0));
 -             }
 -         }},
 -     {"Ppanning::i", rProp(parameter) rLinear(0,127) rShort("pan") rDoc("panning"),
 -         0,
 -         [](const char *msg, rtosc::RtData &d)
 -         {
 -             EffectMgr *eff = (EffectMgr*)d.obj;
 -             if(!rtosc_narguments(msg))
 -                 d.reply(d.loc, "i", eff->geteffectparrt(1));
 -             else if(rtosc_type(msg, 0) == 'i'){
 -                 eff->seteffectparrt(1, rtosc_argument(msg, 0).i);
 -                 d.broadcast(d.loc, "i", eff->geteffectparrt(1));
 -             }
 -         }},
 -     {"parameter#128::i:T:F", rProp(parameter) rProp(alias) rLinear(0,127) rDoc("Parameter Accessor"),
 -         NULL,
 -         [](const char *msg, rtosc::RtData &d)
 -         {
 -             EffectMgr *eff = (EffectMgr*)d.obj;
 -             const char *mm = msg;
 -             while(!isdigit(*mm))++mm;
 - 
 -             if(!rtosc_narguments(msg))
 -                 d.reply(d.loc, "i", eff->geteffectparrt(atoi(mm)));
 -             else if(rtosc_type(msg, 0) == 'i'){
 -                 eff->seteffectparrt(atoi(mm), rtosc_argument(msg, 0).i);
 -                 d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
 -             } else if(rtosc_type(msg, 0) == 'T'){
 -                 eff->seteffectparrt(atoi(mm), 127);
 -                 d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
 -             } else if(rtosc_type(msg, 0) == 'F'){
 -                 eff->seteffectparrt(atoi(mm), 0);
 -                 d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
 -             }
 -         }},
 -     {"preset::i", rProp(parameter) rProp(alias) rDoc("Effect Preset Selector"), NULL,
 -         [](const char *msg, rtosc::RtData &d)
 -         {
 -             char loc[1024];
 -             EffectMgr *eff = (EffectMgr*)d.obj;
 -             if(!rtosc_narguments(msg))
 -                 d.reply(d.loc, "i", eff->getpreset());
 -             else {
 -                 eff->changepresetrt(rtosc_argument(msg, 0).i);
 -                 d.broadcast(d.loc, "i", eff->getpreset());
 - 
 -                 //update parameters as well
 -                 strncpy(loc, d.loc, 1024);
 -                 char *tail = strrchr(loc, '/');
 -                 if(!tail)
 -                     return;
 -                 for(int i=0;i<128;++i) {
 -                     sprintf(tail+1, "parameter%d", i);
 -                     d.broadcast(loc, "i", eff->geteffectparrt(i));
 -                 }
 -             }
 -         }},
 -     {"eq-coeffs:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL,
 -         [](const char *, rtosc::RtData &d)
 -         {
 -             EffectMgr *eff = (EffectMgr*)d.obj;
 -             if(eff->nefx != 7)
 -                 return;
 -             EQ *eq = (EQ*)eff->efx;
 -             float a[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
 -             float b[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
 -             memset(a, 0, sizeof(a));
 -             memset(b, 0, sizeof(b));
 -             eq->getFilter(a,b);
 -             d.reply(d.loc, "bb", sizeof(a), a, sizeof(b), b);
 -         }},
 -     {"efftype::i", rOptions(Disabled, Reverb, Echo, Chorus,
 -             Phaser, Alienwah, Distorsion, EQ, DynFilter)
 -             rProp(parameter) rDoc("Get Effect Type"), NULL,
 -         [](const char *m, rtosc::RtData &d)
 -         {
 -             EffectMgr *eff  = (EffectMgr*)d.obj;
 -             if(rtosc_narguments(m))  {
 -                 eff->changeeffectrt(rtosc_argument(m,0).i);
 -                 d.broadcast(d.loc, "i", eff->nefx);
 -             } else
 -                 d.reply(d.loc, "i", eff->nefx);
 -         }},
 -     {"efftype:b", rProp(internal) rDoc("Pointer swap EffectMgr"), NULL,
 -         [](const char *msg, rtosc::RtData &d)
 -         {
 -             printf("OBSOLETE METHOD CALLED\n");
 -             EffectMgr *eff  = (EffectMgr*)d.obj;
 -             EffectMgr *eff_ = *(EffectMgr**)rtosc_argument(msg,0).b.data;
 - 
 -             //Lets trade data
 -             std::swap(eff->nefx,eff_->nefx);
 -             std::swap(eff->efx,eff_->efx);
 -             std::swap(eff->filterpars,eff_->filterpars);
 -             std::swap(eff->efxoutl, eff_->efxoutl);
 -             std::swap(eff->efxoutr, eff_->efxoutr);
 - 
 -             //Return the old data for distruction
 -             d.reply("/free", "sb", "EffectMgr", sizeof(EffectMgr*), &eff_);
 -         }},
 -     rSubtype(Alienwah),
 -     rSubtype(Chorus),
 -     rSubtype(Distorsion),
 -     rSubtype(DynamicFilter),
 -     rSubtype(Echo),
 -     rSubtype(EQ),
 -     rSubtype(Phaser),
 -     rSubtype(Reverb),
 - };
 - 
 - const rtosc::Ports &EffectMgr::ports = local_ports;
 - 
 - EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_,
 -                      const bool insertion_, const AbsTime *time_)
 -     :insertion(insertion_),
 -       efxoutl(new float[synth_.buffersize]),
 -       efxoutr(new float[synth_.buffersize]),
 -       filterpars(new FilterParams(time_)),
 -       nefx(0),
 -       efx(NULL),
 -       time(time_),
 -       dryonly(false),
 -       memory(alloc),
 -       synth(synth_)
 - {
 -     setpresettype("Peffect");
 -     memset(efxoutl, 0, synth.bufferbytes);
 -     memset(efxoutr, 0, synth.bufferbytes);
 -     memset(settings, 0, sizeof(settings));
 -     defaults();
 - }
 - 
 - 
 - EffectMgr::~EffectMgr()
 - {
 -     memory.dealloc(efx);
 -     delete filterpars;
 -     delete [] efxoutl;
 -     delete [] efxoutr;
 - }
 - 
 - void EffectMgr::defaults(void)
 - {
 -     changeeffect(0);
 -     setdryonly(false);
 - }
 - 
 - //Change the effect
 - void EffectMgr::changeeffectrt(int _nefx, bool avoidSmash)
 - {
 -     cleanup();
 -     if(nefx == _nefx && efx != NULL)
 -         return;
 -     nefx = _nefx;
 -     memset(efxoutl, 0, synth.bufferbytes);
 -     memset(efxoutr, 0, synth.bufferbytes);
 -     memory.dealloc(efx);
 -     EffectParams pars(memory, insertion, efxoutl, efxoutr, 0,
 -             synth.samplerate, synth.buffersize, filterpars, avoidSmash);
 -     try {
 -         switch (nefx) {
 -             case 1:
 -                 efx = memory.alloc<Reverb>(pars);
 -                 break;
 -             case 2:
 -                 efx = memory.alloc<Echo>(pars);
 -                 break;
 -             case 3:
 -                 efx = memory.alloc<Chorus>(pars);
 -                 break;
 -             case 4:
 -                 efx = memory.alloc<Phaser>(pars);
 -                 break;
 -             case 5:
 -                 efx = memory.alloc<Alienwah>(pars);
 -                 break;
 -             case 6:
 -                 efx = memory.alloc<Distorsion>(pars);
 -                 break;
 -             case 7:
 -                 efx = memory.alloc<EQ>(pars);
 -                 break;
 -             case 8:
 -                 efx = memory.alloc<DynamicFilter>(pars, time);
 -                 break;
 -             //put more effect here
 -             default:
 -                 efx = NULL;
 -                 break; //no effect (thru)
 -         }
 -     } catch (std::bad_alloc &ba) {
 -         std::cerr << "failed to change effect " << _nefx << ": " << ba.what() << std::endl;
 -         return;
 -     }
 - 
 -     if(!avoidSmash)
 -         for(int i=0; i<128; ++i)
 -             settings[i] = geteffectparrt(i);
 - }
 - 
 - void EffectMgr::changeeffect(int _nefx)
 - {
 -     nefx = _nefx;
 -     //preset    = 0;
 -     //memset(settings, 0, sizeof(settings));
 - }
 - 
 - //Obtain the effect number
 - int EffectMgr::geteffect(void)
 - {
 -     return nefx;
 - }
 - 
 - // Initialize An Effect in RT context
 - void EffectMgr::init(void)
 - {
 -     kill();
 -     changeeffectrt(nefx, true);
 -     changepresetrt(preset, true);
 -     for(int i=0; i<128; ++i)
 -         seteffectparrt(i, settings[i]);
 - }
 - 
 - //Strip effect manager of it's realtime memory
 - void EffectMgr::kill(void)
 - {
 -     //printf("Killing Effect(%d)\n", nefx);
 -     memory.dealloc(efx);
 - }
 - 
 - // Cleanup the current effect
 - void EffectMgr::cleanup(void)
 - {
 -     if(efx)
 -         efx->cleanup();
 - }
 - 
 - 
 - // Get the preset of the current effect
 - unsigned char EffectMgr::getpreset(void)
 - {
 -     if(efx)
 -         return efx->Ppreset;
 -     else
 -         return 0;
 - }
 - 
 - // Change the preset of the current effect
 - void EffectMgr::changepreset(unsigned char npreset)
 - {
 -     preset = npreset;
 - }
 - 
 - // Change the preset of the current effect
 - void EffectMgr::changepresetrt(unsigned char npreset, bool avoidSmash)
 - {
 -     preset = npreset;
 -     if(avoidSmash && dynamic_cast<DynamicFilter*>(efx)) {
 -         efx->Ppreset = npreset;
 -         return;
 -     }
 -     if(efx)
 -         efx->setpreset(npreset);
 -     if(!avoidSmash)
 -         for(int i=0; i<128; ++i)
 -             settings[i] = geteffectparrt(i);
 - }
 - 
 - //Change a parameter of the current effect
 - void EffectMgr::seteffectparrt(int npar, unsigned char value)
 - {
 -     if(npar<128)
 -         settings[npar] = value;
 -     if(!efx)
 -         return;
 -     try {
 -         efx->changepar(npar, value);
 -     } catch (std::bad_alloc &ba) {
 -         std::cerr << "failed to change effect parameter " << npar << " to " << value << ": " << ba.what() << std::endl;
 -     }
 - }
 - 
 - //Change a parameter of the current effect
 - void EffectMgr::seteffectpar(int npar, unsigned char value)
 - {
 -     settings[npar] = value;
 - }
 - 
 - //Get a parameter of the current effect
 - unsigned char EffectMgr::geteffectpar(int npar)
 - {
 -     if(npar<128)
 -         return settings[npar];
 - 
 -     if(!efx)
 -         return 0;
 -     return efx->getpar(npar);
 - }
 - 
 - unsigned char EffectMgr::geteffectparrt(int npar)
 - {
 -     if(!efx)
 -         return 0;
 -     return efx->getpar(npar);
 - }
 - 
 - // Apply the effect
 - void EffectMgr::out(float *smpsl, float *smpsr)
 - {
 -     if(!efx) {
 -         if(!insertion)
 -             for(int i = 0; i < synth.buffersize; ++i) {
 -                 smpsl[i]   = 0.0f;
 -                 smpsr[i]   = 0.0f;
 -                 efxoutl[i] = 0.0f;
 -                 efxoutr[i] = 0.0f;
 -             }
 -         return;
 -     }
 -     for(int i = 0; i < synth.buffersize; ++i) {
 -         smpsl[i]  += synth.denormalkillbuf[i];
 -         smpsr[i]  += synth.denormalkillbuf[i];
 -         efxoutl[i] = 0.0f;
 -         efxoutr[i] = 0.0f;
 -     }
 -     efx->out(smpsl, smpsr);
 - 
 -     float volume = efx->volume;
 - 
 -     if(nefx == 7) { //this is need only for the EQ effect
 -         memcpy(smpsl, efxoutl, synth.bufferbytes);
 -         memcpy(smpsr, efxoutr, synth.bufferbytes);
 -         return;
 -     }
 - 
 -     //Insertion effect
 -     if(insertion != 0) {
 -         float v1, v2;
 -         if(volume < 0.5f) {
 -             v1 = 1.0f;
 -             v2 = volume * 2.0f;
 -         }
 -         else {
 -             v1 = (1.0f - volume) * 2.0f;
 -             v2 = 1.0f;
 -         }
 -         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(int i = 0; i < synth.buffersize; ++i) {
 -                 smpsl[i]   *= v1;
 -                 smpsr[i]   *= v1;
 -                 efxoutl[i] *= v2;
 -                 efxoutr[i] *= v2;
 -             }
 -         else // normal instrument/insertion effect
 -             for(int i = 0; i < synth.buffersize; ++i) {
 -                 smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2;
 -                 smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2;
 -             }
 -     }
 -     else // System effect
 -         for(int i = 0; i < synth.buffersize; ++i) {
 -             efxoutl[i] *= 2.0f * volume;
 -             efxoutr[i] *= 2.0f * volume;
 -             smpsl[i]    = efxoutl[i];
 -             smpsr[i]    = efxoutr[i];
 -         }
 - }
 - 
 - 
 - // Get the effect volume for the system effect
 - float EffectMgr::sysefxgetvolume(void)
 - {
 -     return efx ? efx->outvolume : 1.0f;
 - }
 - 
 - 
 - // Get the EQ response
 - float EffectMgr::getEQfreqresponse(float freq)
 - {
 -     return (nefx == 7) ? efx->getfreqresponse(freq) : 0.0f;
 - }
 - 
 - 
 - void EffectMgr::setdryonly(bool value)
 - {
 -     dryonly = value;
 - }
 - 
 - void EffectMgr::paste(EffectMgr &e)
 - {
 -     changeeffectrt(e.nefx, true);
 -     changepresetrt(e.preset, true);
 -     for(int i=0;i<128;++i)
 -         seteffectparrt(i, e.settings[i]);
 -     if(dynamic_cast<DynamicFilter*>(efx)) {
 -         std::swap(filterpars, e.filterpars);
 -         efx->filterpars = filterpars;
 -     }
 -     cleanup(); // cleanup the effect and recompute its parameters
 - }
 - 
 - void EffectMgr::add2XML(XMLwrapper& xml)
 - {
 -     xml.addpar("type", geteffect());
 - 
 -     if(!geteffect())
 -         return;
 -     xml.addpar("preset", preset);
 - 
 -     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();
 -     }
 -     assert(filterpars);
 -     if(nefx == 8) {
 -         xml.beginbranch("FILTER");
 -         filterpars->add2XML(xml);
 -         xml.endbranch();
 -     }
 -     xml.endbranch();
 - }
 - 
 - void EffectMgr::getfromXML(XMLwrapper& xml)
 - {
 -     changeeffect(xml.getpar127("type", geteffect()));
 - 
 -     if(!geteffect())
 -         return;
 - 
 -     preset = xml.getpar127("preset", preset);
 - 
 -     if(xml.enterbranch("EFFECT_PARAMETERS")) {
 -         for(int n = 0; n < 128; ++n) {
 -             seteffectpar(n, 0); //erase effect parameter
 -             if(xml.enterbranch("par_no", n) == 0)
 -                 continue;
 -             int par = geteffectpar(n);
 -             seteffectpar(n, xml.getpar127("par", par));
 -             xml.exitbranch();
 -         }
 -         assert(filterpars);
 -         if(xml.enterbranch("FILTER")) {
 -             filterpars->getfromXML(xml);
 -             xml.exitbranch();
 -         }
 -         xml.exitbranch();
 -     }
 -     cleanup();
 - }
 
 
  |