The Synthesis ToolKit in C++ (STK)

Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial

FreeVerb.h
1 #ifndef STK_FREEVERB_H
2 #define STK_FREEVERB_H
3
4 #include "Effect.h"
5 #include "Delay.h"
6 #include "OnePole.h"
7
8 namespace stk {
9
10 /***********************************************************************/
24 /***********************************************************************/
25
26 class FreeVerb : public Effect
27 {
28 public:
30
36 FreeVerb();
37
39 ~FreeVerb();
40
42 void setEffectMix( StkFloat mix );
43
45 void setRoomSize( StkFloat value );
46
48 StkFloat getRoomSize( void );
49
51 void setDamping( StkFloat value );
52
54 StkFloat getDamping( void );
55
57 void setWidth( StkFloat value );
58
60 StkFloat getWidth( void );
61
63 void setMode( bool isFrozen );
64
66 StkFloat getMode( void );
67
69 void clear( void );
70
72
80 StkFloat lastOut( unsigned int channel = 0 );
81
83
90 StkFloat tick( StkFloat inputL, StkFloat inputR = 0.0, unsigned int channel = 0 );
91
93
103 StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
104
106
117 StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
118
119 protected:
121 void update( void );
122
123 // Clamp very small floats to zero, version from
124 // http://music.columbia.edu/pipermail/linux-audio-user/2004-July/013489.html .
125 // However, this is for 32-bit floats only.
126 //static inline StkFloat undenormalize( volatile StkFloat s ) {
127 // s += 9.8607615E-32f;
128 // return s - 9.8607615E-32f;
129 //}
130
131 static const int nCombs = 8;
132 static const int nAllpasses = 4;
133 static const int stereoSpread = 23;
134 static const StkFloat fixedGain;
135 static const StkFloat scaleWet;
136 static const StkFloat scaleDry;
137 static const StkFloat scaleDamp;
138 static const StkFloat scaleRoom;
139 static const StkFloat offsetRoom;
140
141 // Delay line lengths for 44100Hz sampling rate.
142 static int cDelayLengths[nCombs];
143 static int aDelayLengths[nAllpasses];
144
145 StkFloat g_; // allpass coefficient
146 StkFloat gain_;
147 StkFloat roomSizeMem_, roomSize_;
148 StkFloat dampMem_, damp_;
149 StkFloat wet1_, wet2_;
150 StkFloat dry_;
151 StkFloat width_;
152 bool frozenMode_;
153
154 // LBFC: Lowpass Feedback Comb Filters
155 Delay combDelayL_[nCombs];
156 Delay combDelayR_[nCombs];
157 OnePole combLPL_[nCombs];
158 OnePole combLPR_[nCombs];
159
160 // AP: Allpass Filters
161 Delay allPassDelayL_[nAllpasses];
162 Delay allPassDelayR_[nAllpasses];
163 };
164
165 inline StkFloat FreeVerb :: lastOut( unsigned int channel )
166 {
167 #if defined(_STK_DEBUG_)
168 if ( channel > 1 ) {
169 oStream_ << "FreeVerb::lastOut(): channel argument must be less than 2!";
170 handleError( StkError::FUNCTION_ARGUMENT );
171 }
172 #endif
173
174 return lastFrame_[channel];
175 }
176
177 inline StkFloat FreeVerb::tick( StkFloat inputL, StkFloat inputR, unsigned int channel )
178 {
179 #if defined(_STK_DEBUG_)
180 if ( channel > 1 ) {
181 oStream_ << "FreeVerb::tick(): channel argument must be less than 2!";
182 handleError(StkError::FUNCTION_ARGUMENT);
183 }
184 #endif
185
186 StkFloat fInput = (inputL + inputR) * gain_;
187 StkFloat outL = 0.0;
188 StkFloat outR = 0.0;
189
190 // Parallel LBCF filters
191 for ( int i = 0; i < nCombs; i++ ) {
192 // Left channel
193 //StkFloat yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPL_[i].tick(FreeVerb::undenormalize(combDelayL_[i].nextOut()))));
194 StkFloat yn = fInput + (roomSize_ * combLPL_[i].tick( combDelayL_[i].nextOut() ) );
195 combDelayL_[i].tick(yn);
196 outL += yn;
197
198 // Right channel
199 //yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPR_[i].tick(FreeVerb::undenormalize(combDelayR_[i].nextOut()))));
200 yn = fInput + (roomSize_ * combLPR_[i].tick( combDelayR_[i].nextOut() ) );
201 combDelayR_[i].tick(yn);
202 outR += yn;
203 }
204
205 // Series allpass filters
206 for ( int i = 0; i < nAllpasses; i++ ) {
207 // Left channel
208 //StkFloat vn_m = FreeVerb::undenormalize(allPassDelayL_[i].nextOut());
209 StkFloat vn_m = allPassDelayL_[i].nextOut();
210 StkFloat vn = outL + (g_ * vn_m);
211 allPassDelayL_[i].tick(vn);
212
213 // calculate output
214 outL = -vn + (1.0 + g_)*vn_m;
215
216 // Right channel
217 //vn_m = FreeVerb::undenormalize(allPassDelayR_[i].nextOut());
218 vn_m = allPassDelayR_[i].nextOut();
219 vn = outR + (g_ * vn_m);
220 allPassDelayR_[i].tick(vn);
221
222 // calculate output
223 outR = -vn + (1.0 + g_)*vn_m;
224 }
225
226 // Mix output
227 lastFrame_[0] = outL*wet1_ + outR*wet2_ + inputL*dry_;
228 lastFrame_[1] = outR*wet1_ + outL*wet2_ + inputR*dry_;
229
230 /*
231 // Hard limiter ... there's not much else we can do at this point
232 if ( lastFrame_[0] >= 1.0 ) {
233 lastFrame_[0] = 0.9999;
234 }
235 if ( lastFrame_[0] <= -1.0 ) {
236 lastFrame_[0] = -0.9999;
237 }
238 if ( lastFrame_[1] >= 1.0 ) {
239 lastFrame_[1] = 0.9999;
240 }
241 if ( lastFrame_[1] <= -1.0 ) {
242 lastFrame_[1] = -0.9999;
243 }
244 */
245
246 return lastFrame_[channel];
247 }
248
249 }
250
251 #endif

The Synthesis ToolKit in C++ (STK)
©1995--2017 Perry R. Cook and Gary P. Scavone. All Rights Reserved.