1 /**
2 * Enhanced Simple Tank Reverb
3 *
4 * Copyright (C) 2006-2018 Teru Kamogashira
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include "freeverb/strev.hpp"
22 #include "freeverb/fv3_type_float.h"
23 #include "freeverb/fv3_ns_start.h"
24
25 // Fs = 29.761 kHz
26 const long FV3_(strev)::allpCo[] = {142, 107, 379, 277, 672, 908, 1800, 2656,};
27 const long FV3_(strev)::delayCo[] = {4453, 3720, 4217, 3163,};
28 const long FV3_(strev)::idxLCo[] = {266, 2974, 1913, 1996, 1990, 187, 1066,};
29 const long FV3_(strev)::idxRCo[] = {353, 3627, 1228, 2673, 2111, 335, 121,};
30 const long FV3_(strev)::allpM_EXCURSION = 32;
31
FV3_(strev)32 FV3_(strev)::FV3_(strev)()
33 throw(std::bad_alloc)
34 {
35 setrt60(1);
36 setdccutfreq(10);
37 setidiffusion1(0.750);
38 setidiffusion2(0.625);
39 setdiffusion1(0.7);
40 setdiffusion2(0.5);
41 setinputdamp(10000);
42 setdamp(4000);
43 setoutputdamp(10000);
44 setspin(1);
45 setspindiff(0.1);
46 setspinlimit(10);
47 setwander(.1);
48 setmodulationnoise1(0.05);
49 setmodulationnoise2(0.03);
50 setAutoDiff(true);
51 }
52
FV3_(strev)53 void FV3_(strev)::mute()
54 {
55 FV3_(revbase)::mute();
56 for (long i = 0;i < FV3_STREV_NUM_ALLPASS_4;i ++) allpassC[i].mute();
57 allpassC_31_33.mute(); allpassC_55_59.mute();
58 allpassM_23_24.mute(); allpassM_46_48.mute(); delayC_30.mute(); delayC_39.mute(); delayC_54.mute(); delayC_63.mute();
59 dccut1.mute();
60 lpf_in.mute(); lpfC_30.mute(); lpfC_54.mute(); lfo1_lpf.mute(); lfo2_lpf.mute(); out1_lpf.mute(); out2_lpf.mute();
61 lfo1.mute(); lfo2.mute(); noise1L.mute();
62 }
63
64 /*
65 The following reverb algorithm and the allpass modulation filter's algorithm
66 originate from the following article and was originally developed by David Griesinger.
67
68 J. Dattorro, Effect Design Part 1: Reverberator and Other Filters (1997)
69 J. Audio Eng. Soc., vol. 45, pp. 660-684, Sept. 1997.
70 https://ccrma.stanford.edu/~dattorro/EffectDesignPart1.pdf
71
72 J. Dattorro, Effect Design Part 2: Delay-Line Modulation and Chorus (1997)
73 J. Audio Eng. Soc., vol. 45, pp. 764-788, Oct. 1997.
74 http://ccrma.stanford.edu/~dattorro/EffectDesignPart2.pdf
75
76 J. Dattorro, Effect Design: Part 3 Oscillators: Sinusoidal and Pseudonoise (2002)
77 J. Audio Eng. Soc., vol. 50, pp. 115-146, Mar. 2002.
78 http://ccrma.stanford.edu/~dattorro/EffectDesignPart3.pdf
79 */
80
FV3_(strev)81 void FV3_(strev)::processreplace(fv3_float_t *inputL, fv3_float_t *inputR, fv3_float_t *outputL, fv3_float_t *outputR, long numsamples)
82 throw(std::bad_alloc)
83 {
84 if(numsamples <= 0) return;
85 long count = numsamples;
86
87 fv3_float_t outL, outR, input;
88
89 while(count-- > 0)
90 {
91 outL = outR = 0.0;
92 input = (*inputL + *inputR) / 2;
93
94 // DC-cut HPF + input LPF
95 input = lpf_in(dccut1(input));
96
97 // Feed through allpasses in series
98 for(long i = 0;i < FV3_STREV_NUM_ALLPASS_4;i ++)
99 input = allpassC[i]._process(input);
100
101 // Split into L/R part
102 outL = input + delayC_63._getlast()*decay;
103 outR = input + delayC_39._getlast()*decay;
104
105 // Tank
106 fv3_float_t noise1 = noise1L();
107 fv3_float_t lfo1q = lfo1_lpf((lfo1() + modnoise1*noise1)*wander);
108 fv3_float_t lfo2q = lfo2_lpf((lfo2() - modnoise1*noise1)*wander);
109 delayC_39._process(allpassC_31_33._process(decay*lpfC_30(delayC_30._process(allpassM_23_24._process(outL, lfo1q, modnoise2*noise1)))));
110 delayC_63._process(allpassC_55_59._process(decay*lpfC_54(delayC_54._process(allpassM_46_48._process(outR, lfo2q, -1. * modnoise2*noise1)))));
111
112 outL = delayC_54._get_z(iLC[0]) + delayC_54._get_z(iLC[1]) - allpassC_55_59._get_z(iLC[2]) + delayC_63._get_z(iLC[3])
113 - delayC_30._get_z(iLC[4]) - allpassC_31_33._get_z(iLC[5]) - delayC_39._get_z(iLC[6]);
114 outR = delayC_30._get_z(iRC[0]) + delayC_30._get_z(iRC[1]) - allpassC_31_33._get_z(iRC[2]) + delayC_39._get_z(iRC[3])
115 - delayC_54._get_z(iRC[4]) - allpassC_55_59._get_z(iRC[5]) - delayC_63._get_z(iRC[6]);
116
117 fv3_float_t fpL = delayWL(out1_lpf(outL));
118 fv3_float_t fpR = delayWR(out2_lpf(outR));
119 *outputL = fpL*wet1 + fpR*wet2 + delayL(*inputL)*dry;
120 *outputR = fpR*wet1 + fpL*wet2 + delayR(*inputR)*dry;
121 UNDENORMAL(*outputL); UNDENORMAL(*outputR);
122 inputL ++; inputR ++; outputL ++; outputR ++;
123 }
124 }
125
FV3_(strev)126 void FV3_(strev)::setrt60(fv3_float_t value)
127 {
128 rt60 = value;
129 fv3_float_t back = rt60 * getTotalSampleRate();
130 UNDENORMAL(back);
131 if(back > 0) decay = std::pow((fv3_float_t)10.0, -3 * (fv3_float_t)tankDelay / back);
132 else decay = 0;
133 if(autoDiff)
134 {
135 fv3_float_t adiff = decay + 0.15;
136 if(adiff < 0.25) adiff = 0.25; if(adiff > 0.5) adiff = 0.5;
137 setdiffusion2(adiff);
138 }
139 }
140
FV3_(strev)141 fv3_float_t FV3_(strev)::getrt60()
142 {
143 return rt60;
144 }
145
FV3_(strev)146 void FV3_(strev)::setdccutfreq(fv3_float_t value)
147 {
148 dccutfq = limFs2(value);
149 dccut1.setCutOnFreq(dccutfq, getTotalSampleRate());
150 }
151
FV3_(strev)152 fv3_float_t FV3_(strev)::getdccutfreq()
153 {
154 return dccutfq;
155 }
156
FV3_(strev)157 void FV3_(strev)::setidiffusion1(fv3_float_t value)
158 {
159 idiff1 = value;
160 allpassC[0].setfeedback(-1*idiff1);
161 allpassC[1].setfeedback(-1*idiff1);
162 }
163
FV3_(strev)164 fv3_float_t FV3_(strev)::getidiffusion1()
165 {
166 return idiff1;
167 }
168
FV3_(strev)169 void FV3_(strev)::setidiffusion2(fv3_float_t value)
170 {
171 idiff2 = value;
172 allpassC[2].setfeedback(-1*idiff2);
173 allpassC[3].setfeedback(-1*idiff2);
174 }
175
FV3_(strev)176 fv3_float_t FV3_(strev)::getidiffusion2()
177 {
178 return idiff2;
179 }
180
FV3_(strev)181 void FV3_(strev)::setdiffusion1(fv3_float_t value)
182 {
183 diff1 = value;
184 allpassC_31_33.setfeedback(-1*diff1);
185 allpassC_55_59.setfeedback(-1*diff1);
186 }
187
FV3_(strev)188 fv3_float_t FV3_(strev)::getdiffusion1()
189 {
190 return diff1;
191 }
192
FV3_(strev)193 void FV3_(strev)::setdiffusion2(fv3_float_t value)
194 {
195 diff2 = value;
196 allpassM_23_24.setfeedback(diff2);
197 allpassM_46_48.setfeedback(diff2);
198 }
199
FV3_(strev)200 fv3_float_t FV3_(strev)::getdiffusion2()
201 {
202 return diff2;
203 }
204
FV3_(strev)205 void FV3_(strev)::setspin(fv3_float_t value)
206 {
207 if(spin > 0)
208 {
209 spin = limFs2(value);
210 lfo1.setFreq(spin, getTotalSampleRate());
211 lfo2.setFreq(spin+spindiff, getTotalSampleRate());
212 }
213 else
214 {
215 spin = 0; lfo1.setFreq(0); lfo2.setFreq(0);
216 }
217 }
218
FV3_(strev)219 fv3_float_t FV3_(strev)::getspin()
220 {
221 return spin;
222 }
223
224
FV3_(strev)225 void FV3_(strev)::setspindiff(fv3_float_t value)
226 {
227 spindiff = limFs2(value);
228 setspin(getspin());
229 }
230
FV3_(strev)231 fv3_float_t FV3_(strev)::getspindiff()
232 {
233 return spindiff;
234 }
235
FV3_(strev)236 void FV3_(strev)::setspinlimit(fv3_float_t value)
237 {
238 spinlimit = limFs2(value);
239 lfo1_lpf.setLPF_BW(spinlimit, getTotalSampleRate());
240 lfo2_lpf.setLPF_BW(spinlimit, getTotalSampleRate());
241 }
242
FV3_(strev)243 fv3_float_t FV3_(strev)::getspinlimit()
244 {
245 return spinlimit;
246 }
247
FV3_(strev)248 void FV3_(strev)::setwander(fv3_float_t value)
249 {
250 if(value < 0) value = 0;
251 if(value > 1) value = 1;
252 wander = value;
253 }
254
FV3_(strev)255 fv3_float_t FV3_(strev)::getwander()
256 {
257 return wander;
258 }
259
FV3_(strev)260 void FV3_(strev)::setmodulationnoise1(fv3_float_t value)
261 {
262 modnoise1 = value;
263 }
264
FV3_(strev)265 fv3_float_t FV3_(strev)::getmodulationnoise1()
266 {
267 return modnoise1;
268 }
269
FV3_(strev)270 void FV3_(strev)::setmodulationnoise2(fv3_float_t value)
271 {
272 modnoise2 = value;
273 }
274
FV3_(strev)275 fv3_float_t FV3_(strev)::getmodulationnoise2()
276 {
277 return modnoise2;
278 }
279
FV3_(strev)280 void FV3_(strev)::setinputdamp(fv3_float_t value)
281 {
282 inputdamp = limFs2(value);
283 lpf_in.setLPF_BW(inputdamp, getTotalSampleRate());
284 }
285
FV3_(strev)286 fv3_float_t FV3_(strev)::getinputdamp()
287 {
288 return inputdamp;
289 }
290
FV3_(strev)291 void FV3_(strev)::setdamp(fv3_float_t value)
292 {
293 damp = limFs2(value);
294 lpfC_30.setLPF_BW(damp, getTotalSampleRate());
295 lpfC_54.setLPF_BW(damp, getTotalSampleRate());
296 }
297
FV3_(strev)298 fv3_float_t FV3_(strev)::getdamp()
299 {
300 return damp;
301 }
302
FV3_(strev)303 void FV3_(strev)::setoutputdamp(fv3_float_t value)
304 {
305 outputdamp = limFs2(value);
306 out1_lpf.setLPF_BW(outputdamp, getTotalSampleRate());
307 out2_lpf.setLPF_BW(outputdamp, getTotalSampleRate());
308 }
309
FV3_(strev)310 fv3_float_t FV3_(strev)::getoutputdamp()
311 {
312 return outputdamp;
313 }
314
FV3_(strev)315 void FV3_(strev)::setAutoDiff(bool value)
316 {
317 autoDiff = value;
318 }
319
FV3_(strev)320 bool FV3_(strev)::getAutoDiff()
321 {
322 return autoDiff;
323 }
324
FV3_(strev)325 void FV3_(strev)::setFsFactors()
326 {
327 FV3_(revbase)::setFsFactors();
328
329 fv3_float_t totalFactor = getTotalFactorFs()/(fv3_float_t)FV3_STREV_DEFAULT_FS;
330 fv3_float_t excurFactor = getTotalSampleRate()/(fv3_float_t)FV3_STREV_DEFAULT_FS;
331
332 for(long i = 0;i < FV3_STREV_NUM_ALLPASS_4;i ++) allpassC[i].setsize(f_(allpCo[i],totalFactor));
333 allpassM_23_24.setsize(f_(allpCo[4],totalFactor), f_(allpM_EXCURSION,excurFactor));
334 allpassM_46_48.setsize(f_(allpCo[5],totalFactor), f_(allpM_EXCURSION,excurFactor));
335 allpassC_31_33.setsize(f_(allpCo[6],totalFactor));
336 allpassC_55_59.setsize(f_(allpCo[7],totalFactor));
337 delayC_30.setsize(f_(delayCo[0],totalFactor));
338 delayC_39.setsize(f_(delayCo[1],totalFactor));
339 delayC_54.setsize(f_(delayCo[2],totalFactor));
340 delayC_63.setsize(f_(delayCo[3],totalFactor));
341 for(long i = 0;i < FV3_STREV_NUM_INDEX;i ++)
342 {
343 iLC[i] = f_(idxLCo[i],totalFactor);
344 iRC[i] = f_(idxRCo[i],totalFactor);
345 }
346 tankDelay = (delayC_30.getsize()+delayC_39.getsize()+delayC_54.getsize()+delayC_63.getsize())/4;
347 setrt60(getrt60());
348 setdccutfreq(getdccutfreq());
349 setidiffusion1(getidiffusion1());
350 setidiffusion2(getidiffusion2());
351 setdiffusion1(getdiffusion1());
352 setdiffusion2(getdiffusion2());
353 setinputdamp(getinputdamp());
354 setdamp(getdamp());
355 setoutputdamp(getoutputdamp());
356 setspin(getspin());
357 setspindiff(getspindiff());
358 setspinlimit(getspinlimit());
359 setwander(getwander());
360 }
361
362 #include "freeverb/fv3_ns_end.h"
363