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--2014 Perry R. Cook and Gary P. Scavone. All Rights Reserved.