The Synthesis ToolKit in C++ (STK)

Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial

# BlitSaw.h

    00001 #ifndef STK_BLITSAW_H
    00002 #define STK_BLITSAW_H
    00003
    00004 #include "Generator.h"
    00005 #include <cmath>
    00006 #include <limits>
    00007
    00008 namespace stk {
    00009
    00010 /***************************************************/
    00029 /***************************************************/
    00030
    00031 class BlitSaw: public Generator
    00032 {
    00033  public:
    00035   BlitSaw( StkFloat frequency = 220.0 );
    00036
    00038   ~BlitSaw();
    00039
    00041   void reset();
    00042
    00044   void setFrequency( StkFloat frequency );
    00045
    00047
    00059   void setHarmonics( unsigned int nHarmonics = 0 );
    00060
    00062   StkFloat lastOut( void ) const { return lastFrame_[0]; };
    00063
    00065   StkFloat tick( void );
    00066
    00068
    00075   StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
    00076
    00077  protected:
    00078
    00079   void updateHarmonics( void );
    00080
    00081   unsigned int nHarmonics_;
    00082   unsigned int m_;
    00083   StkFloat rate_;
    00084   StkFloat phase_;
    00085   StkFloat p_;
    00086   StkFloat C2_;
    00087   StkFloat a_;
    00088   StkFloat state_;
    00089
    00090 };
    00091
    00092 inline StkFloat BlitSaw :: tick( void )
    00093 {
    00094   // The code below implements the BLIT algorithm of Stilson and
    00095   // Smith, followed by a summation and filtering operation to produce
    00096   // a sawtooth waveform.  After experimenting with various approaches
    00097   // to calculate the average value of the BLIT over one period, I
    00098   // found that an estimate of C2_ = 1.0 / period (in samples) worked
    00099   // most consistently.  A "leaky integrator" is then applied to the
    00100   // difference of the BLIT output and C2_. (GPS - 1 October 2005)
    00101
    00102   // A fully  optimized version of this code would replace the two sin
    00103   // calls with a pair of fast sin oscillators, for which stable fast
    00104   // two-multiply algorithms are well known. In the spirit of STK,
    00105   // which favors clarity over performance, the optimization has
    00106   // not been made here.
    00107
    00108   // Avoid a divide by zero, or use of a denormalized divisor
    00109   // at the sinc peak, which has a limiting value of m_ / p_.
    00110   StkFloat tmp, denominator = sin( phase_ );
    00111   if ( fabs(denominator) <= std::numeric_limits<StkFloat>::epsilon() )
    00112     tmp = a_;
    00113   else {
    00114     tmp =  sin( m_ * phase_ );
    00115     tmp /= p_ * denominator;
    00116   }
    00117
    00118   tmp += state_ - C2_;
    00119   state_ = tmp * 0.995;
    00120
    00121   phase_ += rate_;
    00122   if ( phase_ >= PI ) phase_ -= PI;
    00123
    00124   lastFrame_[0] = tmp;
    00125          return lastFrame_[0];
    00126 }
    00127
    00128 inline StkFrames& BlitSaw :: tick( StkFrames& frames, unsigned int channel )
    00129 {
    00130 #if defined(_STK_DEBUG_)
    00131   if ( channel >= frames.channels() ) {
    00132     oStream_ << "BlitSaw::tick(): channel and StkFrames arguments are incompatible!";
    00133     handleError( StkError::FUNCTION_ARGUMENT );
    00134   }
    00135 #endif
    00136
    00137
    00138   StkFloat *samples = &frames[channel];
    00139   unsigned int hop = frames.channels();
    00140   for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
    00141     *samples = BlitSaw::tick();
    00142
    00143   return frames;
    00144 }
    00145
    00146 } // stk namespace
    00147
    00148 #endif

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