2 ==============================================================================
3 This file is part of Tal-Reverb by Patrick Kunz.
5 Copyright(c) 2005-2009 Patrick Kunz, TAL
9 This file may be licensed under the terms of of the
10 GNU General Public License Version 2 (the ``GPL'').
12 Software distributed under the License is distributed
13 on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14 express or implied. See the GPL for the specific language
15 governing rights and limitations.
17 You should have received a copy of the GPL along with this
18 program. If not, go to http://www.gnu.org/licenses/gpl.html
19 or write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 ==============================================================================
25 #if !defined(__TalReverb_h)
28 #include "AllPassFilter.h"
29 #include "CombFilter.h"
30 #include "NoiseGenerator.h"
33 #include "AudioUtils.h"
39 static const int DELAY_LINES_COMB
= 4;
40 static const int DELAY_LINES_ALLPASS
= 5;
42 static const int MAX_PRE_DELAY_MS
= 1000;
43 float* reflectionGains
;
44 float* reflectionDelays
;
46 CombFilter
*combFiltersPreDelayL
;
47 CombFilter
*combFiltersPreDelayR
;
49 CombFilter
**combFiltersL
;
50 CombFilter
**combFiltersR
;
51 NoiseGenerator
**noiseGeneratorAllPassL
;
52 NoiseGenerator
**noiseGeneratorAllPassR
;
53 NoiseGenerator
**noiseGeneratorDelayL
;
54 NoiseGenerator
**noiseGeneratorDelayR
;
55 NoiseGenerator
**diffusionL
;
56 NoiseGenerator
**diffusionR
;
58 AllPassFilter
**allPassFiltersL
;
59 AllPassFilter
**allPassFiltersR
;
61 AllPassFilter
*preAllPassFilterL
;
62 AllPassFilter
*preAllPassFilterR
;
64 AllPassFilter
*postAllPassFilterL
;
65 AllPassFilter
*postAllPassFilterR
;
73 float modulationIntensity
;
78 AudioUtils audioUtils
;
81 TalReverb(int sampleRate
)
83 createDelaysAndCoefficients(DELAY_LINES_COMB
+ DELAY_LINES_ALLPASS
, 82.0f
);
85 combFiltersPreDelayL
= new CombFilter((float)MAX_PRE_DELAY_MS
, 0.0f
, sampleRate
);
86 combFiltersPreDelayR
= new CombFilter((float)MAX_PRE_DELAY_MS
, 0.0f
, sampleRate
);
88 combFiltersL
= new CombFilter
*[DELAY_LINES_COMB
];
89 combFiltersR
= new CombFilter
*[DELAY_LINES_COMB
];
90 noiseGeneratorAllPassL
= new NoiseGenerator
*[DELAY_LINES_COMB
];
91 noiseGeneratorAllPassR
= new NoiseGenerator
*[DELAY_LINES_COMB
];
92 noiseGeneratorDelayL
= new NoiseGenerator
*[DELAY_LINES_COMB
];
93 noiseGeneratorDelayR
= new NoiseGenerator
*[DELAY_LINES_COMB
];
94 diffusionL
= new NoiseGenerator
*[DELAY_LINES_COMB
];
95 diffusionR
= new NoiseGenerator
*[DELAY_LINES_COMB
];
97 float stereoSpreadValue
= 0.008f
;
98 float stereoSpreadSign
= 1.0f
;
99 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++)
101 float stereoSpreadFactor
= 1.0f
+ stereoSpreadValue
;
102 if (stereoSpreadSign
> 0.0f
)
104 combFiltersL
[i
] = new CombFilter(reflectionDelays
[i
] * stereoSpreadFactor
, reflectionGains
[i
], sampleRate
);
105 combFiltersR
[i
] = new CombFilter(reflectionDelays
[i
], reflectionGains
[i
], sampleRate
);
109 combFiltersL
[i
] = new CombFilter(reflectionDelays
[i
], reflectionGains
[i
], sampleRate
);
110 combFiltersR
[i
] = new CombFilter(reflectionDelays
[i
] * stereoSpreadFactor
, reflectionGains
[i
], sampleRate
);
112 stereoSpreadSign
*= -1.0f
;
113 noiseGeneratorAllPassL
[i
] = new NoiseGenerator(sampleRate
);
114 noiseGeneratorAllPassR
[i
] = new NoiseGenerator(sampleRate
);
115 noiseGeneratorDelayL
[i
] = new NoiseGenerator(sampleRate
);
116 noiseGeneratorDelayR
[i
] = new NoiseGenerator(sampleRate
);
117 diffusionL
[i
] = new NoiseGenerator(sampleRate
);
118 diffusionR
[i
] = new NoiseGenerator(sampleRate
);
121 preAllPassFilterL
= new AllPassFilter(20.0f
, 0.68f
, sampleRate
);
122 preAllPassFilterR
= new AllPassFilter(20.0f
, 0.68f
, sampleRate
);
124 postAllPassFilterL
= new AllPassFilter(200.0f
, 0.68f
, sampleRate
);
125 postAllPassFilterR
= new AllPassFilter(200.0f
, 0.68f
, sampleRate
);
127 allPassFiltersL
= new AllPassFilter
*[DELAY_LINES_ALLPASS
];
128 allPassFiltersR
= new AllPassFilter
*[DELAY_LINES_ALLPASS
];
129 for (int i
= 0; i
< DELAY_LINES_ALLPASS
; i
++)
131 allPassFiltersL
[i
] = new AllPassFilter(reflectionDelays
[i
+ DELAY_LINES_COMB
- 1] * 0.105f
, 0.68f
, sampleRate
);
132 allPassFiltersR
[i
] = new AllPassFilter(reflectionDelays
[i
+ DELAY_LINES_COMB
- 1] * 0.1f
, 0.68f
, sampleRate
);
135 talEqL
= new TalEq(sampleRate
);
136 talEqR
= new TalEq(sampleRate
);
140 modulationIntensity
= 0.12f
;
149 delete[] reflectionGains
;
150 delete[] reflectionDelays
;
152 delete combFiltersPreDelayL
;
153 delete combFiltersPreDelayR
;
155 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete combFiltersL
[i
];
156 delete[] combFiltersL
;
157 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete combFiltersR
[i
];
158 delete[] combFiltersR
;
160 for (int i
= 0; i
< DELAY_LINES_ALLPASS
; i
++) delete allPassFiltersL
[i
];
161 delete[] allPassFiltersL
;
162 for (int i
= 0; i
< DELAY_LINES_ALLPASS
; i
++) delete allPassFiltersR
[i
];
163 delete[] allPassFiltersR
;
165 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete noiseGeneratorAllPassL
[i
];
166 delete[] noiseGeneratorAllPassL
;
167 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete noiseGeneratorAllPassR
[i
];
168 delete[] noiseGeneratorAllPassR
;
169 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete noiseGeneratorDelayL
[i
];
170 delete[] noiseGeneratorDelayL
;
171 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete noiseGeneratorDelayR
[i
];
172 delete[] noiseGeneratorDelayR
;
174 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete diffusionL
[i
];
176 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++) delete diffusionR
[i
];
179 delete preAllPassFilterL
;
180 delete preAllPassFilterR
;
182 delete postAllPassFilterL
;
183 delete postAllPassFilterR
;
190 void setDecayTime(float decayTime
)
192 this->decayTime
= audioUtils
.getLogScaledValueInverted(decayTime
) * 0.99f
;
195 void setPreDelay(float preDelayTime
)
197 this->preDelayTime
= audioUtils
.getLogScaledValue(preDelayTime
);
200 void setStereoMode(bool stereoMode
)
202 this->stereoMode
= stereoMode
;
205 void setLowShelfGain(float lowShelfGain
)
207 talEqL
->setLowShelfGain(lowShelfGain
);
208 talEqR
->setLowShelfGain(lowShelfGain
);
211 void setHighShelfGain(float highShelfGain
)
213 talEqL
->setHighShelfGain(highShelfGain
);
214 talEqR
->setHighShelfGain(highShelfGain
);
217 void setLowShelfFrequency(float lowShelfFrequency
)
219 talEqL
->setLowShelfFrequency(lowShelfFrequency
);
220 talEqR
->setLowShelfFrequency(lowShelfFrequency
);
223 void setHighShelfFrequency(float highShelfFrequency
)
225 talEqL
->setHighShelfFrequency(highShelfFrequency
);
226 talEqR
->setHighShelfFrequency(highShelfFrequency
);
229 void setPeakFrequency(float peakFrequency
)
231 talEqL
->setPeakFrequency(peakFrequency
);
232 talEqR
->setPeakFrequency(peakFrequency
);
235 void setPeakGain(float peakGain
)
237 talEqL
->setPeakGain(peakGain
);
238 talEqR
->setPeakGain(peakGain
);
241 // All input values [0..1]
242 inline void process(float* sampleL
, float* sampleR
)
249 revL
= (*sampleL
+ *sampleR
) * 0.25f
;
250 revL
= combFiltersPreDelayL
->process(revL
, 0.0f
, 0.0f
, preDelayTime
);
251 talEqL
->process(&revL
);
256 revL
= combFiltersPreDelayL
->process(*sampleL
* 0.5f
, 0.0f
, 0.0f
, preDelayTime
);
257 revR
= combFiltersPreDelayL
->process(*sampleR
* 0.5f
, 0.0f
, 0.0f
, preDelayTime
);
258 talEqL
->process(&revL
);
259 talEqR
->process(&revR
);
262 // ----------------- Comb Filter --------------------
266 float scaledRoomSize
= decayTime
* 0.998f
;
268 for (int i
= 0; i
< DELAY_LINES_COMB
; i
++)
270 outL
+= sign
* combFiltersL
[i
]->processInterpolated(revL
, diffusionL
[i
]->tickFilteredNoiseFast() * 0.2f
, scaledRoomSize
, scaledRoomSize
+ 0.012f
* noiseGeneratorDelayL
[i
]->tickFilteredNoise());
271 outR
+= sign
* combFiltersR
[i
]->processInterpolated(revR
, diffusionR
[i
]->tickFilteredNoiseFast() * 0.2f
, scaledRoomSize
, scaledRoomSize
+ 0.012f
* noiseGeneratorDelayR
[i
]->tickFilteredNoise());
275 // ----------------- Pre AllPass --------------------
276 outL
+= 0.5f
* preAllPassFilterL
->processInterpolated(revR
, 0.6f
+ 0.4f
* noiseGeneratorAllPassL
[0]->tickFilteredNoise(), 0.99f
, true);
277 outR
+= 0.5f
* preAllPassFilterR
->processInterpolated(revL
, 0.6f
+ 0.4f
* noiseGeneratorAllPassR
[0]->tickFilteredNoise(), 0.99f
, true);
279 //// ----------------- Post AllPass --------------------
280 outL
+= 0.45f
* postAllPassFilterL
->processInterpolated(revL
, 0.8f
+ 0.2f
* noiseGeneratorAllPassL
[1]->tickFilteredNoise(), 0.7f
, true);
281 outR
+= 0.45f
* postAllPassFilterR
->processInterpolated(revR
, 0.8f
+ 0.2f
* noiseGeneratorAllPassR
[1]->tickFilteredNoise(), 0.7f
, true);
283 // ----------------- AllPass Filter ------------------
284 for (int i
= 0; i
< DELAY_LINES_ALLPASS
; i
++)
286 outL
= allPassFiltersL
[i
]->process(outL
);
287 outR
= allPassFiltersR
[i
]->process(outR
);
290 // ----------------- Write to output / Stereo --------
295 void createDelaysAndCoefficients(int numlines
, float delayLength
)
297 reflectionDelays
= new float[numlines
];
298 reflectionGains
= new float[numlines
];
300 float volumeScale
= (float)(-3.0 * delayLength
/ log10f(0.5f
));
301 for (int n
= numlines
- 1; n
>= 0; n
--)
303 reflectionDelays
[numlines
-1 - n
] = delayLength
/ powf(2.0f
, (float)n
/ numlines
);
304 reflectionGains
[numlines
-1 - n
] = powf(10.0f
, - (3.0f
* reflectionDelays
[numlines
-1 - n
]) / volumeScale
);