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 modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License (version 2 or later) for more details.
17
18 You should have received a copy of the GNU General Public License (version 2)
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 */
23
24 #include "Reverb.h"
25 #include "../Misc/Util.h"
26 #include "../DSP/AnalogFilter.h"
27 #include "../DSP/Unison.h"
28 #include <cmath>
29
Reverb(bool insertion_,float * efxoutl_,float * efxoutr_,unsigned int srate,int bufsize)30 Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
31 :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
32 // defaults
33 Pvolume(48),
34 Ptime(64),
35 Pidelay(40),
36 Pidelayfb(0),
37 Plpf(127),
38 Phpf(0),
39 Plohidamp(80),
40 Ptype(1),
41 Proomsize(64),
42 Pbandwidth(30),
43 roomsize(1.0f),
44 rs(1.0f),
45 bandwidth(NULL),
46 idelay(NULL),
47 lpf(NULL),
48 hpf(NULL) // no filter
49 {
50 for(int i = 0; i < REV_COMBS * 2; ++i) {
51 comblen[i] = 800 + (int)(RND * 1400.0f);
52 combk[i] = 0;
53 lpcomb[i] = 0;
54 combfb[i] = -0.97f;
55 comb[i] = NULL;
56 }
57
58 for(int i = 0; i < REV_APS * 2; ++i) {
59 aplen[i] = 500 + (int)(RND * 500.0f);
60 apk[i] = 0;
61 ap[i] = NULL;
62 }
63 setpreset(Ppreset);
64 cleanup(); //do not call this before the comb initialisation
65 }
66
67
~Reverb()68 Reverb::~Reverb()
69 {
70 delete [] idelay;
71 delete hpf;
72 delete lpf;
73
74 for(int i = 0; i < REV_APS * 2; ++i)
75 delete [] ap[i];
76 for(int i = 0; i < REV_COMBS * 2; ++i)
77 delete [] comb[i];
78
79 if(bandwidth)
80 delete bandwidth;
81 }
82
83 //Cleanup the effect
cleanup(void)84 void Reverb::cleanup(void)
85 {
86 int i, j;
87 for(i = 0; i < REV_COMBS * 2; ++i) {
88 lpcomb[i] = 0.0f;
89 for(j = 0; j < comblen[i]; ++j)
90 comb[i][j] = 0.0f;
91 }
92
93 for(i = 0; i < REV_APS * 2; ++i)
94 for(j = 0; j < aplen[i]; ++j)
95 ap[i][j] = 0.0f;
96
97 if(idelay)
98 for(i = 0; i < idelaylen; ++i)
99 idelay[i] = 0.0f;
100 if(hpf)
101 hpf->cleanup();
102 if(lpf)
103 lpf->cleanup();
104 }
105
106 //Process one channel; 0=left, 1=right
processmono(int ch,float * output,float * inputbuf)107 void Reverb::processmono(int ch, float *output, float *inputbuf)
108 {
109 //todo: implement the high part from lohidamp
110
111 for(int j = REV_COMBS * ch; j < REV_COMBS * (ch + 1); ++j) {
112 int &ck = combk[j];
113 const int comblength = comblen[j];
114 float &lpcombj = lpcomb[j];
115
116 for(int i = 0; i < buffersize; ++i) {
117 float fbout = comb[j][ck] * combfb[j];
118 fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb;
119 lpcombj = fbout;
120
121 comb[j][ck] = inputbuf[i] + fbout;
122 output[i] += fbout;
123
124 if((++ck) >= comblength)
125 ck = 0;
126 }
127 }
128
129 for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) {
130 int &ak = apk[j];
131 const int aplength = aplen[j];
132 for(int i = 0; i < buffersize; ++i) {
133 float tmp = ap[j][ak];
134 ap[j][ak] = 0.7f * tmp + output[i];
135 output[i] = tmp - 0.7f * ap[j][ak];
136 if((++ak) >= aplength)
137 ak = 0;
138 }
139 }
140 }
141
142 //Effect output
out(const Stereo<float * > & smp)143 void Reverb::out(const Stereo<float *> &smp)
144 {
145 if(!Pvolume && insertion)
146 return;
147
148 float inputbuf[buffersize];
149 for(int i = 0; i < buffersize; ++i)
150 inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f;
151
152 if(idelay)
153 for(int i = 0; i < buffersize; ++i) {
154 //Initial delay r
155 float tmp = inputbuf[i] + idelay[idelayk] * idelayfb;
156 inputbuf[i] = idelay[idelayk];
157 idelay[idelayk] = tmp;
158 idelayk++;
159 if(idelayk >= idelaylen)
160 idelayk = 0;
161 }
162
163 if(bandwidth)
164 bandwidth->process(buffersize, inputbuf);
165
166 if(lpf)
167 lpf->filterout(inputbuf);
168 if(hpf)
169 hpf->filterout(inputbuf);
170
171 processmono(0, efxoutl, inputbuf); //left
172 processmono(1, efxoutr, inputbuf); //right
173
174 float lvol = rs / REV_COMBS * pangainL;
175 float rvol = rs / REV_COMBS * pangainR;
176 if(insertion != 0) {
177 lvol *= 2.0f;
178 rvol *= 2.0f;
179 }
180 for(int i = 0; i < buffersize; ++i) {
181 efxoutl[i] *= lvol;
182 efxoutr[i] *= rvol;
183 }
184 }
185
186
187 //Parameter control
setvolume(unsigned char _Pvolume)188 void Reverb::setvolume(unsigned char _Pvolume)
189 {
190 Pvolume = _Pvolume;
191 if(!insertion) {
192 outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
193 volume = 1.0f;
194 }
195 else {
196 volume = outvolume = Pvolume / 127.0f;
197 if(Pvolume == 0)
198 cleanup();
199 }
200 }
201
settime(unsigned char _Ptime)202 void Reverb::settime(unsigned char _Ptime)
203 {
204 Ptime = _Ptime;
205 float t = powf(60.0f, Ptime / 127.0f) - 0.97f;
206
207 for(int i = 0; i < REV_COMBS * 2; ++i)
208 combfb[i] =
209 -expf((float)comblen[i] / samplerate_f * logf(0.001f) / t);
210 //the feedback is negative because it removes the DC
211 }
212
setlohidamp(unsigned char _Plohidamp)213 void Reverb::setlohidamp(unsigned char _Plohidamp)
214 {
215 Plohidamp = (_Plohidamp < 64) ? 64 : _Plohidamp;
216 //remove this when the high part from lohidamp is added
217 if(Plohidamp == 64) {
218 lohidamptype = 0;
219 lohifb = 0.0f;
220 }
221 else {
222 if(Plohidamp < 64)
223 lohidamptype = 1;
224 if(Plohidamp > 64)
225 lohidamptype = 2;
226 float x = fabsf((float)(Plohidamp - 64) / 64.1f);
227 lohifb = x * x;
228 }
229 }
230
setidelay(unsigned char _Pidelay)231 void Reverb::setidelay(unsigned char _Pidelay)
232 {
233 Pidelay = _Pidelay;
234 float delay = powf(50.0f * Pidelay / 127.0f, 2.0f) - 1.0f;
235
236 if(idelay)
237 delete [] idelay;
238 idelay = NULL;
239
240 idelaylen = (int) (samplerate_f * delay / 1000);
241 if(idelaylen > 1) {
242 idelayk = 0;
243 idelay = new float[idelaylen];
244 memset(idelay, 0, idelaylen * sizeof(float));
245 }
246 }
247
setidelayfb(unsigned char _Pidelayfb)248 void Reverb::setidelayfb(unsigned char _Pidelayfb)
249 {
250 Pidelayfb = _Pidelayfb;
251 idelayfb = Pidelayfb / 128.0f;
252 }
253
sethpf(unsigned char _Phpf)254 void Reverb::sethpf(unsigned char _Phpf)
255 {
256 Phpf = _Phpf;
257 if(Phpf == 0) { //No HighPass
258 if(hpf)
259 delete hpf;
260 hpf = NULL;
261 }
262 else {
263 float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f;
264 if(hpf == NULL)
265 hpf = new AnalogFilter(3, fr, 1, 0, samplerate, buffersize);
266 else
267 hpf->setfreq(fr);
268 }
269 }
270
setlpf(unsigned char _Plpf)271 void Reverb::setlpf(unsigned char _Plpf)
272 {
273 Plpf = _Plpf;
274 if(Plpf == 127) { //No LowPass
275 if(lpf)
276 delete lpf;
277 lpf = NULL;
278 }
279 else {
280 float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f;
281 if(!lpf)
282 lpf = new AnalogFilter(2, fr, 1, 0, samplerate, buffersize);
283 else
284 lpf->setfreq(fr);
285 }
286 }
287
settype(unsigned char _Ptype)288 void Reverb::settype(unsigned char _Ptype)
289 {
290 Ptype = _Ptype;
291 const int NUM_TYPES = 3;
292 const int combtunings[NUM_TYPES][REV_COMBS] = {
293 //this is unused (for random)
294 {0, 0, 0, 0, 0, 0, 0, 0 },
295 //Freeverb by Jezar at Dreampoint
296 {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 },
297 //duplicate of Freeverb by Jezar at Dreampoint
298 {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }
299 };
300
301 const int aptunings[NUM_TYPES][REV_APS] = {
302 //this is unused (for random)
303 {0, 0, 0, 0 },
304 //Freeverb by Jezar at Dreampoint
305 {225, 341, 441, 556 },
306 //duplicate of Freeverb by Jezar at Dreampoint
307 {225, 341, 441, 556 }
308 };
309
310 if(Ptype >= NUM_TYPES)
311 Ptype = NUM_TYPES - 1;
312
313 // adjust the combs according to the samplerate
314 float samplerate_adjust = samplerate_f / 44100.0f;
315 float tmp;
316 for(int i = 0; i < REV_COMBS * 2; ++i) {
317 if(Ptype == 0)
318 tmp = 800.0f + (int)(RND * 1400.0f);
319 else
320 tmp = combtunings[Ptype][i % REV_COMBS];
321 tmp *= roomsize;
322 if(i > REV_COMBS)
323 tmp += 23.0f;
324 tmp *= samplerate_adjust; //adjust the combs according to the samplerate
325 if(tmp < 10.0f)
326 tmp = 10.0f;
327 comblen[i] = (int) tmp;
328 combk[i] = 0;
329 lpcomb[i] = 0;
330 if(comb[i])
331 delete [] comb[i];
332 comb[i] = new float[comblen[i]];
333 }
334
335 for(int i = 0; i < REV_APS * 2; ++i) {
336 if(Ptype == 0)
337 tmp = 500 + (int)(RND * 500.0f);
338 else
339 tmp = aptunings[Ptype][i % REV_APS];
340 tmp *= roomsize;
341 if(i > REV_APS)
342 tmp += 23.0f;
343 tmp *= samplerate_adjust; //adjust the combs according to the samplerate
344 if(tmp < 10)
345 tmp = 10;
346 aplen[i] = (int) tmp;
347 apk[i] = 0;
348 if(ap[i])
349 delete [] ap[i];
350 ap[i] = new float[aplen[i]];
351 }
352 delete bandwidth;
353 bandwidth = NULL;
354 if(Ptype == 2) { //bandwidth
355 //TODO the size of the unison buffer may be too small, though this has
356 //not been verified yet.
357 //As this cannot be resized in a RT context, a good upper bound should
358 //be found
359 bandwidth = new Unison(buffersize / 4 + 1, 2.0f, samplerate_f);
360 bandwidth->setSize(50);
361 bandwidth->setBaseFrequency(1.0f);
362 }
363 settime(Ptime);
364 cleanup();
365 }
366
setroomsize(unsigned char _Proomsize)367 void Reverb::setroomsize(unsigned char _Proomsize)
368 {
369 Proomsize = _Proomsize;
370 if(!Proomsize)
371 this->Proomsize = 64; //this is because the older versions consider roomsize=0
372 roomsize = (this->Proomsize - 64.0f) / 64.0f;
373 if(roomsize > 0.0f)
374 roomsize *= 2.0f;
375 roomsize = powf(10.0f, roomsize);
376 rs = sqrtf(roomsize);
377 settype(Ptype);
378 }
379
setbandwidth(unsigned char _Pbandwidth)380 void Reverb::setbandwidth(unsigned char _Pbandwidth)
381 {
382 Pbandwidth = _Pbandwidth;
383 float v = Pbandwidth / 127.0f;
384 if(bandwidth)
385 bandwidth->setBandwidth(powf(v, 2.0f) * 200.0f);
386 }
387
setpreset(unsigned char npreset)388 void Reverb::setpreset(unsigned char npreset)
389 {
390 const int PRESET_SIZE = 13;
391 const int NUM_PRESETS = 13;
392 unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
393 //Cathedral1
394 {80, 64, 63, 24, 0, 0, 0, 85, 5, 83, 1, 64, 20},
395 //Cathedral2
396 {80, 64, 69, 35, 0, 0, 0, 127, 0, 71, 0, 64, 20},
397 //Cathedral3
398 {80, 64, 69, 24, 0, 0, 0, 127, 75, 78, 1, 85, 20},
399 //Hall1
400 {90, 64, 51, 10, 0, 0, 0, 127, 21, 78, 1, 64, 20},
401 //Hall2
402 {90, 64, 53, 20, 0, 0, 0, 127, 75, 71, 1, 64, 20},
403 //Room1
404 {100, 64, 33, 0, 0, 0, 0, 127, 0, 106, 0, 30, 20},
405 //Room2
406 {100, 64, 21, 26, 0, 0, 0, 62, 0, 77, 1, 45, 20},
407 //Basement
408 {110, 64, 14, 0, 0, 0, 0, 127, 5, 71, 0, 25, 20},
409 //Tunnel
410 {85, 80, 84, 20, 42, 0, 0, 51, 0, 78, 1, 105, 20},
411 //Echoed1
412 {95, 64, 26, 60, 71, 0, 0, 114, 0, 64, 1, 64, 20},
413 //Echoed2
414 {90, 64, 40, 88, 71, 0, 0, 114, 0, 88, 1, 64, 20},
415 //VeryLong1
416 {90, 64, 93, 15, 0, 0, 0, 114, 0, 77, 0, 95, 20},
417 //VeryLong2
418 {90, 64, 111, 30, 0, 0, 0, 114, 90, 74, 1, 80, 20}
419 };
420
421 if(npreset >= NUM_PRESETS)
422 npreset = NUM_PRESETS - 1;
423 for(int n = 0; n < PRESET_SIZE; ++n)
424 changepar(n, presets[npreset][n]);
425 if(insertion)
426 changepar(0, presets[npreset][0] / 2); //lower the volume if reverb is insertion effect
427 Ppreset = npreset;
428 }
429
430
changepar(int npar,unsigned char value)431 void Reverb::changepar(int npar, unsigned char value)
432 {
433 switch(npar) {
434 case 0:
435 setvolume(value);
436 break;
437 case 1:
438 setpanning(value);
439 break;
440 case 2:
441 settime(value);
442 break;
443 case 3:
444 setidelay(value);
445 break;
446 case 4:
447 setidelayfb(value);
448 break;
449 // case 5:
450 // setrdelay(value);
451 // break;
452 // case 6:
453 // seterbalance(value);
454 // break;
455 case 7:
456 setlpf(value);
457 break;
458 case 8:
459 sethpf(value);
460 break;
461 case 9:
462 setlohidamp(value);
463 break;
464 case 10:
465 settype(value);
466 break;
467 case 11:
468 setroomsize(value);
469 break;
470 case 12:
471 setbandwidth(value);
472 break;
473 }
474 }
475
getpar(int npar) const476 unsigned char Reverb::getpar(int npar) const
477 {
478 switch(npar) {
479 case 0: return Pvolume;
480 case 1: return Ppanning;
481 case 2: return Ptime;
482 case 3: return Pidelay;
483 case 4: return Pidelayfb;
484 case 7: return Plpf;
485 case 8: return Phpf;
486 case 9: return Plohidamp;
487 case 10: return Ptype;
488 case 11: return Proomsize;
489 case 12: return Pbandwidth;
490 default: return 0;
491 }
492 }
493