Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial
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 errorString_ << "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-2010 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |