Home   Information   Classes   Download   Usage   Mail List   Requirements   Links   FAQ   Tutorial


BlitSaw.h
1 #ifndef STK_BLITSAW_H
2 #define STK_BLITSAW_H
3 
4 #include "Generator.h"
5 #include <cmath>
6 #include <limits>
7 
8 namespace stk {
9 
10 /***************************************************/
29 /***************************************************/
30 
31 class BlitSaw: public Generator
32 {
33  public:
35  BlitSaw( StkFloat frequency = 220.0 );
36 
38  ~BlitSaw();
39 
41  void reset();
42 
44  void setFrequency( StkFloat frequency );
45 
47 
59  void setHarmonics( unsigned int nHarmonics = 0 );
60 
62  StkFloat lastOut( void ) const { return lastFrame_[0]; };
63 
65  StkFloat tick( void );
66 
68 
75  StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
76 
77  protected:
78 
79  void updateHarmonics( void );
80 
81  unsigned int nHarmonics_;
82  unsigned int m_;
83  StkFloat rate_;
84  StkFloat phase_;
85  StkFloat p_;
86  StkFloat C2_;
87  StkFloat a_;
88  StkFloat state_;
89 
90 };
91 
92 inline StkFloat BlitSaw :: tick( void )
93 {
94  // The code below implements the BLIT algorithm of Stilson and
95  // Smith, followed by a summation and filtering operation to produce
96  // a sawtooth waveform. After experimenting with various approaches
97  // to calculate the average value of the BLIT over one period, I
98  // found that an estimate of C2_ = 1.0 / period (in samples) worked
99  // most consistently. A "leaky integrator" is then applied to the
100  // difference of the BLIT output and C2_. (GPS - 1 October 2005)
101 
102  // A fully optimized version of this code would replace the two sin
103  // calls with a pair of fast sin oscillators, for which stable fast
104  // two-multiply algorithms are well known. In the spirit of STK,
105  // which favors clarity over performance, the optimization has
106  // not been made here.
107 
108  // Avoid a divide by zero, or use of a denormalized divisor
109  // at the sinc peak, which has a limiting value of m_ / p_.
110  StkFloat tmp, denominator = sin( phase_ );
111  if ( fabs(denominator) <= std::numeric_limits<StkFloat>::epsilon() )
112  tmp = a_;
113  else {
114  tmp = sin( m_ * phase_ );
115  tmp /= p_ * denominator;
116  }
117 
118  tmp += state_ - C2_;
119  state_ = tmp * 0.995;
120 
121  phase_ += rate_;
122  if ( phase_ >= PI ) phase_ -= PI;
123 
124  lastFrame_[0] = tmp;
125  return lastFrame_[0];
126 }
127 
128 inline StkFrames& BlitSaw :: tick( StkFrames& frames, unsigned int channel )
129 {
130 #if defined(_STK_DEBUG_)
131  if ( channel >= frames.channels() ) {
132  oStream_ << "BlitSaw::tick(): channel and StkFrames arguments are incompatible!";
133  handleError( StkError::FUNCTION_ARGUMENT );
134  }
135 #endif
136 
137 
138  StkFloat *samples = &frames[channel];
139  unsigned int hop = frames.channels();
140  for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
141  *samples = BlitSaw::tick();
142 
143  return frames;
144 }
145 
146 } // stk namespace
147 
148 #endif

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