Home   Information   Classes   Download   Usage   Mail List   Requirements   Links   FAQ   Tutorial


BlitSquare.h

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     oStream_ << "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-2012 Perry R. Cook and Gary P. Scavone. All Rights Reserved.