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