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