Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial
00001 #ifndef STK_FREEVERB_H 00002 #define STK_FREEVERB_H 00003 00004 #include "Effect.h" 00005 #include "Delay.h" 00006 #include "OnePole.h" 00007 00008 namespace stk { 00009 00010 /***********************************************************************/ 00024 /***********************************************************************/ 00025 00026 class FreeVerb : public Effect 00027 { 00028 public: 00030 00036 FreeVerb(); 00037 00039 ~FreeVerb(); 00040 00042 void setEffectMix( StkFloat mix ); 00043 00045 void setRoomSize( StkFloat value ); 00046 00048 StkFloat getRoomSize( void ); 00049 00051 void setDamping( StkFloat value ); 00052 00054 StkFloat getDamping( void ); 00055 00057 void setWidth( StkFloat value ); 00058 00060 StkFloat getWidth( void ); 00061 00063 void setMode( bool isFrozen ); 00064 00066 StkFloat getMode( void ); 00067 00069 void clear( void ); 00070 00072 00080 StkFloat lastOut( unsigned int channel = 0 ); 00081 00083 00090 StkFloat tick( StkFloat inputL, StkFloat inputR = 0.0, unsigned int channel = 0 ); 00091 00093 00103 StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 00104 00106 00117 StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 ); 00118 00119 protected: 00121 void update( void ); 00122 00123 // Clamp very small floats to zero, version from 00124 // http://music.columbia.edu/pipermail/linux-audio-user/2004-July/013489.html . 00125 // However, this is for 32-bit floats only. 00126 //static inline StkFloat undenormalize( volatile StkFloat s ) { 00127 // s += 9.8607615E-32f; 00128 // return s - 9.8607615E-32f; 00129 //} 00130 00131 static const int nCombs = 8; 00132 static const int nAllpasses = 4; 00133 static const int stereoSpread = 23; 00134 static const StkFloat fixedGain; 00135 static const StkFloat scaleWet; 00136 static const StkFloat scaleDry; 00137 static const StkFloat scaleDamp; 00138 static const StkFloat scaleRoom; 00139 static const StkFloat offsetRoom; 00140 00141 // Delay line lengths for 44100Hz sampling rate. 00142 static int cDelayLengths[nCombs]; 00143 static int aDelayLengths[nAllpasses]; 00144 00145 StkFloat g_; // allpass coefficient 00146 StkFloat gain_; 00147 StkFloat roomSizeMem_, roomSize_; 00148 StkFloat dampMem_, damp_; 00149 StkFloat wet1_, wet2_; 00150 StkFloat dry_; 00151 StkFloat width_; 00152 bool frozenMode_; 00153 00154 // LBFC: Lowpass Feedback Comb Filters 00155 Delay combDelayL_[nCombs]; 00156 Delay combDelayR_[nCombs]; 00157 OnePole combLPL_[nCombs]; 00158 OnePole combLPR_[nCombs]; 00159 00160 // AP: Allpass Filters 00161 Delay allPassDelayL_[nAllpasses]; 00162 Delay allPassDelayR_[nAllpasses]; 00163 }; 00164 00165 inline StkFloat FreeVerb :: lastOut( unsigned int channel ) 00166 { 00167 #if defined(_STK_DEBUG_) 00168 if ( channel > 1 ) { 00169 oStream_ << "FreeVerb::lastOut(): channel argument must be less than 2!"; 00170 handleError( StkError::FUNCTION_ARGUMENT ); 00171 } 00172 #endif 00173 00174 return lastFrame_[channel]; 00175 } 00176 00177 inline StkFloat FreeVerb::tick( StkFloat inputL, StkFloat inputR, unsigned int channel ) 00178 { 00179 #if defined(_STK_DEBUG_) 00180 if ( channel > 1 ) { 00181 oStream_ << "FreeVerb::tick(): channel argument must be less than 2!"; 00182 handleError(StkError::FUNCTION_ARGUMENT); 00183 } 00184 #endif 00185 00186 if ( !inputR ) { 00187 inputR = inputL; 00188 } 00189 00190 StkFloat fInput = (inputL + inputR) * gain_; 00191 StkFloat outL = 0.0; 00192 StkFloat outR = 0.0; 00193 00194 // Parallel LBCF filters 00195 for ( int i = 0; i < nCombs; i++ ) { 00196 // Left channel 00197 //StkFloat yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPL_[i].tick(FreeVerb::undenormalize(combDelayL_[i].nextOut())))); 00198 StkFloat yn = fInput + (roomSize_ * combLPL_[i].tick( combDelayL_[i].nextOut() ) ); 00199 combDelayL_[i].tick(yn); 00200 outL += yn; 00201 00202 // Right channel 00203 //yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPR_[i].tick(FreeVerb::undenormalize(combDelayR_[i].nextOut())))); 00204 yn = fInput + (roomSize_ * combLPR_[i].tick( combDelayR_[i].nextOut() ) ); 00205 combDelayR_[i].tick(yn); 00206 outR += yn; 00207 } 00208 00209 // Series allpass filters 00210 for ( int i = 0; i < nAllpasses; i++ ) { 00211 // Left channel 00212 //StkFloat vn_m = FreeVerb::undenormalize(allPassDelayL_[i].nextOut()); 00213 StkFloat vn_m = allPassDelayL_[i].nextOut(); 00214 StkFloat vn = outL + (g_ * vn_m); 00215 allPassDelayL_[i].tick(vn); 00216 00217 // calculate output 00218 outL = -vn + (1.0 + g_)*vn_m; 00219 00220 // Right channel 00221 //vn_m = FreeVerb::undenormalize(allPassDelayR_[i].nextOut()); 00222 vn_m = allPassDelayR_[i].nextOut(); 00223 vn = outR + (g_ * vn_m); 00224 allPassDelayR_[i].tick(vn); 00225 00226 // calculate output 00227 outR = -vn + (1.0 + g_)*vn_m; 00228 } 00229 00230 // Mix output 00231 lastFrame_[0] = outL*wet1_ + outR*wet2_ + inputL*dry_; 00232 lastFrame_[1] = outR*wet1_ + outL*wet2_ + inputR*dry_; 00233 00234 /* 00235 // Hard limiter ... there's not much else we can do at this point 00236 if ( lastFrame_[0] >= 1.0 ) { 00237 lastFrame_[0] = 0.9999; 00238 } 00239 if ( lastFrame_[0] <= -1.0 ) { 00240 lastFrame_[0] = -0.9999; 00241 } 00242 if ( lastFrame_[1] >= 1.0 ) { 00243 lastFrame_[1] = 0.9999; 00244 } 00245 if ( lastFrame_[1] <= -1.0 ) { 00246 lastFrame_[1] = -0.9999; 00247 } 00248 */ 00249 00250 return lastFrame_[channel]; 00251 } 00252 00253 } 00254 00255 #endif
The Synthesis ToolKit in C++ (STK) |
©1995-2012 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |