Home   Information   Classes   Download   Usage   Mail List   Requirements   Links   FAQ   Tutorial


FreeVerb.h

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.