Mercurial > hg > audio_effects_textbook_code
comparison effects/reverb/Source/MVerb.h @ 0:e32fe563e124
First commit
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Fri, 10 Oct 2014 15:41:23 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e32fe563e124 |
---|---|
1 // Copyright (c) 2010 Martin Eastwood | |
2 // This code is distributed under the terms of the GNU General Public License | |
3 | |
4 // MVerb is free software: you can redistribute it and/or modify | |
5 // it under the terms of the GNU General Public License as published by | |
6 // the Free Software Foundation, either version 3 of the License, or | |
7 // at your option) any later version. | |
8 // | |
9 // MVerb is distributed in the hope that it will be useful, | |
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 // GNU General Public License for more details. | |
13 // | |
14 // You should have received a copy of the GNU General Public License | |
15 // along with this MVerb. If not, see <http://www.gnu.org/licenses/>. | |
16 | |
17 #ifndef EMVERB_H | |
18 #define EMVERB_H | |
19 | |
20 //forward declaration | |
21 template<typename T, int maxLength> class Allpass; | |
22 template<typename T, int maxLength> class StaticAllpassFourTap; | |
23 template<typename T, int maxLength> class StaticDelayLine; | |
24 template<typename T, int maxLength> class StaticDelayLineFourTap; | |
25 template<typename T, int maxLength> class StaticDelayLineEightTap; | |
26 template<typename T, int OverSampleCount> class StateVariable; | |
27 | |
28 template<typename T> | |
29 class MVerb | |
30 { | |
31 private: | |
32 Allpass<T, 96000> allpass[4]; | |
33 StaticAllpassFourTap<T, 96000> allpassFourTap[4]; | |
34 StateVariable<T,4> bandwidthFilter[2]; | |
35 StateVariable<T,4> damping[2]; | |
36 StaticDelayLine<T, 96000> predelay; | |
37 StaticDelayLineFourTap<T, 96000> staticDelayLine[4]; | |
38 StaticDelayLineEightTap<T, 96000> earlyReflectionsDelayLine[2]; | |
39 T SampleRate, DampingFreq, Density1, Density2, BandwidthFreq, PreDelayTime, Decay, Gain, Mix, EarlyMix, Size; | |
40 T MixSmooth, EarlyLateSmooth, BandwidthSmooth, DampingSmooth, PredelaySmooth, SizeSmooth, DensitySmooth, DecaySmooth; | |
41 T PreviousLeftTank, PreviousRightTank; | |
42 int ControlRate, ControlRateCounter; | |
43 | |
44 public: | |
45 enum | |
46 { | |
47 DAMPINGFREQ=0, | |
48 DENSITY, | |
49 BANDWIDTHFREQ, | |
50 DECAY, | |
51 PREDELAY, | |
52 SIZE, | |
53 GAIN, | |
54 MIX, | |
55 EARLYMIX, | |
56 NUM_PARAMS | |
57 }; | |
58 | |
59 MVerb(){ | |
60 setParameter (DAMPINGFREQ, 0.0); | |
61 setParameter (DENSITY, 0.5); | |
62 setParameter (BANDWIDTHFREQ, 1.0); | |
63 setParameter (DECAY, 0.5); | |
64 setParameter (PREDELAY, 0.0); | |
65 setParameter (SIZE, 0.5); | |
66 setParameter (GAIN, 1.0); | |
67 setParameter (MIX, 0.15); | |
68 setParameter (EARLYMIX, 0.75); | |
69 | |
70 SampleRate = 44100.; | |
71 PreviousLeftTank = 0.; | |
72 PreviousRightTank = 0.; | |
73 PreDelayTime = 100 * (SampleRate / 1000); | |
74 MixSmooth = EarlyLateSmooth = BandwidthSmooth = DampingSmooth = PredelaySmooth = SizeSmooth = DecaySmooth = DensitySmooth = 0.; | |
75 ControlRate = SampleRate / 1000; | |
76 ControlRateCounter = 0; | |
77 reset(); | |
78 } | |
79 | |
80 ~MVerb(){ | |
81 //nowt to do here | |
82 } | |
83 | |
84 void process(T **inputs, T **outputs, int sampleFrames){ | |
85 T OneOverSampleFrames = 1. / sampleFrames; | |
86 T MixDelta = (Mix - MixSmooth) * OneOverSampleFrames; | |
87 T EarlyLateDelta = (EarlyMix - EarlyLateSmooth) * OneOverSampleFrames; | |
88 T BandwidthDelta = (((BandwidthFreq * 18400.) + 100.) - BandwidthSmooth) * OneOverSampleFrames; | |
89 T DampingDelta = (((DampingFreq * 18400.) + 100.) - DampingSmooth) * OneOverSampleFrames; | |
90 T PredelayDelta = ((PreDelayTime * 200 * (SampleRate / 1000)) - PredelaySmooth) * OneOverSampleFrames; | |
91 T SizeDelta = (Size - SizeSmooth) * OneOverSampleFrames; | |
92 T DecayDelta = (((0.7995f * Decay) + 0.005) - DecaySmooth) * OneOverSampleFrames; | |
93 T DensityDelta = (((0.7995f * Density1) + 0.005) - DensitySmooth) * OneOverSampleFrames; | |
94 for(int i=0;i<sampleFrames;++i){ | |
95 T left = inputs[0][i]; | |
96 T right = inputs[1][i]; | |
97 MixSmooth += MixDelta; | |
98 EarlyLateSmooth += EarlyLateDelta; | |
99 BandwidthSmooth += BandwidthDelta; | |
100 DampingSmooth += DampingDelta; | |
101 PredelaySmooth += PredelayDelta; | |
102 SizeSmooth += SizeDelta; | |
103 DecaySmooth += DecayDelta; | |
104 DensitySmooth += DensityDelta; | |
105 if (ControlRateCounter >= ControlRate){ | |
106 ControlRateCounter = 0; | |
107 bandwidthFilter[0].Frequency(BandwidthSmooth); | |
108 bandwidthFilter[1].Frequency(BandwidthSmooth); | |
109 damping[0].Frequency(DampingSmooth); | |
110 damping[1].Frequency(DampingSmooth); | |
111 } | |
112 ++ControlRateCounter; | |
113 predelay.SetLength(PredelaySmooth); | |
114 Density2 = DecaySmooth + 0.15; | |
115 if (Density2 > 0.5) | |
116 Density2 = 0.5; | |
117 if (Density2 < 0.25) | |
118 Density2 = 0.25; | |
119 allpassFourTap[1].SetFeedback(Density2); | |
120 allpassFourTap[3].SetFeedback(Density2); | |
121 allpassFourTap[0].SetFeedback(Density1); | |
122 allpassFourTap[2].SetFeedback(Density1); | |
123 T bandwidthLeft = bandwidthFilter[0](left) ; | |
124 T bandwidthRight = bandwidthFilter[1](right) ; | |
125 T earlyReflectionsL = earlyReflectionsDelayLine[0] ( bandwidthLeft * 0.5 + bandwidthRight * 0.3 ) | |
126 + earlyReflectionsDelayLine[0].GetIndex(2) * 0.6 | |
127 + earlyReflectionsDelayLine[0].GetIndex(3) * 0.4 | |
128 + earlyReflectionsDelayLine[0].GetIndex(4) * 0.3 | |
129 + earlyReflectionsDelayLine[0].GetIndex(5) * 0.3 | |
130 + earlyReflectionsDelayLine[0].GetIndex(6) * 0.1 | |
131 + earlyReflectionsDelayLine[0].GetIndex(7) * 0.1 | |
132 + ( bandwidthLeft * 0.4 + bandwidthRight * 0.2 ) * 0.5 ; | |
133 T earlyReflectionsR = earlyReflectionsDelayLine[1] ( bandwidthLeft * 0.3 + bandwidthRight * 0.5 ) | |
134 + earlyReflectionsDelayLine[1].GetIndex(2) * 0.6 | |
135 + earlyReflectionsDelayLine[1].GetIndex(3) * 0.4 | |
136 + earlyReflectionsDelayLine[1].GetIndex(4) * 0.3 | |
137 + earlyReflectionsDelayLine[1].GetIndex(5) * 0.3 | |
138 + earlyReflectionsDelayLine[1].GetIndex(6) * 0.1 | |
139 + earlyReflectionsDelayLine[1].GetIndex(7) * 0.1 | |
140 + ( bandwidthLeft * 0.2 + bandwidthRight * 0.4 ) * 0.5 ; | |
141 T predelayMonoInput = predelay(( bandwidthRight + bandwidthLeft ) * 0.5f); | |
142 T smearedInput = predelayMonoInput; | |
143 for(int j=0;j<4;j++) | |
144 smearedInput = allpass[j] ( smearedInput ); | |
145 T leftTank = allpassFourTap[0] ( smearedInput + PreviousRightTank ) ; | |
146 leftTank = staticDelayLine[0] (leftTank); | |
147 leftTank = damping[0](leftTank); | |
148 leftTank = allpassFourTap[1](leftTank); | |
149 leftTank = staticDelayLine[1](leftTank); | |
150 T rightTank = allpassFourTap[2] (smearedInput + PreviousLeftTank) ; | |
151 rightTank = staticDelayLine[2](rightTank); | |
152 rightTank = damping[1] (rightTank); | |
153 rightTank = allpassFourTap[3](rightTank); | |
154 rightTank = staticDelayLine[3](rightTank); | |
155 PreviousLeftTank = leftTank * DecaySmooth; | |
156 PreviousRightTank = rightTank * DecaySmooth; | |
157 T accumulatorL = (0.6*staticDelayLine[2].GetIndex(1)) | |
158 +(0.6*staticDelayLine[2].GetIndex(2)) | |
159 -(0.6*allpassFourTap[3].GetIndex(1)) | |
160 +(0.6*staticDelayLine[3].GetIndex(1)) | |
161 -(0.6*staticDelayLine[0].GetIndex(1)) | |
162 -(0.6*allpassFourTap[1].GetIndex(1)) | |
163 -(0.6*staticDelayLine[1].GetIndex(1)); | |
164 T accumulatorR = (0.6*staticDelayLine[0].GetIndex(2)) | |
165 +(0.6*staticDelayLine[0].GetIndex(3)) | |
166 -(0.6*allpassFourTap[1].GetIndex(2)) | |
167 +(0.6*staticDelayLine[1].GetIndex(2)) | |
168 -(0.6*staticDelayLine[2].GetIndex(3)) | |
169 -(0.6*allpassFourTap[3].GetIndex(2)) | |
170 -(0.6*staticDelayLine[3].GetIndex(2)); | |
171 accumulatorL = ((accumulatorL * EarlyMix) + ((1 - EarlyMix) * earlyReflectionsL)); | |
172 accumulatorR = ((accumulatorR * EarlyMix) + ((1 - EarlyMix) * earlyReflectionsR)); | |
173 left = ( left + MixSmooth * ( accumulatorL - left ) ) * Gain; | |
174 right = ( right + MixSmooth * ( accumulatorR - right ) ) * Gain; | |
175 outputs[0][i] = left; | |
176 outputs[1][i] = right; | |
177 } | |
178 } | |
179 | |
180 void reset(){ | |
181 ControlRateCounter = 0; | |
182 bandwidthFilter[0].SetSampleRate (SampleRate ); | |
183 bandwidthFilter[1].SetSampleRate (SampleRate ); | |
184 bandwidthFilter[0].Reset(); | |
185 bandwidthFilter[1].Reset(); | |
186 damping[0].SetSampleRate (SampleRate ); | |
187 damping[1].SetSampleRate (SampleRate ); | |
188 damping[0].Reset(); | |
189 damping[1].Reset(); | |
190 predelay.Clear(); | |
191 predelay.SetLength(PreDelayTime); | |
192 allpass[0].Clear(); | |
193 allpass[1].Clear(); | |
194 allpass[2].Clear(); | |
195 allpass[3].Clear(); | |
196 allpass[0].SetLength (0.0048 * SampleRate); | |
197 allpass[1].SetLength (0.0036 * SampleRate); | |
198 allpass[2].SetLength (0.0127 * SampleRate); | |
199 allpass[3].SetLength (0.0093 * SampleRate); | |
200 allpass[0].SetFeedback (0.75); | |
201 allpass[1].SetFeedback (0.75); | |
202 allpass[2].SetFeedback (0.625); | |
203 allpass[3].SetFeedback (0.625); | |
204 allpassFourTap[0].Clear(); | |
205 allpassFourTap[1].Clear(); | |
206 allpassFourTap[2].Clear(); | |
207 allpassFourTap[3].Clear(); | |
208 allpassFourTap[0].SetLength(0.020 * SampleRate * Size); | |
209 allpassFourTap[1].SetLength(0.060 * SampleRate * Size); | |
210 allpassFourTap[2].SetLength(0.030 * SampleRate * Size); | |
211 allpassFourTap[3].SetLength(0.089 * SampleRate * Size); | |
212 allpassFourTap[0].SetFeedback(Density1); | |
213 allpassFourTap[1].SetFeedback(Density2); | |
214 allpassFourTap[2].SetFeedback(Density1); | |
215 allpassFourTap[3].SetFeedback(Density2); | |
216 allpassFourTap[0].SetIndex(0,0,0,0); | |
217 allpassFourTap[1].SetIndex(0,0.006 * SampleRate * Size, 0.041 * SampleRate * Size, 0); | |
218 allpassFourTap[2].SetIndex(0,0,0,0); | |
219 allpassFourTap[3].SetIndex(0,0.031 * SampleRate * Size, 0.011 * SampleRate * Size, 0); | |
220 staticDelayLine[0].Clear(); | |
221 staticDelayLine[1].Clear(); | |
222 staticDelayLine[2].Clear(); | |
223 staticDelayLine[3].Clear(); | |
224 staticDelayLine[0].SetLength(0.15 * SampleRate * Size); | |
225 staticDelayLine[1].SetLength(0.12 * SampleRate * Size); | |
226 staticDelayLine[2].SetLength(0.14 * SampleRate * Size); | |
227 staticDelayLine[3].SetLength(0.11 * SampleRate * Size); | |
228 staticDelayLine[0].SetIndex(0, 0.067 * SampleRate * Size, 0.011 * SampleRate * Size , 0.121 * SampleRate * Size); | |
229 staticDelayLine[1].SetIndex(0, 0.036 * SampleRate * Size, 0.089 * SampleRate * Size , 0); | |
230 staticDelayLine[2].SetIndex(0, 0.0089 * SampleRate * Size, 0.099 * SampleRate * Size , 0); | |
231 staticDelayLine[3].SetIndex(0, 0.067 * SampleRate * Size, 0.0041 * SampleRate * Size , 0); | |
232 earlyReflectionsDelayLine[0].Clear(); | |
233 earlyReflectionsDelayLine[1].Clear(); | |
234 earlyReflectionsDelayLine[0].SetLength(0.089 * SampleRate); | |
235 earlyReflectionsDelayLine[0].SetIndex (0, 0.0199*SampleRate, 0.0219*SampleRate, 0.0354*SampleRate,0.0389*SampleRate, 0.0414*SampleRate, 0.0692*SampleRate, 0); | |
236 earlyReflectionsDelayLine[1].SetLength(0.069 * SampleRate); | |
237 earlyReflectionsDelayLine[1].SetIndex (0, 0.0099*SampleRate, 0.011*SampleRate, 0.0182*SampleRate,0.0189*SampleRate, 0.0213*SampleRate, 0.0431*SampleRate, 0); | |
238 } | |
239 | |
240 void setParameter(int index, T value){ | |
241 switch(index){ | |
242 case DAMPINGFREQ: | |
243 DampingFreq = 1. - value; | |
244 break; | |
245 case DENSITY: | |
246 Density1 = value; | |
247 break; | |
248 case BANDWIDTHFREQ: | |
249 BandwidthFreq = value; | |
250 break; | |
251 case PREDELAY: | |
252 PreDelayTime = value; | |
253 break; | |
254 case SIZE: | |
255 Size = (0.95 * value) + 0.05; | |
256 allpassFourTap[0].Clear(); | |
257 allpassFourTap[1].Clear(); | |
258 allpassFourTap[2].Clear(); | |
259 allpassFourTap[3].Clear(); | |
260 allpassFourTap[0].SetLength(0.020 * SampleRate * Size); | |
261 allpassFourTap[1].SetLength(0.060 * SampleRate * Size); | |
262 allpassFourTap[2].SetLength(0.030 * SampleRate * Size); | |
263 allpassFourTap[3].SetLength(0.089 * SampleRate * Size); | |
264 allpassFourTap[1].SetIndex(0,0.006 * SampleRate * Size, 0.041 * SampleRate * Size, 0); | |
265 allpassFourTap[3].SetIndex(0,0.031 * SampleRate * Size, 0.011 * SampleRate * Size, 0); | |
266 staticDelayLine[0].Clear(); | |
267 staticDelayLine[1].Clear(); | |
268 staticDelayLine[2].Clear(); | |
269 staticDelayLine[3].Clear(); | |
270 staticDelayLine[0].SetLength(0.15 * SampleRate * Size); | |
271 staticDelayLine[1].SetLength(0.12 * SampleRate * Size); | |
272 staticDelayLine[2].SetLength(0.14 * SampleRate * Size); | |
273 staticDelayLine[3].SetLength(0.11 * SampleRate * Size); | |
274 staticDelayLine[0].SetIndex(0, 0.067 * SampleRate * Size, 0.011 * SampleRate * Size , 0.121 * SampleRate * Size); | |
275 staticDelayLine[1].SetIndex(0, 0.036 * SampleRate * Size, 0.089 * SampleRate * Size , 0); | |
276 staticDelayLine[2].SetIndex(0, 0.0089 * SampleRate * Size, 0.099 * SampleRate * Size , 0); | |
277 staticDelayLine[3].SetIndex(0, 0.067 * SampleRate * Size, 0.0041 * SampleRate * Size , 0); | |
278 break; | |
279 case DECAY: | |
280 Decay = value; | |
281 break; | |
282 case GAIN: | |
283 Gain = value; | |
284 break; | |
285 case MIX: | |
286 Mix = value; | |
287 break; | |
288 case EARLYMIX: | |
289 EarlyMix = value; | |
290 break; | |
291 } | |
292 } | |
293 | |
294 float getParameter(int index){ | |
295 switch(index){ | |
296 case DAMPINGFREQ: | |
297 return DampingFreq * 100.; | |
298 break; | |
299 case DENSITY: | |
300 return Density1 * 100.f; | |
301 break; | |
302 case BANDWIDTHFREQ: | |
303 return BandwidthFreq * 100.; | |
304 break; | |
305 case PREDELAY: | |
306 return PreDelayTime * 100.; | |
307 break; | |
308 case SIZE: | |
309 return (((0.95 * Size) + 0.05)*100.); | |
310 break; | |
311 case DECAY: | |
312 return Decay * 100.f; | |
313 break; | |
314 case GAIN: | |
315 return Gain * 100.f; | |
316 break; | |
317 case MIX: | |
318 return Mix * 100.f; | |
319 break; | |
320 case EARLYMIX: | |
321 return EarlyMix * 100.f; | |
322 break; | |
323 default: return 0.f; | |
324 break; | |
325 | |
326 } | |
327 } | |
328 | |
329 void setSampleRate(T sr){ | |
330 SampleRate = sr; | |
331 ControlRate = SampleRate / 1000; | |
332 reset(); | |
333 } | |
334 }; | |
335 | |
336 | |
337 | |
338 template<typename T, int maxLength> | |
339 class Allpass | |
340 { | |
341 private: | |
342 T buffer[maxLength]; | |
343 int index; | |
344 int Length; | |
345 T Feedback; | |
346 | |
347 public: | |
348 Allpass() | |
349 { | |
350 SetLength ( maxLength - 1 ); | |
351 Clear(); | |
352 Feedback = 0.5; | |
353 } | |
354 | |
355 T operator()(T input) | |
356 { | |
357 T output; | |
358 T bufout; | |
359 bufout = buffer[index]; | |
360 T temp = input * -Feedback; | |
361 output = bufout + temp; | |
362 buffer[index] = input + ((bufout+temp)*Feedback); | |
363 if(++index>=Length) index = 0; | |
364 return output; | |
365 | |
366 } | |
367 | |
368 void SetLength (int Length) | |
369 { | |
370 if( Length >= maxLength ) | |
371 Length = maxLength; | |
372 if( Length < 0 ) | |
373 Length = 0; | |
374 | |
375 this->Length = Length; | |
376 } | |
377 | |
378 void SetFeedback(T feedback) | |
379 { | |
380 Feedback = feedback; | |
381 } | |
382 | |
383 void Clear() | |
384 { | |
385 memset(buffer, 0, sizeof(buffer)); | |
386 index = 0; | |
387 } | |
388 | |
389 int GetLength() const | |
390 { | |
391 return Length; | |
392 } | |
393 }; | |
394 | |
395 template<typename T, int maxLength> | |
396 class StaticAllpassFourTap | |
397 { | |
398 private: | |
399 T buffer[maxLength]; | |
400 int index1, index2, index3, index4; | |
401 int Length; | |
402 T Feedback; | |
403 | |
404 public: | |
405 StaticAllpassFourTap() | |
406 { | |
407 SetLength ( maxLength - 1 ); | |
408 Clear(); | |
409 Feedback = 0.5; | |
410 } | |
411 | |
412 T operator()(T input) | |
413 { | |
414 T output; | |
415 T bufout; | |
416 | |
417 bufout = buffer[index1]; | |
418 T temp = input * -Feedback; | |
419 output = bufout + temp; | |
420 buffer[index1] = input + ((bufout+temp)*Feedback); | |
421 | |
422 if(++index1>=Length) | |
423 index1 = 0; | |
424 if(++index2 >= Length) | |
425 index2 = 0; | |
426 if(++index3 >= Length) | |
427 index3 = 0; | |
428 if(++index4 >= Length) | |
429 index4 = 0; | |
430 | |
431 return output; | |
432 | |
433 } | |
434 | |
435 void SetIndex (int Index1, int Index2, int Index3, int Index4) | |
436 { | |
437 index1 = Index1; | |
438 index2 = Index2; | |
439 index3 = Index3; | |
440 index4 = Index4; | |
441 } | |
442 | |
443 T GetIndex (int Index) | |
444 { | |
445 switch (Index) | |
446 { | |
447 case 0: | |
448 return buffer[index1]; | |
449 break; | |
450 case 1: | |
451 return buffer[index2]; | |
452 break; | |
453 case 2: | |
454 return buffer[index3]; | |
455 break; | |
456 case 3: | |
457 return buffer[index4]; | |
458 break; | |
459 default: | |
460 return buffer[index1]; | |
461 break; | |
462 } | |
463 } | |
464 | |
465 void SetLength (int Length) | |
466 { | |
467 if( Length >= maxLength ) | |
468 Length = maxLength; | |
469 if( Length < 0 ) | |
470 Length = 0; | |
471 | |
472 this->Length = Length; | |
473 } | |
474 | |
475 | |
476 void Clear() | |
477 { | |
478 memset(buffer, 0, sizeof(buffer)); | |
479 index1 = index2 = index3 = index4 = 0; | |
480 } | |
481 | |
482 void SetFeedback(T feedback) | |
483 { | |
484 Feedback = feedback; | |
485 } | |
486 | |
487 | |
488 int GetLength() const | |
489 { | |
490 return Length; | |
491 } | |
492 }; | |
493 | |
494 template<typename T, int maxLength> | |
495 class StaticDelayLine | |
496 { | |
497 private: | |
498 T buffer[maxLength]; | |
499 int index; | |
500 int Length; | |
501 T Feedback; | |
502 | |
503 public: | |
504 StaticDelayLine() | |
505 { | |
506 SetLength ( maxLength - 1 ); | |
507 Clear(); | |
508 } | |
509 | |
510 T operator()(T input) | |
511 { | |
512 T output = buffer[index]; | |
513 buffer[index++] = input; | |
514 if(index >= Length) | |
515 index = 0; | |
516 return output; | |
517 | |
518 } | |
519 | |
520 void SetLength (int Length) | |
521 { | |
522 if( Length >= maxLength ) | |
523 Length = maxLength; | |
524 if( Length < 0 ) | |
525 Length = 0; | |
526 | |
527 this->Length = Length; | |
528 } | |
529 | |
530 void Clear() | |
531 { | |
532 memset(buffer, 0, sizeof(buffer)); | |
533 index = 0; | |
534 } | |
535 | |
536 int GetLength() const | |
537 { | |
538 return Length; | |
539 } | |
540 }; | |
541 | |
542 template<typename T, int maxLength> | |
543 class StaticDelayLineFourTap | |
544 { | |
545 private: | |
546 T buffer[maxLength]; | |
547 int index1, index2, index3, index4; | |
548 int Length; | |
549 T Feedback; | |
550 | |
551 public: | |
552 StaticDelayLineFourTap() | |
553 { | |
554 SetLength ( maxLength - 1 ); | |
555 Clear(); | |
556 } | |
557 | |
558 //get ouput and iterate | |
559 T operator()(T input) | |
560 { | |
561 T output = buffer[index1]; | |
562 buffer[index1++] = input; | |
563 if(index1 >= Length) | |
564 index1 = 0; | |
565 if(++index2 >= Length) | |
566 index2 = 0; | |
567 if(++index3 >= Length) | |
568 index3 = 0; | |
569 if(++index4 >= Length) | |
570 index4 = 0; | |
571 return output; | |
572 | |
573 } | |
574 | |
575 void SetIndex (int Index1, int Index2, int Index3, int Index4) | |
576 { | |
577 index1 = Index1; | |
578 index2 = Index2; | |
579 index3 = Index3; | |
580 index4 = Index4; | |
581 } | |
582 | |
583 | |
584 T GetIndex (int Index) | |
585 { | |
586 switch (Index) | |
587 { | |
588 case 0: | |
589 return buffer[index1]; | |
590 break; | |
591 case 1: | |
592 return buffer[index2]; | |
593 break; | |
594 case 2: | |
595 return buffer[index3]; | |
596 break; | |
597 case 3: | |
598 return buffer[index4]; | |
599 break; | |
600 default: | |
601 return buffer[index1]; | |
602 break; | |
603 } | |
604 } | |
605 | |
606 | |
607 void SetLength (int Length) | |
608 { | |
609 if( Length >= maxLength ) | |
610 Length = maxLength; | |
611 if( Length < 0 ) | |
612 Length = 0; | |
613 | |
614 this->Length = Length; | |
615 } | |
616 | |
617 | |
618 void Clear() | |
619 { | |
620 memset(buffer, 0, sizeof(buffer)); | |
621 index1 = index2 = index3 = index4 = 0; | |
622 } | |
623 | |
624 | |
625 int GetLength() const | |
626 { | |
627 return Length; | |
628 } | |
629 }; | |
630 | |
631 template<typename T, int maxLength> | |
632 class StaticDelayLineEightTap | |
633 { | |
634 private: | |
635 T buffer[maxLength]; | |
636 int index1, index2, index3, index4, index5, index6, index7, index8; | |
637 int Length; | |
638 T Feedback; | |
639 | |
640 public: | |
641 StaticDelayLineEightTap() | |
642 { | |
643 SetLength ( maxLength - 1 ); | |
644 Clear(); | |
645 } | |
646 | |
647 //get ouput and iterate | |
648 T operator()(T input) | |
649 { | |
650 T output = buffer[index1]; | |
651 buffer[index1++] = input; | |
652 if(index1 >= Length) | |
653 index1 = 0; | |
654 if(++index2 >= Length) | |
655 index2 = 0; | |
656 if(++index3 >= Length) | |
657 index3 = 0; | |
658 if(++index4 >= Length) | |
659 index4 = 0; | |
660 if(++index5 >= Length) | |
661 index5 = 0; | |
662 if(++index6 >= Length) | |
663 index6 = 0; | |
664 if(++index7 >= Length) | |
665 index7 = 0; | |
666 if(++index8 >= Length) | |
667 index8 = 0; | |
668 return output; | |
669 | |
670 } | |
671 | |
672 void SetIndex (int Index1, int Index2, int Index3, int Index4, int Index5, int Index6, int Index7, int Index8) | |
673 { | |
674 index1 = Index1; | |
675 index2 = Index2; | |
676 index3 = Index3; | |
677 index4 = Index4; | |
678 index5 = Index5; | |
679 index6 = Index6; | |
680 index7 = Index7; | |
681 index8 = Index8; | |
682 } | |
683 | |
684 | |
685 T GetIndex (int Index) | |
686 { | |
687 switch (Index) | |
688 { | |
689 case 0: | |
690 return buffer[index1]; | |
691 break; | |
692 case 1: | |
693 return buffer[index2]; | |
694 break; | |
695 case 2: | |
696 return buffer[index3]; | |
697 break; | |
698 case 3: | |
699 return buffer[index4]; | |
700 break; | |
701 case 4: | |
702 return buffer[index5]; | |
703 break; | |
704 case 5: | |
705 return buffer[index6]; | |
706 break; | |
707 case 6: | |
708 return buffer[index7]; | |
709 break; | |
710 case 7: | |
711 return buffer[index8]; | |
712 break; | |
713 default: | |
714 return buffer[index1]; | |
715 break; | |
716 } | |
717 } | |
718 | |
719 | |
720 void SetLength (int Length) | |
721 { | |
722 if( Length >= maxLength ) | |
723 Length = maxLength; | |
724 if( Length < 0 ) | |
725 Length = 0; | |
726 | |
727 this->Length = Length; | |
728 } | |
729 | |
730 | |
731 void Clear() | |
732 { | |
733 memset(buffer, 0, sizeof(buffer)); | |
734 index1 = index2 = index3 = index4 = index5 = index6 = index7 = index8 = 0; | |
735 } | |
736 | |
737 | |
738 int GetLength() const | |
739 { | |
740 return Length; | |
741 } | |
742 }; | |
743 | |
744 template<typename T, int OverSampleCount> | |
745 class StateVariable | |
746 { | |
747 public: | |
748 | |
749 enum FilterType | |
750 { | |
751 LOWPASS, | |
752 HIGHPASS, | |
753 BANDPASS, | |
754 NOTCH, | |
755 FilterTypeCount | |
756 }; | |
757 | |
758 private: | |
759 | |
760 T sampleRate; | |
761 T frequency; | |
762 T q; | |
763 T f; | |
764 | |
765 T low; | |
766 T high; | |
767 T band; | |
768 T notch; | |
769 | |
770 T *out; | |
771 | |
772 public: | |
773 StateVariable() | |
774 { | |
775 SetSampleRate(44100.); | |
776 Frequency(1000.); | |
777 Resonance(0); | |
778 Type(LOWPASS); | |
779 Reset(); | |
780 } | |
781 | |
782 T operator()(T input) | |
783 { | |
784 for(unsigned int i = 0; i < OverSampleCount; i++) | |
785 { | |
786 low += f * band + 1e-25; | |
787 high = input - low - q * band; | |
788 band += f * high; | |
789 notch = low + high; | |
790 } | |
791 return *out; | |
792 } | |
793 | |
794 void Reset() | |
795 { | |
796 low = high = band = notch = 0; | |
797 } | |
798 | |
799 void SetSampleRate(T sampleRate) | |
800 { | |
801 this->sampleRate = sampleRate * OverSampleCount; | |
802 UpdateCoefficient(); | |
803 } | |
804 | |
805 void Frequency(T frequency) | |
806 { | |
807 this->frequency = frequency; | |
808 UpdateCoefficient(); | |
809 } | |
810 | |
811 void Resonance(T resonance) | |
812 { | |
813 this->q = 2 - 2 * resonance; | |
814 } | |
815 | |
816 void Type(int type) | |
817 { | |
818 switch(type) | |
819 { | |
820 case LOWPASS: | |
821 out = &low; | |
822 break; | |
823 | |
824 case HIGHPASS: | |
825 out = &high; | |
826 break; | |
827 | |
828 case BANDPASS: | |
829 out = &band; | |
830 break; | |
831 | |
832 case NOTCH: | |
833 out = ¬ch; | |
834 break; | |
835 | |
836 default: | |
837 out = &low; | |
838 break; | |
839 } | |
840 } | |
841 | |
842 private: | |
843 void UpdateCoefficient() | |
844 { | |
845 f = 2. * sinf(3.141592654 * frequency / sampleRate); | |
846 } | |
847 }; | |
848 #endif |