Mercurial > hg > apm2s
comparison stk/include/SineWave.h @ 0:4606bd505630 tip
first import
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Sat, 13 Jun 2015 15:08:10 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4606bd505630 |
---|---|
1 #ifndef STK_SINEWAVE_H | |
2 #define STK_SINEWAVE_H | |
3 | |
4 const unsigned long TABLE_SIZE = 2048; | |
5 | |
6 #include "Generator.h" | |
7 | |
8 namespace stk { | |
9 | |
10 /***************************************************/ | |
11 /*! \class SineWave | |
12 \brief STK sinusoid oscillator class. | |
13 | |
14 This class computes and saves a static sine "table" that can be | |
15 shared by multiple instances. It has an interface similar to the | |
16 WaveLoop class but inherits from the Generator class. Output | |
17 values are computed using linear interpolation. | |
18 | |
19 The "table" length, set in SineWave.h, is 2048 samples by default. | |
20 | |
21 by Perry R. Cook and Gary P. Scavone, 1995--2014. | |
22 */ | |
23 /***************************************************/ | |
24 | |
25 class SineWave : public Generator | |
26 { | |
27 public: | |
28 //! Default constructor. | |
29 SineWave( void ); | |
30 | |
31 //! Class destructor. | |
32 ~SineWave( void ); | |
33 | |
34 //! Clear output and reset time pointer to zero. | |
35 void reset( void ); | |
36 | |
37 //! Set the data read rate in samples. The rate can be negative. | |
38 /*! | |
39 If the rate value is negative, the data is read in reverse order. | |
40 */ | |
41 void setRate( StkFloat rate ) { rate_ = rate; }; | |
42 | |
43 //! Set the data interpolation rate based on a looping frequency. | |
44 /*! | |
45 This function determines the interpolation rate based on the file | |
46 size and the current Stk::sampleRate. The \e frequency value | |
47 corresponds to file cycles per second. The frequency can be | |
48 negative, in which case the loop is read in reverse order. | |
49 */ | |
50 void setFrequency( StkFloat frequency ); | |
51 | |
52 //! Increment the read pointer by \e time in samples, modulo the table size. | |
53 void addTime( StkFloat time ); | |
54 | |
55 //! Increment the read pointer by a normalized \e phase value. | |
56 /*! | |
57 This function increments the read pointer by a normalized phase | |
58 value, such that \e phase = 1.0 corresponds to a 360 degree phase | |
59 shift. Positive or negative values are possible. | |
60 */ | |
61 void addPhase( StkFloat phase ); | |
62 | |
63 //! Add a normalized phase offset to the read pointer. | |
64 /*! | |
65 A \e phaseOffset = 1.0 corresponds to a 360 degree phase | |
66 offset. Positive or negative values are possible. | |
67 */ | |
68 void addPhaseOffset( StkFloat phaseOffset ); | |
69 | |
70 //! Return the last computed output value. | |
71 StkFloat lastOut( void ) const { return lastFrame_[0]; }; | |
72 | |
73 //! Compute and return one output sample. | |
74 StkFloat tick( void ); | |
75 | |
76 //! Fill a channel of the StkFrames object with computed outputs. | |
77 /*! | |
78 The \c channel argument must be less than the number of | |
79 channels in the StkFrames argument (the first channel is specified | |
80 by 0). However, range checking is only performed if _STK_DEBUG_ | |
81 is defined during compilation, in which case an out-of-range value | |
82 will trigger an StkError exception. | |
83 */ | |
84 StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); | |
85 | |
86 protected: | |
87 | |
88 void sampleRateChanged( StkFloat newRate, StkFloat oldRate ); | |
89 | |
90 static StkFrames table_; | |
91 StkFloat time_; | |
92 StkFloat rate_; | |
93 StkFloat phaseOffset_; | |
94 unsigned int iIndex_; | |
95 StkFloat alpha_; | |
96 | |
97 }; | |
98 | |
99 inline StkFloat SineWave :: tick( void ) | |
100 { | |
101 // Check limits of time address ... if necessary, recalculate modulo | |
102 // TABLE_SIZE. | |
103 while ( time_ < 0.0 ) | |
104 time_ += TABLE_SIZE; | |
105 while ( time_ >= TABLE_SIZE ) | |
106 time_ -= TABLE_SIZE; | |
107 | |
108 iIndex_ = (unsigned int) time_; | |
109 alpha_ = time_ - iIndex_; | |
110 StkFloat tmp = table_[ iIndex_ ]; | |
111 tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) ); | |
112 | |
113 // Increment time, which can be negative. | |
114 time_ += rate_; | |
115 | |
116 lastFrame_[0] = tmp; | |
117 return lastFrame_[0]; | |
118 } | |
119 | |
120 inline StkFrames& SineWave :: tick( StkFrames& frames, unsigned int channel ) | |
121 { | |
122 #if defined(_STK_DEBUG_) | |
123 if ( channel >= frames.channels() ) { | |
124 oStream_ << "SineWave::tick(): channel and StkFrames arguments are incompatible!"; | |
125 handleError( StkError::FUNCTION_ARGUMENT ); | |
126 } | |
127 #endif | |
128 | |
129 StkFloat *samples = &frames[channel]; | |
130 StkFloat tmp = 0.0; | |
131 | |
132 unsigned int hop = frames.channels(); | |
133 for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) { | |
134 | |
135 // Check limits of time address ... if necessary, recalculate modulo | |
136 // TABLE_SIZE. | |
137 while ( time_ < 0.0 ) | |
138 time_ += TABLE_SIZE; | |
139 while ( time_ >= TABLE_SIZE ) | |
140 time_ -= TABLE_SIZE; | |
141 | |
142 iIndex_ = (unsigned int) time_; | |
143 alpha_ = time_ - iIndex_; | |
144 tmp = table_[ iIndex_ ]; | |
145 tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) ); | |
146 *samples = tmp; | |
147 | |
148 // Increment time, which can be negative. | |
149 time_ += rate_; | |
150 } | |
151 | |
152 lastFrame_[0] = tmp; | |
153 return frames; | |
154 } | |
155 | |
156 } // stk namespace | |
157 | |
158 #endif | |
159 |