The Synthesis ToolKit in C++ (STK)

Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial

# Shakers.h

    00001 #ifndef STK_SHAKERS_H
    00002 #define STK_SHAKERS_H
    00003
    00004 #include "Instrmnt.h"
    00005 #include <cmath>
    00006 #include <stdlib.h>
    00007
    00008 namespace stk {
    00009
    00010 /***************************************************/
    00058 /***************************************************/
    00059
    00060 class Shakers : public Instrmnt
    00061 {
    00062  public:
    00064   Shakers( int type = 0 );
    00065
    00067
    00071   void noteOn( StkFloat instrument, StkFloat amplitude );
    00072
    00074   void noteOff( StkFloat amplitude );
    00075
    00077   void controlChange( int number, StkFloat value );
    00078
    00080   StkFloat tick( unsigned int channel = 0 );
    00081
    00083
    00090   StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
    00091
    00092   struct BiQuad {
    00093     StkFloat gain;
    00094     StkFloat b[3];
    00095     StkFloat a[3]; // a0 term assumed equal to 1.0
    00096     StkFloat inputs[3];
    00097     StkFloat outputs[3];
    00098
    00099     // Default constructor.
    00100     BiQuad()
    00101     {
    00102       gain = 0.0;
    00103       for ( int i=0; i<3; i++ ) {
    00104         b[i] = 0.0;
    00105         a[i] = 0.0;
    00106         inputs[i] = 0.0;
    00107         outputs[i] = 0.0;
    00108       }
    00109     }
    00110   };
    00111
    00112  protected:
    00113
    00114   void setType( int type );
    00115   void setResonance( BiQuad &filter, StkFloat frequency, StkFloat radius );
    00116   StkFloat tickResonance( BiQuad &filter, StkFloat input );
    00117   void setEqualization( StkFloat b0, StkFloat b1, StkFloat b2 );
    00118   StkFloat tickEqualize( StkFloat input );
    00119   int randomInt( int max );
    00120   StkFloat randomFloat( StkFloat max = 1.0 );
    00121   StkFloat noise( void );
    00122   void waterDrop( void );
    00123
    00124   int shakerType_;
    00125   unsigned int nResonances_;
    00126   StkFloat shakeEnergy_;
    00127   StkFloat soundDecay_;
    00128   StkFloat systemDecay_;
    00129   StkFloat nObjects_;
    00130   StkFloat sndLevel_;
    00131   StkFloat baseGain_;
    00132   StkFloat currentGain_;
    00133   StkFloat baseDecay_;
    00134   StkFloat baseObjects_;
    00135   StkFloat decayScale_;
    00136   BiQuad equalizer_;
    00137   StkFloat ratchetCount_;
    00138   StkFloat ratchetDelta_;
    00139   StkFloat baseRatchetDelta_;
    00140   int lastRatchetValue_;
    00141
    00142   std::vector< BiQuad > filters_;
    00143   std::vector< StkFloat > baseFrequencies_;
    00144   std::vector< StkFloat > baseRadii_;
    00145   std::vector< bool > doVaryFrequency_;
    00146   std::vector< StkFloat > tempFrequencies_;
    00147   StkFloat varyFactor_;
    00148 };
    00149
    00150 inline void Shakers :: setResonance( BiQuad &filter, StkFloat frequency, StkFloat radius )
    00151 {
    00152   filter.a[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate());
    00153   filter.a[2] = radius * radius;
    00154 }
    00155
    00156 inline StkFloat Shakers :: tickResonance( BiQuad &filter, StkFloat input )
    00157 {
    00158   filter.outputs[0] = input * filter.gain * currentGain_;
    00159   filter.outputs[0] -= filter.a[1] * filter.outputs[1] + filter.a[2] * filter.outputs[2];
    00160   filter.outputs[2] = filter.outputs[1];
    00161   filter.outputs[1] = filter.outputs[0];
    00162   return filter.outputs[0];
    00163 }
    00164
    00165 inline void Shakers :: setEqualization( StkFloat b0, StkFloat b1, StkFloat b2 )
    00166 {
    00167   equalizer_.b[0] = b0;
    00168   equalizer_.b[1] = b1;
    00169   equalizer_.b[2] = b2;
    00170 }
    00171
    00172 inline StkFloat Shakers :: tickEqualize( StkFloat input )
    00173 {
    00174   equalizer_.inputs[0] = input;
    00175   equalizer_.outputs[0] = equalizer_.b[0] * equalizer_.inputs[0] + equalizer_.b[1] * equalizer_.inputs[1] + equalizer_.b[2] * equalizer_.inputs[2];
    00176   equalizer_.inputs[2] = equalizer_.inputs[1];
    00177   equalizer_.inputs[1] = equalizer_.inputs[0];
    00178   return equalizer_.outputs[0];
    00179 }
    00180
    00181 inline int Shakers :: randomInt( int max ) //  Return random integer between 0 and max-1
    00182 {
    00183   return (int) ((float)max * rand() / (RAND_MAX + 1.0) );
    00184 }
    00185
    00186 inline StkFloat Shakers :: randomFloat( StkFloat max ) // Return random float between 0.0 and max
    00187 {
    00188   return (StkFloat) (max * rand() / (RAND_MAX + 1.0) );
    00189 }
    00190
    00191 inline StkFloat Shakers :: noise( void ) //  Return random StkFloat float between -1.0 and 1.0
    00192 {
    00193   return ( (StkFloat) ( 2.0 * rand() / (RAND_MAX + 1.0) ) - 1.0 );
    00194 }
    00195
    00196 const StkFloat MIN_ENERGY = 0.001;
    00197 const StkFloat WATER_FREQ_SWEEP = 1.0001;
    00198
    00199 inline void Shakers :: waterDrop( void )
    00200 {
    00201   if ( randomInt( 32767 ) < nObjects_) {
    00202     sndLevel_ = shakeEnergy_;
    00203     unsigned int j = randomInt( 3 );
    00204     if ( j == 0 && filters_[0].gain == 0.0 ) { // don't change unless fully decayed
    00205       tempFrequencies_[0] = baseFrequencies_[1] * (0.75 + (0.25 * noise()));
    00206       filters_[0].gain = fabs( noise() );
    00207     }
    00208     else if (j == 1 && filters_[1].gain == 0.0) {
    00209       tempFrequencies_[1] = baseFrequencies_[1] * (1.0 + (0.25 * noise()));
    00210       filters_[1].gain = fabs( noise() );
    00211     }
    00212     else if ( filters_[2].gain == 0.0 ) {
    00213       tempFrequencies_[2] = baseFrequencies_[1] * (1.25 + (0.25 * noise()));
    00214       filters_[2].gain = fabs( noise() );
    00215     }
    00216   }
    00217
    00218   // Sweep center frequencies.
    00219   for ( unsigned int i=0; i<3; i++ ) { // WATER_RESONANCES = 3
    00220     filters_[i].gain *= baseRadii_[i];
    00221     if ( filters_[i].gain > 0.001 ) {
    00222       tempFrequencies_[i] *= WATER_FREQ_SWEEP;
    00223       filters_[i].a[1] = -2.0 * baseRadii_[i] * cos( TWO_PI * tempFrequencies_[i] / Stk::sampleRate() );
    00224     }
    00225     else
    00226       filters_[i].gain = 0.0;
    00227   }
    00228 }
    00229
    00230 inline StkFloat Shakers :: tick( unsigned int )
    00231 {
    00232   unsigned int iTube = 0;
    00233   StkFloat input = 0.0;
    00234   if ( shakerType_ == 19 || shakerType_ == 20 ) {
    00235     if ( ratchetCount_ <= 0 ) return lastFrame_[0] = 0.0;
    00236
    00237     shakeEnergy_ -= ( ratchetDelta_ + ( 0.002 * shakeEnergy_ ) );
    00238     if ( shakeEnergy_ < 0.0 ) {
    00239       shakeEnergy_ = 1.0;
    00240       ratchetCount_--;
    00241     }
    00242
    00243     if ( randomFloat( 1024 ) < nObjects_ )
    00244       sndLevel_ += shakeEnergy_ * shakeEnergy_;
    00245
    00246     // Sound is enveloped noise
    00247     input = sndLevel_ * noise() * shakeEnergy_;
    00248   }
    00249   else {
    00250     if ( shakeEnergy_ < MIN_ENERGY ) return lastFrame_[0] = 0.0;
    00251
    00252     // Exponential system decay
    00253     shakeEnergy_ *= systemDecay_;
    00254
    00255     // Random events
    00256     if ( shakerType_ == 21 ) {
    00257       waterDrop();
    00258       input = sndLevel_;
    00259     }
    00260     else {
    00261       if ( randomFloat( 1024.0 ) < nObjects_ ) {
    00262         sndLevel_ += shakeEnergy_;
    00263         input = sndLevel_;
    00264         // Vary resonance frequencies if specified.
    00265         for ( unsigned int i=0; i<nResonances_; i++ ) {
    00266           if ( doVaryFrequency_[i] ) {
    00267             StkFloat tempRand = baseFrequencies_[i] * ( 1.0 + ( varyFactor_ * noise() ) );
    00268             filters_[i].a[1] = -2.0 * baseRadii_[i] * cos( TWO_PI * tempRand / Stk::sampleRate() );
    00269           }
    00270         }
    00271         if ( shakerType_ == 22 ) iTube = randomInt( 7 ); // ANGKLUNG_RESONANCES
    00272       }
    00273     }
    00274   }
    00275
    00276   // Exponential sound decay
    00277   sndLevel_ *= soundDecay_;
    00278
    00279   // Do resonance filtering
    00280   lastFrame_[0] = 0.0;
    00281   if ( shakerType_ == 22 ) {
    00282     for ( unsigned int i=0; i<nResonances_; i++ ) {
    00283       if ( i == iTube )
    00284         lastFrame_[0] += tickResonance( filters_[i], input );
    00285       else
    00286         lastFrame_[0] += tickResonance( filters_[i], 0.0 );
    00287     }
    00288   }
    00289   else {
    00290     for ( unsigned int i=0; i<nResonances_; i++ )
    00291       lastFrame_[0] += tickResonance( filters_[i], input );
    00292   }
    00293
    00294   // Do final FIR filtering (lowpass or highpass)
    00295   lastFrame_[0] = tickEqualize( lastFrame_[0] );
    00296
    00297   //if ( std::abs(lastFrame_[0]) > 1.0 )
    00298   //  std::cout << "lastOutput = " << lastFrame_[0] << std::endl;
    00299
    00300   return lastFrame_[0];
    00301 }
    00302
    00303 inline StkFrames& Shakers :: tick( StkFrames& frames, unsigned int channel )
    00304 {
    00305   unsigned int nChannels = lastFrame_.channels();
    00306 #if defined(_STK_DEBUG_)
    00307   if ( channel > frames.channels() - nChannels ) {
    00308     oStream_ << "Shakers::tick(): channel and StkFrames arguments are incompatible!";
    00309     handleError( StkError::FUNCTION_ARGUMENT );
    00310   }
    00311 #endif
    00312
    00313   StkFloat *samples = &frames[channel];
    00314   unsigned int j, hop = frames.channels() - nChannels;
    00315   if ( nChannels == 1 ) {
    00316     for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
    00317       *samples++ = tick();
    00318   }
    00319   else {
    00320     for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
    00321       *samples++ = tick();
    00322       for ( j=1; j<nChannels; j++ )
    00323         *samples++ = lastFrame_[j];
    00324     }
    00325   }
    00326
    00327   return frames;
    00328 }
    00329
    00330 } // stk namespace
    00331
    00332 #endif

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