Home   Information   Classes   Download   Usage   Mail List   Requirements   Links   FAQ   Tutorial


Shakers.h
1 #ifndef STK_SHAKERS_H
2 #define STK_SHAKERS_H
3 
4 #include "Instrmnt.h"
5 #include <cmath>
6 #include <stdlib.h>
7 
8 namespace stk {
9 
10 /***************************************************/
58 /***************************************************/
59 
60 class Shakers : public Instrmnt
61 {
62  public:
64  Shakers( int type = 0 );
65 
67 
71  void noteOn( StkFloat instrument, StkFloat amplitude );
72 
74  void noteOff( StkFloat amplitude );
75 
77  void controlChange( int number, StkFloat value );
78 
80  StkFloat tick( unsigned int channel = 0 );
81 
83 
90  StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
91 
92  struct BiQuad {
93  StkFloat gain;
94  StkFloat b[3];
95  StkFloat a[3]; // a0 term assumed equal to 1.0
96  StkFloat inputs[3];
97  StkFloat outputs[3];
98 
99  // Default constructor.
100  BiQuad()
101  {
102  gain = 0.0;
103  for ( int i=0; i<3; i++ ) {
104  b[i] = 0.0;
105  a[i] = 0.0;
106  inputs[i] = 0.0;
107  outputs[i] = 0.0;
108  }
109  }
110  };
111 
112  protected:
113 
114  void setType( int type );
115  void setResonance( BiQuad &filter, StkFloat frequency, StkFloat radius );
116  StkFloat tickResonance( BiQuad &filter, StkFloat input );
117  void setEqualization( StkFloat b0, StkFloat b1, StkFloat b2 );
118  StkFloat tickEqualize( StkFloat input );
119  int randomInt( int max );
120  StkFloat randomFloat( StkFloat max = 1.0 );
121  StkFloat noise( void );
122  void waterDrop( void );
123 
124  int shakerType_;
125  unsigned int nResonances_;
126  StkFloat shakeEnergy_;
127  StkFloat soundDecay_;
128  StkFloat systemDecay_;
129  StkFloat nObjects_;
130  StkFloat sndLevel_;
131  StkFloat baseGain_;
132  StkFloat currentGain_;
133  StkFloat baseDecay_;
134  StkFloat baseObjects_;
135  StkFloat decayScale_;
136  BiQuad equalizer_;
137  StkFloat ratchetCount_;
138  StkFloat ratchetDelta_;
139  StkFloat baseRatchetDelta_;
140  int lastRatchetValue_;
141 
142  std::vector< BiQuad > filters_;
143  std::vector< StkFloat > baseFrequencies_;
144  std::vector< StkFloat > baseRadii_;
145  std::vector< bool > doVaryFrequency_;
146  std::vector< StkFloat > tempFrequencies_;
147  StkFloat varyFactor_;
148 };
149 
150 inline void Shakers :: setResonance( BiQuad &filter, StkFloat frequency, StkFloat radius )
151 {
152  filter.a[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate());
153  filter.a[2] = radius * radius;
154 }
155 
156 inline StkFloat Shakers :: tickResonance( BiQuad &filter, StkFloat input )
157 {
158  filter.outputs[0] = input * filter.gain * currentGain_;
159  filter.outputs[0] -= filter.a[1] * filter.outputs[1] + filter.a[2] * filter.outputs[2];
160  filter.outputs[2] = filter.outputs[1];
161  filter.outputs[1] = filter.outputs[0];
162  return filter.outputs[0];
163 }
164 
165 inline void Shakers :: setEqualization( StkFloat b0, StkFloat b1, StkFloat b2 )
166 {
167  equalizer_.b[0] = b0;
168  equalizer_.b[1] = b1;
169  equalizer_.b[2] = b2;
170 }
171 
172 inline StkFloat Shakers :: tickEqualize( StkFloat input )
173 {
174  equalizer_.inputs[0] = input;
175  equalizer_.outputs[0] = equalizer_.b[0] * equalizer_.inputs[0] + equalizer_.b[1] * equalizer_.inputs[1] + equalizer_.b[2] * equalizer_.inputs[2];
176  equalizer_.inputs[2] = equalizer_.inputs[1];
177  equalizer_.inputs[1] = equalizer_.inputs[0];
178  return equalizer_.outputs[0];
179 }
180 
181 inline int Shakers :: randomInt( int max ) // Return random integer between 0 and max-1
182 {
183  return (int) ((float)max * rand() / (RAND_MAX + 1.0) );
184 }
185 
186 inline StkFloat Shakers :: randomFloat( StkFloat max ) // Return random float between 0.0 and max
187 {
188  return (StkFloat) (max * rand() / (RAND_MAX + 1.0) );
189 }
190 
191 inline StkFloat Shakers :: noise( void ) // Return random StkFloat float between -1.0 and 1.0
192 {
193  return ( (StkFloat) ( 2.0 * rand() / (RAND_MAX + 1.0) ) - 1.0 );
194 }
195 
196 const StkFloat MIN_ENERGY = 0.001;
197 const StkFloat WATER_FREQ_SWEEP = 1.0001;
198 
199 inline void Shakers :: waterDrop( void )
200 {
201  if ( randomInt( 32767 ) < nObjects_) {
202  sndLevel_ = shakeEnergy_;
203  unsigned int j = randomInt( 3 );
204  if ( j == 0 && filters_[0].gain == 0.0 ) { // don't change unless fully decayed
205  tempFrequencies_[0] = baseFrequencies_[1] * (0.75 + (0.25 * noise()));
206  filters_[0].gain = fabs( noise() );
207  }
208  else if (j == 1 && filters_[1].gain == 0.0) {
209  tempFrequencies_[1] = baseFrequencies_[1] * (1.0 + (0.25 * noise()));
210  filters_[1].gain = fabs( noise() );
211  }
212  else if ( filters_[2].gain == 0.0 ) {
213  tempFrequencies_[2] = baseFrequencies_[1] * (1.25 + (0.25 * noise()));
214  filters_[2].gain = fabs( noise() );
215  }
216  }
217 
218  // Sweep center frequencies.
219  for ( unsigned int i=0; i<3; i++ ) { // WATER_RESONANCES = 3
220  filters_[i].gain *= baseRadii_[i];
221  if ( filters_[i].gain > 0.001 ) {
222  tempFrequencies_[i] *= WATER_FREQ_SWEEP;
223  filters_[i].a[1] = -2.0 * baseRadii_[i] * cos( TWO_PI * tempFrequencies_[i] / Stk::sampleRate() );
224  }
225  else
226  filters_[i].gain = 0.0;
227  }
228 }
229 
230 inline StkFloat Shakers :: tick( unsigned int )
231 {
232  unsigned int iTube = 0;
233  StkFloat input = 0.0;
234  if ( shakerType_ == 19 || shakerType_ == 20 ) {
235  if ( ratchetCount_ <= 0 ) return lastFrame_[0] = 0.0;
236 
237  shakeEnergy_ -= ( ratchetDelta_ + ( 0.002 * shakeEnergy_ ) );
238  if ( shakeEnergy_ < 0.0 ) {
239  shakeEnergy_ = 1.0;
240  ratchetCount_--;
241  }
242 
243  if ( randomFloat( 1024 ) < nObjects_ )
244  sndLevel_ += shakeEnergy_ * shakeEnergy_;
245 
246  // Sound is enveloped noise
247  input = sndLevel_ * noise() * shakeEnergy_;
248  }
249  else {
250  if ( shakeEnergy_ < MIN_ENERGY ) return lastFrame_[0] = 0.0;
251 
252  // Exponential system decay
253  shakeEnergy_ *= systemDecay_;
254 
255  // Random events
256  if ( shakerType_ == 21 ) {
257  waterDrop();
258  input = sndLevel_;
259  }
260  else {
261  if ( randomFloat( 1024.0 ) < nObjects_ ) {
262  sndLevel_ += shakeEnergy_;
263  input = sndLevel_;
264  // Vary resonance frequencies if specified.
265  for ( unsigned int i=0; i<nResonances_; i++ ) {
266  if ( doVaryFrequency_[i] ) {
267  StkFloat tempRand = baseFrequencies_[i] * ( 1.0 + ( varyFactor_ * noise() ) );
268  filters_[i].a[1] = -2.0 * baseRadii_[i] * cos( TWO_PI * tempRand / Stk::sampleRate() );
269  }
270  }
271  if ( shakerType_ == 22 ) iTube = randomInt( 7 ); // ANGKLUNG_RESONANCES
272  }
273  }
274  }
275 
276  // Exponential sound decay
277  sndLevel_ *= soundDecay_;
278 
279  // Do resonance filtering
280  lastFrame_[0] = 0.0;
281  if ( shakerType_ == 22 ) {
282  for ( unsigned int i=0; i<nResonances_; i++ ) {
283  if ( i == iTube )
284  lastFrame_[0] += tickResonance( filters_[i], input );
285  else
286  lastFrame_[0] += tickResonance( filters_[i], 0.0 );
287  }
288  }
289  else {
290  for ( unsigned int i=0; i<nResonances_; i++ )
291  lastFrame_[0] += tickResonance( filters_[i], input );
292  }
293 
294  // Do final FIR filtering (lowpass or highpass)
295  lastFrame_[0] = tickEqualize( lastFrame_[0] );
296 
297  //if ( std::abs(lastFrame_[0]) > 1.0 )
298  // std::cout << "lastOutput = " << lastFrame_[0] << std::endl;
299 
300  return lastFrame_[0];
301 }
302 
303 inline StkFrames& Shakers :: tick( StkFrames& frames, unsigned int channel )
304 {
305  unsigned int nChannels = lastFrame_.channels();
306 #if defined(_STK_DEBUG_)
307  if ( channel > frames.channels() - nChannels ) {
308  oStream_ << "Shakers::tick(): channel and StkFrames arguments are incompatible!";
309  handleError( StkError::FUNCTION_ARGUMENT );
310  }
311 #endif
312 
313  StkFloat *samples = &frames[channel];
314  unsigned int j, hop = frames.channels() - nChannels;
315  if ( nChannels == 1 ) {
316  for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
317  *samples++ = tick();
318  }
319  else {
320  for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
321  *samples++ = tick();
322  for ( j=1; j<nChannels; j++ )
323  *samples++ = lastFrame_[j];
324  }
325  }
326 
327  return frames;
328 }
329 
330 } // stk namespace
331 
332 #endif

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