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