1 /*
2 ZynAddSubFX - a software synthesizer
3
4 Reverb.C - Reverberation effect
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Author: Nasca Octavian Paul
7
8 Modified for rakarrack by Josep Andreu
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of version 2 of the GNU General Public License
12 as published by the Free Software Foundation.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License (version 2) for more details.
18
19 You should have received a copy of the GNU General Public License (version 2)
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24
25 #include <stdio.h>
26
27 #include <math.h>
28 #include <stdlib.h>
29 #include "Reverb.h"
30
31 /*TODO: EarlyReflections,Prdelay,Perbalance */
32
Reverb(float * efxoutl_,float * efxoutr_,double samplerate,uint16_t intermediate_bufsize)33 Reverb::Reverb (float * efxoutl_, float * efxoutr_, double samplerate, uint16_t intermediate_bufsize)
34 {
35 efxoutl = efxoutl_;
36 efxoutr = efxoutr_;
37 inputbuf = new float[intermediate_bufsize];
38 //filterpars=NULL;
39 unsigned int i;
40 for(i=0;i<intermediate_bufsize;i++)
41 {
42 inputbuf[i] = 0;
43 }
44
45
46 //defaults
47 Ppreset = 0;
48 Pvolume = 48;
49 Ppan = 64;
50 Ptime = 64;
51 Pidelay = 40;
52 Pidelayfb = 0;
53 Prdelay = 0;
54 Plpf = 127;
55 Phpf = 0;
56 Perbalance = 64;
57 Plohidamp = 80;
58 Ptype = 1;
59 Proomsize = 64;
60 roomsize = 1.0f;
61 rs = 1.0f;
62 rs_coeff = rs / (float) REV_COMBS;
63
64 fSAMPLE_RATE = samplerate;
65
66 //max comb length
67 unsigned int tmp = lrintf(220023.0*samplerate/44100.0);
68
69 for (int i = 0; i < REV_COMBS * 2; i++) {
70 comblen[i] = 800 + (int) (RND * 1400);
71 combk[i] = 0;
72 lpcomb[i] = 0;
73 combfb[i] = -0.97f;
74 comb[i] = new float[tmp];//set to make length so we don't need to reallocate ever
75 };
76
77 //max ap length
78 tmp = lrintf(100023.0*samplerate/44100.0);
79
80 for (int i = 0; i < REV_APS * 2; i++) {
81 aplen[i] = 500 + (int) (RND * 500);
82 apk[i] = 0;
83 ap[i] = new float[tmp]; //set to max length
84 };
85
86 interpbuf = new float[intermediate_bufsize];
87 lpf = new AnalogFilter (2, 22000, 1, 0, samplerate, interpbuf);
88 hpf = new AnalogFilter (3, 20, 1, 0, samplerate, interpbuf);
89
90 //max delay length
91 tmp = lrintf(2.5*samplerate);
92 idelay = new float[tmp]; //set to max length
93
94 setpreset (Ppreset);
95 cleanup (); //do not call this before the comb initialisation
96 };
97
98
~Reverb()99 Reverb::~Reverb ()
100 {
101 delete lpf;
102 delete hpf;
103 delete[] interpbuf;
104 delete[] inputbuf;
105 for (int i = 0; i < REV_COMBS * 2; i++) {
106 delete[] comb[i];
107 }
108 for (int i = 0; i < REV_APS * 2; i++) {
109 delete[] ap[i];
110 }
111 delete[] idelay;
112 };
113
114 /*
115 * Cleanup the effect
116 */
117 void
cleanup()118 Reverb::cleanup ()
119 {
120 int i, j;
121 for (i = 0; i < REV_COMBS * 2; i++) {
122 lpcomb[i] = 0.0;
123 for (j = 0; j < comblen[i]; j++)
124 comb[i][j] = 0.0;
125 };
126
127 for (i = 0; i < REV_APS * 2; i++)
128 for (j = 0; j < aplen[i]; j++)
129 ap[i][j] = 0.0;
130
131 if (idelay != NULL)
132 for (i = 0; i < idelaylen; i++)
133 idelay[i] = 0.0;
134
135 hpf->cleanup ();
136 lpf->cleanup ();
137
138
139 };
140
141 /*
142 * Process one channel; 0=left,1=right
143 */
144 void
processmono(unsigned int ch,float * output,uint32_t period)145 Reverb::processmono (unsigned int ch, float * output, uint32_t period)
146 {
147 unsigned int i, j;
148 float fbout, tmp;
149 //TODO: implement the high part from lohidamp
150
151 for (j = REV_COMBS * ch; j < REV_COMBS * (ch + 1); j++) {
152
153 int ck = combk[j];
154 int comblength = comblen[j];
155 float lpcombj = lpcomb[j];
156
157 for (i = 0; i < period; i++) {
158 fbout = comb[j][ck] * combfb[j];
159 fbout = fbout * (1.0f - lohifb) + (lpcombj * lohifb);
160 lpcombj = fbout;
161
162 comb[j][ck] = inputbuf[i] + fbout;
163 output[i] += fbout;
164
165 if ((++ck) >= comblength)
166 ck = 0;
167 };
168
169 combk[j] = ck;
170 lpcomb[j] = lpcombj;
171 };
172
173 for (j = REV_APS * ch; j < REV_APS * (1 + ch); j++) {
174 int ak = apk[j];
175 int aplength = aplen[j];
176 for (i = 0; i < period; i++) {
177 tmp = ap[j][ak];
178 ap[j][ak] = 0.7f * tmp + output[i];
179 output[i] = tmp - 0.7f * ap[j][ak];
180 if ((++ak) >= aplength)
181 ak = 0;
182 };
183 apk[j] = ak;
184 };
185 };
186
187 /*
188 * Effect output
189 */
190 void
out(float * smps_l,float * smps_r,uint32_t period)191 Reverb::out (float * smps_l, float * smps_r, uint32_t period)
192 {
193 unsigned int i;
194
195 for (i = 0; i < period; i++) {
196 inputbuf[i] = (smps_l[i] + smps_r[i]) * .5f;
197 //Initial delay r
198 if (idelay != NULL) {
199 float tmp = inputbuf[i] + idelay[idelayk] * idelayfb;
200 inputbuf[i] = idelay[idelayk];
201 idelay[idelayk] = tmp;
202 idelayk++;
203 if (idelayk >= idelaylen)
204 idelayk = 0;
205 };
206 };
207
208
209 lpf->filterout (inputbuf, period);
210 hpf->filterout (inputbuf, period);
211
212 processmono (0, efxoutl, period); //left
213 processmono (1, efxoutr, period); //right
214
215
216
217 float lvol = rs_coeff * pan * 2.0f;
218 float rvol = rs_coeff * (1.0f - pan) * 2.0f;
219
220 for (unsigned int i = 0; i < period; i++) {
221 efxoutl[i] *= lvol;
222 efxoutr[i] *= rvol;
223
224 };
225 };
226
227
228 /*
229 * Parameter control
230 */
231 void
setvolume(int Pvolume)232 Reverb::setvolume (int Pvolume)
233 {
234 this->Pvolume = Pvolume;
235 outvolume = (float)Pvolume / 127.0f;
236 if (Pvolume == 0)
237 cleanup ();
238
239
240 };
241
242 void
setpan(int Ppan)243 Reverb::setpan (int Ppan)
244 {
245 this->Ppan = Ppan;
246 pan = (float) Ppan / 127.0f;
247 };
248
249 void
settime(int Ptime)250 Reverb::settime (int Ptime)
251 {
252 int i;
253 float t;
254 this->Ptime = Ptime;
255 t = powf (60.0f, (float) Ptime / 127.0f) - 0.97f;
256
257 for (i = 0; i < REV_COMBS * 2; i++) {
258 combfb[i] =
259 -expf ((float) comblen[i] / fSAMPLE_RATE * logf (0.001f) /
260 t);
261 //the feedback is negative because it removes the DC
262 };
263 };
264
265 void
setlohidamp(int Plohidamp)266 Reverb::setlohidamp (int Plohidamp)
267 {
268 float x;
269
270 if (Plohidamp < 64)
271 Plohidamp = 64; //remove this when the high part from lohidamp will be added
272
273 this->Plohidamp = Plohidamp;
274 if (Plohidamp == 64) {
275 lohidamptype = 0;
276 lohifb = 0.0;
277 } else {
278 if (Plohidamp < 64)
279 lohidamptype = 1;
280 if (Plohidamp > 64)
281 lohidamptype = 2;
282 x = fabsf ((float) (Plohidamp - 64) / 64.1f);
283 lohifb = x * x;
284 };
285 };
286
287 void
setidelay(int Pidelay)288 Reverb::setidelay (int Pidelay)
289 {
290 float delay;
291 this->Pidelay = Pidelay;
292 delay = powf (50.0f * (float)Pidelay / 127.0f, 2.0f) - 1.0f;
293
294 idelaylen = lrintf (fSAMPLE_RATE * delay / 1000.0f);
295 if (idelaylen > 1) {
296 idelayk = 0;
297 for (int i = 0; i < idelaylen; i++)
298 idelay[i] = 0.0;
299 };
300 };
301
302 void
setidelayfb(int Pidelayfb)303 Reverb::setidelayfb (int Pidelayfb)
304 {
305 this->Pidelayfb = Pidelayfb;
306 idelayfb = (float)Pidelayfb / 128.0f;
307 };
308
309 void
sethpf(int value)310 Reverb::sethpf (int value)
311 {
312 Phpf = value;
313 float fr = (float)Phpf;
314 hpf->setfreq (fr);
315
316 };
317
318 void
setlpf(int value)319 Reverb::setlpf (int value)
320 {
321 Plpf = value;
322 float fr = (float)Plpf;
323 lpf->setfreq (fr);
324
325 };
326
327 void
settype(int Ptype)328 Reverb::settype (int Ptype)
329 {
330 const int NUM_TYPES = 2;
331 int combtunings[NUM_TYPES][REV_COMBS] = {
332 //this is unused (for random)
333 {0, 0, 0, 0, 0, 0, 0, 0},
334 //Freeverb by Jezar at Dreampoint
335 {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617}
336 };
337 int aptunings[NUM_TYPES][REV_APS] = {
338 //this is unused (for random)
339 {0, 0, 0, 0},
340 //Freeverb by Jezar at Dreampoint
341 {225, 341, 441, 556}
342 };
343
344 if (Ptype >= NUM_TYPES)
345 Ptype = NUM_TYPES - 1;
346 this->Ptype = Ptype;
347
348 float tmp;
349 for (int i = 0; i < REV_COMBS * 2; i++) {
350 if (Ptype == 0)
351 tmp = 800.0f + (float)(RND*1400.0f);
352 else
353 tmp = (float)combtunings[Ptype][i % REV_COMBS];
354 tmp *= roomsize;
355 if (i > REV_COMBS)
356 tmp += 23.0f;
357 tmp *= fSAMPLE_RATE / 44100.0f; //adjust the combs according to the samplerate
358 if (tmp < 10)
359 tmp = 10;
360
361 comblen[i] = lrintf(tmp);
362 combk[i] = 0;
363 lpcomb[i] = 0;
364 };
365
366 for (int i = 0; i < REV_APS * 2; i++) {
367 if (Ptype == 0)
368 tmp = 500.0f + (float)(RND*500.0f);
369 else
370 tmp = (float)aptunings[Ptype][i % REV_APS];
371 tmp *= roomsize;
372 if (i > REV_APS)
373 tmp += 23.0f;
374 tmp *= fSAMPLE_RATE / 44100.0f; //adjust the combs according to the samplerate
375 if (tmp < 10)
376 tmp = 10;
377 aplen[i] = lrintf(tmp);
378 apk[i] = 0;
379 };
380 settime (Ptime);
381 cleanup ();
382 };
383
384 void
setroomsize(int Proomsize)385 Reverb::setroomsize (int Proomsize)
386 {
387 if (Proomsize == 0)
388 Proomsize = 64; //this is because the older versions consider roomsize=0
389 this->Proomsize = Proomsize;
390 roomsize = ((float)Proomsize - 64.0f) / 64.0f;
391 if (roomsize > 0.0)
392 roomsize *= 2.0f;
393 roomsize = powf (10.0f, roomsize);
394 rs = sqrtf (roomsize);
395 rs_coeff = rs / (float) REV_COMBS;
396 settype (Ptype);
397 };
398
399 void
setpreset(int npreset)400 Reverb::setpreset (int npreset)
401 {
402 const int PRESET_SIZE = 12;
403 const int NUM_PRESETS = 13;
404 int pdata[PRESET_SIZE];
405 int presets[NUM_PRESETS][PRESET_SIZE] = {
406 //Cathedral1
407 {80, 64, 63, 24, 0, 0, 0, 4002, 27, 83, 1, 64},
408 //Cathedral2
409 {80, 64, 69, 35, 0, 0, 0, 25040, 21, 71, 0, 64},
410 //Cathedral3
411 {80, 64, 69, 24, 0, 0, 0, 25040, 2417, 78, 1, 85},
412 //Hall1
413 {90, 64, 51, 10, 0, 0, 0, 25040, 81, 78, 1, 64},
414 //Hall2
415 {90, 64, 53, 20, 0, 0, 0, 25040, 2417, 71, 1, 64},
416 //Room1
417 {100, 64, 33, 0, 0, 0, 0, 25040, 21, 106, 0, 30},
418 //Room2
419 {100, 64, 21, 26, 0, 0, 0, 1223, 21, 77, 1, 45},
420 //Basement
421 {110, 64, 14, 0, 0, 0, 0, 25040, 27, 71, 0, 25},
422 //Tunnel
423 {85, 80, 84, 20, 42, 0, 0, 652, 21, 78, 1, 105},
424 //Echoed1
425 {95, 64, 26, 60, 71, 0, 0, 14722, 21, 64, 1, 64},
426 //Echoed2
427 {90, 64, 40, 88, 71, 0, 0, 14722, 21, 88, 1, 64},
428 //VeryLong1
429 {90, 64, 93, 15, 0, 0, 0, 14722, 21, 77, 0, 95},
430 //VeryLong2
431 {90, 64, 111, 30, 0, 0, 0, 14722, 5058, 74, 1, 80}
432 };
433
434
435 if(npreset>NUM_PRESETS-1) {
436
437 Fpre->ReadPreset(8,npreset-NUM_PRESETS+1,pdata);
438 for (int n = 0; n < PRESET_SIZE; n++)
439 changepar (n, pdata[n]);
440 } else {
441 for (int n = 0; n < PRESET_SIZE; n++)
442 changepar (n, presets[npreset][n]);
443 }
444 Ppreset = npreset;
445 };
446
447
448 void
changepar(int npar,int value)449 Reverb::changepar (int npar, int value)
450 {
451 switch (npar) {
452 case 0:
453 setvolume (value);
454 break;
455 case 1:
456 setpan (value);
457 break;
458 case 2:
459 settime (value);
460 break;
461 case 3:
462 setidelay (value);
463 break;
464 case 4:
465 setidelayfb (value);
466 break;
467 // case 5: setrdelay(value);
468 // break;
469 // case 6: seterbalance(value);
470 // break;
471 case 7:
472 setlpf (value);
473 break;
474 case 8:
475 sethpf (value);
476 break;
477 case 9:
478 setlohidamp (value);
479 break;
480 case 10:
481 settype (value);
482 break;
483 case 11:
484 setroomsize (value);
485 break;
486 };
487 };
488
489 int
getpar(int npar)490 Reverb::getpar (int npar)
491 {
492 switch (npar) {
493 case 0:
494 return (Pvolume);
495 break;
496 case 1:
497 return (Ppan);
498 break;
499 case 2:
500 return (Ptime);
501 break;
502 case 3:
503 return (Pidelay);
504 break;
505 case 4:
506 return (Pidelayfb);
507 break;
508 // case 5: return(Prdelay);
509 // break;
510 // case 6: return(Perbalance);
511 // break;
512 case 7:
513 return (Plpf);
514 break;
515 case 8:
516 return (Phpf);
517 break;
518 case 9:
519 return (Plohidamp);
520 break;
521 case 10:
522 return (Ptype);
523 break;
524 case 11:
525 return (Proomsize);
526 break;
527 };
528 return (0); //in case of bogus "parameter"
529 };
530