Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial
00001 #ifndef STK_BLITSQUARE_H 00002 #define STK_BLITSQUARE_H 00003 00004 #include "Generator.h" 00005 #include <cmath> 00006 #include <limits> 00007 00008 namespace stk { 00009 00010 /***************************************************/ 00040 /***************************************************/ 00041 00042 class BlitSquare: public Generator 00043 { 00044 public: 00046 BlitSquare( StkFloat frequency = 220.0 ); 00047 00049 ~BlitSquare(); 00050 00052 void reset(); 00053 00055 00058 void setPhase( StkFloat phase ) { phase_ = PI * phase; }; 00059 00061 00064 StkFloat getPhase() const { return phase_ / PI; }; 00065 00067 void setFrequency( StkFloat frequency ); 00068 00070 00082 void setHarmonics( unsigned int nHarmonics = 0 ); 00083 00085 StkFloat lastOut( void ) const { return lastFrame_[0]; }; 00086 00088 StkFloat tick( void ); 00089 00091 00098 StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 00099 00100 protected: 00101 00102 void updateHarmonics( void ); 00103 00104 unsigned int nHarmonics_; 00105 unsigned int m_; 00106 StkFloat rate_; 00107 StkFloat phase_; 00108 StkFloat p_; 00109 StkFloat a_; 00110 StkFloat lastBlitOutput_; 00111 StkFloat dcbState_; 00112 }; 00113 00114 inline StkFloat BlitSquare :: tick( void ) 00115 { 00116 StkFloat temp = lastBlitOutput_; 00117 00118 // A fully optimized version of this would replace the two sin calls 00119 // with a pair of fast sin oscillators, for which stable fast 00120 // two-multiply algorithms are well known. In the spirit of STK, 00121 // which favors clarity over performance, the optimization has 00122 // not been made here. 00123 00124 // Avoid a divide by zero, or use of a denomralized divisor 00125 // at the sinc peak, which has a limiting value of 1.0. 00126 StkFloat denominator = sin( phase_ ); 00127 if ( fabs( denominator ) < std::numeric_limits<StkFloat>::epsilon() ) { 00128 // Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*. 00129 if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f ) 00130 lastBlitOutput_ = a_; 00131 else 00132 lastBlitOutput_ = -a_; 00133 } 00134 else { 00135 lastBlitOutput_ = sin( m_ * phase_ ); 00136 lastBlitOutput_ /= p_ * denominator; 00137 } 00138 00139 lastBlitOutput_ += temp; 00140 00141 // Now apply DC blocker. 00142 lastFrame_[0] = lastBlitOutput_ - dcbState_ + 0.999 * lastFrame_[0]; 00143 dcbState_ = lastBlitOutput_; 00144 00145 phase_ += rate_; 00146 if ( phase_ >= TWO_PI ) phase_ -= TWO_PI; 00147 00148 return lastFrame_[0]; 00149 } 00150 00151 inline StkFrames& BlitSquare :: tick( StkFrames& frames, unsigned int channel ) 00152 { 00153 #if defined(_STK_DEBUG_) 00154 if ( channel >= frames.channels() ) { 00155 errorString_ << "BlitSquare::tick(): channel and StkFrames arguments are incompatible!"; 00156 handleError( StkError::FUNCTION_ARGUMENT ); 00157 } 00158 #endif 00159 00160 StkFloat *samples = &frames[channel]; 00161 unsigned int hop = frames.channels(); 00162 for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) 00163 *samples = BlitSquare::tick(); 00164 00165 return frames; 00166 } 00167 00168 } // stk namespace 00169 00170 #endif
The Synthesis ToolKit in C++ (STK) |
©1995-2010 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |