zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

Reverb.cpp (15941B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   Reverb.cpp - Reverberation effect
      5   Copyright (C) 2002-2005 Nasca Octavian Paul
      6   Author: Nasca Octavian Paul
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 #include "Reverb.h"
     15 #include "../Misc/Util.h"
     16 #include "../Misc/Allocator.h"
     17 #include "../DSP/AnalogFilter.h"
     18 #include "../DSP/Unison.h"
     19 #include <cmath>
     20 #include <rtosc/ports.h>
     21 #include <rtosc/port-sugar.h>
     22 
     23 namespace zyn {
     24 
     25 #define rObject Reverb
     26 #define rBegin [](const char *msg, rtosc::RtData &d) {
     27 #define rEnd }
     28 
     29 rtosc::Ports Reverb::ports = {
     30     {"preset::i", rOptions(Cathedral1, Cathedral2, Cathedral3,
     31             Hall1, Hall2, Room1, Room2, Basement,
     32             Tunnel, Echoed1, Echoed2, VeryLong1, VeryLong2)
     33                   rDefault(0)
     34                   rProp(alias)
     35                   rProp(parameter)
     36                   rDoc("Instrument Presets"), 0,
     37                   rBegin;
     38                   rObject *o = (rObject*)d.obj;
     39                   if(rtosc_narguments(msg))
     40                       o->setpreset(rtosc_argument(msg, 0).i);
     41                   else
     42                       d.reply(d.loc, "i", o->Ppreset);
     43                   rEnd},
     44     rPresetForVolume,
     45     rEffParVol(rDefaultDepends(presetOfVolume),
     46           rDefault(90),
     47           rPresets(80, 80, 80),
     48           rPresetsAt(5, 100, 100, 110, 85, 95),
     49           rPresetsAt(16, 40, 40, 40, 45, 45),
     50           rPresetsAt(21, 50, 50, 55, 42, 47, 45, 45, 45)),
     51     rEffParPan(rDefaultDepends(preset), rPreset(8, 80)),
     52     rEffPar(Ptime,    2, rShort("time"), rLinear(0, 127),
     53             rPresets(63, 69, 69, 51, 53, 33, 21, 14, 84, 26, 40, 93, 111),
     54             "Length of Reverb"),
     55     rEffPar(Pidelay,  3, rShort("i.time"),
     56             rPresets(24, 35, 24, 10, 20, 0, 26, 0, 20, 60, 88, 15, 30),
     57             "Delay for first impulse"),
     58     rEffPar(Pidelayfb,4, rShort("i.fb"), rPresetsAt(8, 42, 71, 71), rDefault(0),
     59             "Feedback for first impulse"),
     60     rEffPar(Plpf,     7, rShort("lpf"),
     61             rPreset(0, 85), rPresetsAt(6, 62, 127, 51, 114, 114, 114, 114),
     62             rDefault(127), "Low pass filter"),
     63     rEffPar(Phpf,     8, rShort("hpf"),
     64             rPresets(5), rPresetsAt(2, 75, 21, 75), rPreset(7, 5),
     65             rPreset(12, 90), rDefault(0), "High pass filter"),
     66     rEffPar(Plohidamp,9, rShort("damp"),
     67             rPresets(83, 71, 78, 78, 71, 106, 77, 71, 78, 64, 88, 77, 74),
     68             "Dampening"),
     69     //Todo make this a selector
     70     rEffParOpt(Ptype,    10, rShort("type"),
     71             rOptions(Random, Freeverb, Bandwidth),
     72             rPresets(Freeverb, Random, Freeverb, Freeverb, Freeverb, Random,
     73                      Freeverb, Random, Freeverb, Freeverb, Freeverb, Random,
     74                      Freeverb)
     75             rDefault(Random), "Type"),
     76     rEffPar(Proomsize,11,rShort("size"),
     77             rPreset(2, 85), rPresetsAt(5, 30, 45, 25, 105),
     78             rPresetsAt(11, 95, 80), rDefault(64),
     79             "Room Size"),
     80     rEffPar(Pbandwidth,12,rShort("bw"), rDefault(20), "Bandwidth"),
     81 };
     82 #undef rBegin
     83 #undef rEnd
     84 #undef rObject
     85 
     86 Reverb::Reverb(EffectParams pars)
     87     :Effect(pars),
     88       // defaults
     89       Pvolume(48),
     90       Ptime(64),
     91       Pidelay(40),
     92       Pidelayfb(0),
     93       Plpf(127),
     94       Phpf(0),
     95       Plohidamp(80),
     96       Ptype(1),
     97       Proomsize(64),
     98       Pbandwidth(30),
     99       idelaylen(0),
    100       roomsize(1.0f),
    101       rs(1.0f),
    102       bandwidth(NULL),
    103       idelay(NULL),
    104       lpf(NULL),
    105       hpf(NULL) // no filter
    106 {
    107     for(int i = 0; i < REV_COMBS * 2; ++i) {
    108         comblen[i] = 800 + (int)(RND * 1400.0f);
    109         combk[i]   = 0;
    110         lpcomb[i]  = 0;
    111         combfb[i]  = -0.97f;
    112         comb[i]    = NULL;
    113     }
    114 
    115     for(int i = 0; i < REV_APS * 2; ++i) {
    116         aplen[i] = 500 + (int)(RND * 500.0f);
    117         apk[i]   = 0;
    118         ap[i]    = NULL;
    119     }
    120     setpreset(Ppreset);
    121     cleanup(); //do not call this before the comb initialisation
    122 }
    123 
    124 
    125 Reverb::~Reverb()
    126 {
    127     memory.devalloc(idelay);
    128     memory.dealloc(hpf);
    129     memory.dealloc(lpf);
    130 
    131     for(int i = 0; i < REV_APS * 2; ++i)
    132         memory.devalloc(ap[i]);
    133     for(int i = 0; i < REV_COMBS * 2; ++i)
    134         memory.devalloc(comb[i]);
    135 
    136     memory.dealloc(bandwidth);
    137 }
    138 
    139 //Cleanup the effect
    140 void Reverb::cleanup(void)
    141 {
    142     for(int i = 0; i < REV_COMBS * 2; ++i) {
    143         lpcomb[i] = 0.0f;
    144         for(int j = 0; j < comblen[i]; ++j)
    145             comb[i][j] = 0.0f;
    146     }
    147 
    148     for(int i = 0; i < REV_APS * 2; ++i)
    149         for(int j = 0; j < aplen[i]; ++j)
    150             ap[i][j] = 0.0f;
    151 
    152     if(idelay)
    153         for(int i = 0; i < idelaylen; ++i)
    154             idelay[i] = 0.0f;
    155     if(hpf)
    156         hpf->cleanup();
    157     if(lpf)
    158         lpf->cleanup();
    159 }
    160 
    161 //Process one channel; 0=left, 1=right
    162 void Reverb::processmono(int ch, float *output, float *inputbuf)
    163 {
    164     //todo: implement the high part from lohidamp
    165 
    166     for(int j = REV_COMBS * ch; j < REV_COMBS * (ch + 1); ++j) {
    167         int &ck = combk[j];
    168         const int comblength = comblen[j];
    169         float    &lpcombj    = lpcomb[j];
    170 
    171         for(int i = 0; i < buffersize; ++i) {
    172             float fbout = comb[j][ck] * combfb[j];
    173             fbout   = fbout * (1.0f - lohifb) + lpcombj * lohifb;
    174             lpcombj = fbout;
    175 
    176             comb[j][ck] = inputbuf[i] + fbout;
    177             output[i]  += fbout;
    178 
    179             if((++ck) >= comblength)
    180                 ck = 0;
    181         }
    182     }
    183 
    184     for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) {
    185         int &ak = apk[j];
    186         const int aplength = aplen[j];
    187         for(int i = 0; i < buffersize; ++i) {
    188             float tmp = ap[j][ak];
    189             ap[j][ak] = 0.7f * tmp + output[i];
    190             output[i] = tmp - 0.7f * ap[j][ak];
    191             if((++ak) >= aplength)
    192                 ak = 0;
    193         }
    194     }
    195 }
    196 
    197 //Effect output
    198 void Reverb::out(const Stereo<float *> &smp)
    199 {
    200     if(!Pvolume && insertion)
    201         return;
    202 
    203     float inputbuf[buffersize];
    204     for(int i = 0; i < buffersize; ++i)
    205         inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f;
    206 
    207     if(idelay)
    208         for(int i = 0; i < buffersize; ++i) {
    209             //Initial delay r
    210             float tmp = inputbuf[i] + idelay[idelayk] * idelayfb;
    211             inputbuf[i]     = idelay[idelayk];
    212             idelay[idelayk] = tmp;
    213             idelayk++;
    214             if(idelayk >= idelaylen)
    215                 idelayk = 0;
    216         }
    217 
    218     if(bandwidth)
    219         bandwidth->process(buffersize, inputbuf);
    220 
    221     if(lpf)
    222         lpf->filterout(inputbuf);
    223     if(hpf)
    224         hpf->filterout(inputbuf);
    225 
    226     processmono(0, efxoutl, inputbuf); //left
    227     processmono(1, efxoutr, inputbuf); //right
    228 
    229     float lvol = rs / REV_COMBS * pangainL;
    230     float rvol = rs / REV_COMBS * pangainR;
    231     if(insertion != 0) {
    232         lvol *= 2.0f;
    233         rvol *= 2.0f;
    234     }
    235     for(int i = 0; i < buffersize; ++i) {
    236         efxoutl[i] *= lvol;
    237         efxoutr[i] *= rvol;
    238     }
    239 }
    240 
    241 
    242 //Parameter control
    243 void Reverb::setvolume(unsigned char _Pvolume)
    244 {
    245     Pvolume = _Pvolume;
    246     if(!insertion) {
    247         if (Pvolume == 0) {
    248             outvolume = 0.0f;
    249         } else {
    250             outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
    251         }
    252         volume    = 1.0f;
    253     }
    254     else {
    255         volume = outvolume = Pvolume / 127.0f;
    256         if(Pvolume == 0)
    257             cleanup();
    258     }
    259 }
    260 
    261 void Reverb::settime(unsigned char _Ptime)
    262 {
    263     Ptime = _Ptime;
    264     float t = powf(60.0f, Ptime / 127.0f) - 0.97f;
    265 
    266     for(int i = 0; i < REV_COMBS * 2; ++i)
    267         combfb[i] =
    268             -expf((float)comblen[i] / samplerate_f * logf(0.001f) / t);
    269     //the feedback is negative because it removes the DC
    270 }
    271 
    272 void Reverb::setlohidamp(unsigned char _Plohidamp)
    273 {
    274     Plohidamp = (_Plohidamp < 64) ? 64 : _Plohidamp;
    275     //remove this when the high part from lohidamp is added
    276     if(Plohidamp == 64) {
    277         lohidamptype = 0;
    278         lohifb = 0.0f;
    279     }
    280     else {
    281         if(Plohidamp < 64)
    282             lohidamptype = 1;
    283         if(Plohidamp > 64)
    284             lohidamptype = 2;
    285         float x = fabsf((float)(Plohidamp - 64) / 64.1f);
    286         lohifb = x * x;
    287     }
    288 }
    289 
    290 void Reverb::setidelay(unsigned char _Pidelay)
    291 {
    292     Pidelay = _Pidelay;
    293     float delay = powf(50.0f * Pidelay / 127.0f, 2.0f) - 1.0f;
    294     int newDelayLen = (int) (samplerate_f * delay / 1000);
    295     if(newDelayLen == idelaylen)
    296         return;
    297 
    298     memory.devalloc(idelay);
    299 
    300     idelaylen = newDelayLen;
    301     if(idelaylen > 1) {
    302         idelayk = 0;
    303         idelay  = memory.valloc<float>(idelaylen);
    304         memset(idelay, 0, idelaylen * sizeof(float));
    305     }
    306 }
    307 
    308 void Reverb::setidelayfb(unsigned char _Pidelayfb)
    309 {
    310     Pidelayfb = _Pidelayfb;
    311     idelayfb  = Pidelayfb / 128.0f;
    312 }
    313 
    314 void Reverb::sethpf(unsigned char _Phpf)
    315 {
    316     Phpf = _Phpf;
    317     if(Phpf == 0) { //No HighPass
    318         memory.dealloc(hpf);
    319     } else {
    320         float fr = expf(sqrtf(Phpf / 127.0f) * logf(10000.0f)) + 20.0f;
    321         if(hpf == NULL)
    322             hpf = memory.alloc<AnalogFilter>(3, fr, 1, 0, samplerate, buffersize);
    323         else
    324             hpf->setfreq(fr);
    325     }
    326 }
    327 
    328 void Reverb::setlpf(unsigned char _Plpf)
    329 {
    330     Plpf = _Plpf;
    331     if(Plpf == 127) { //No LowPass
    332         memory.dealloc(lpf);
    333     } else {
    334         float fr = expf(sqrtf(Plpf / 127.0f) * logf(25000.0f)) + 40.0f;
    335         if(!lpf)
    336             lpf = memory.alloc<AnalogFilter>(2, fr, 1, 0, samplerate, buffersize);
    337         else
    338             lpf->setfreq(fr);
    339     }
    340 }
    341 
    342 void Reverb::settype(unsigned char _Ptype)
    343 {
    344     Ptype = _Ptype;
    345     const int NUM_TYPES = 3;
    346     const int combtunings[NUM_TYPES][REV_COMBS] = {
    347         //this is unused (for random)
    348         {0,    0,    0,    0,    0,    0,    0,    0      },
    349         //Freeverb by Jezar at Dreampoint
    350         {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617   },
    351         //duplicate of Freeverb by Jezar at Dreampoint
    352         {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617   }
    353     };
    354 
    355     const int aptunings[NUM_TYPES][REV_APS] = {
    356         //this is unused (for random)
    357         {0,   0,   0,   0    },
    358         //Freeverb by Jezar at Dreampoint
    359         {225, 341, 441, 556  },
    360         //duplicate of Freeverb by Jezar at Dreampoint
    361         {225, 341, 441, 556  }
    362     };
    363 
    364     if(Ptype >= NUM_TYPES)
    365         Ptype = NUM_TYPES - 1;
    366 
    367     // adjust the combs according to the samplerate
    368     float samplerate_adjust = samplerate_f / 44100.0f;
    369     float tmp;
    370     for(int i = 0; i < REV_COMBS * 2; ++i) {
    371         if(Ptype == 0)
    372             tmp = 800.0f + (int)(RND * 1400.0f);
    373         else
    374             tmp = combtunings[Ptype][i % REV_COMBS];
    375         tmp *= roomsize;
    376         if(i > REV_COMBS)
    377             tmp += 23.0f;
    378         tmp *= samplerate_adjust; //adjust the combs according to the samplerate
    379         if(tmp < 10.0f)
    380             tmp = 10.0f;
    381         combk[i]   = 0;
    382         lpcomb[i]  = 0;
    383         if(comblen[i] != (int)tmp || comb[i] == NULL) {
    384             comblen[i] = (int) tmp;
    385             memory.devalloc(comb[i]);
    386             comb[i] = memory.valloc<float>(comblen[i]);
    387         }
    388     }
    389 
    390     for(int i = 0; i < REV_APS * 2; ++i) {
    391         if(Ptype == 0)
    392             tmp = 500 + (int)(RND * 500.0f);
    393         else
    394             tmp = aptunings[Ptype][i % REV_APS];
    395         tmp *= roomsize;
    396         if(i > REV_APS)
    397             tmp += 23.0f;
    398         tmp *= samplerate_adjust; //adjust the combs according to the samplerate
    399         if(tmp < 10)
    400             tmp = 10;
    401         apk[i]   = 0;
    402         if(aplen[i] != (int)tmp || ap[i] == NULL) {
    403             aplen[i] = (int) tmp;
    404             memory.devalloc(ap[i]);
    405             ap[i] = memory.valloc<float>(aplen[i]);
    406         }
    407     }
    408     memory.dealloc(bandwidth);
    409     if(Ptype == 2) { //bandwidth
    410         //TODO the size of the unison buffer may be too small, though this has
    411         //not been verified yet.
    412         //As this cannot be resized in a RT context, a good upper bound should
    413         //be found
    414         bandwidth = memory.alloc<Unison>(&memory, buffersize / 4 + 1, 2.0f, samplerate_f);
    415         bandwidth->setSize(50);
    416         bandwidth->setBaseFrequency(1.0f);
    417     }
    418     settime(Ptime);
    419     cleanup();
    420 }
    421 
    422 void Reverb::setroomsize(unsigned char _Proomsize)
    423 {
    424     Proomsize = _Proomsize;
    425     if(!Proomsize)
    426         this->Proomsize = 64;  //this is because the older versions consider roomsize=0
    427     roomsize = (this->Proomsize - 64.0f) / 64.0f;
    428     if(roomsize > 0.0f)
    429         roomsize *= 2.0f;
    430     roomsize = powf(10.0f, roomsize);
    431     rs = sqrtf(roomsize);
    432     settype(Ptype);
    433 }
    434 
    435 void Reverb::setbandwidth(unsigned char _Pbandwidth)
    436 {
    437     Pbandwidth = _Pbandwidth;
    438     float v = Pbandwidth / 127.0f;
    439     if(bandwidth)
    440         bandwidth->setBandwidth(powf(v, 2.0f) * 200.0f);
    441 }
    442 
    443 unsigned char Reverb::getpresetpar(unsigned char npreset, unsigned int npar)
    444 {
    445 #define	PRESET_SIZE 13
    446 #define	NUM_PRESETS 13
    447     static const unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
    448         //Cathedral1
    449         {80,  64, 63,  24, 0,  0, 0, 85,  5,  83,  1, 64,  20},
    450         //Cathedral2
    451         {80,  64, 69,  35, 0,  0, 0, 127, 0,  71,  0, 64,  20},
    452         //Cathedral3
    453         {80,  64, 69,  24, 0,  0, 0, 127, 75, 78,  1, 85,  20},
    454         //Hall1
    455         {90,  64, 51,  10, 0,  0, 0, 127, 21, 78,  1, 64,  20},
    456         //Hall2
    457         {90,  64, 53,  20, 0,  0, 0, 127, 75, 71,  1, 64,  20},
    458         //Room1
    459         {100, 64, 33,  0,  0,  0, 0, 127, 0,  106, 0, 30,  20},
    460         //Room2
    461         {100, 64, 21,  26, 0,  0, 0, 62,  0,  77,  1, 45,  20},
    462         //Basement
    463         {110, 64, 14,  0,  0,  0, 0, 127, 5,  71,  0, 25,  20},
    464         //Tunnel
    465         {85,  80, 84,  20, 42, 0, 0, 51,  0,  78,  1, 105, 20},
    466         //Echoed1
    467         {95,  64, 26,  60, 71, 0, 0, 114, 0,  64,  1, 64,  20},
    468         //Echoed2
    469         {90,  64, 40,  88, 71, 0, 0, 114, 0,  88,  1, 64,  20},
    470         //VeryLong1
    471         {90,  64, 93,  15, 0,  0, 0, 114, 0,  77,  0, 95,  20},
    472         //VeryLong2
    473         {90,  64, 111, 30, 0,  0, 0, 114, 90, 74,  1, 80,  20}
    474     };
    475     if(npreset < NUM_PRESETS && npar < PRESET_SIZE) {
    476         if (npar == 0 && insertion != 0) {
    477             /* lower the volume if reverb is insertion effect */
    478             return presets[npreset][npar] / 2;
    479         }
    480         return presets[npreset][npar];
    481     }
    482     return 0;
    483 }
    484 
    485 void Reverb::setpreset(unsigned char npreset)
    486 {
    487     if(npreset >= NUM_PRESETS)
    488         npreset = NUM_PRESETS - 1;
    489     for(int n = 0; n != 128; n++)
    490         changepar(n, getpresetpar(npreset, n));
    491     Ppreset = npreset;
    492 }
    493 
    494 void Reverb::changepar(int npar, unsigned char value)
    495 {
    496     switch(npar) {
    497         case 0:
    498             setvolume(value);
    499             break;
    500         case 1:
    501             setpanning(value);
    502             break;
    503         case 2:
    504             settime(value);
    505             break;
    506         case 3:
    507             setidelay(value);
    508             break;
    509         case 4:
    510             setidelayfb(value);
    511             break;
    512 //      case 5:
    513 //          setrdelay(value);
    514 //          break;
    515 //      case 6:
    516 //          seterbalance(value);
    517 //          break;
    518         case 7:
    519             setlpf(value);
    520             break;
    521         case 8:
    522             sethpf(value);
    523             break;
    524         case 9:
    525             setlohidamp(value);
    526             break;
    527         case 10:
    528             settype(value);
    529             break;
    530         case 11:
    531             setroomsize(value);
    532             break;
    533         case 12:
    534             setbandwidth(value);
    535             break;
    536     }
    537 }
    538 
    539 unsigned char Reverb::getpar(int npar) const
    540 {
    541     switch(npar) {
    542         case 0:  return Pvolume;
    543         case 1:  return Ppanning;
    544         case 2:  return Ptime;
    545         case 3:  return Pidelay;
    546         case 4:  return Pidelayfb;
    547         case 7:  return Plpf;
    548         case 8:  return Phpf;
    549         case 9:  return Plohidamp;
    550         case 10: return Ptype;
    551         case 11: return Proomsize;
    552         case 12: return Pbandwidth;
    553         default: return 0;
    554     }
    555 }
    556 
    557 }