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 }