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