CSL  5.2
Oscillator.cpp
Go to the documentation of this file.
1 //
2 // Oscillator.cpp -- implementation of the base oscillator class and most simple waveform generators
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "Oscillator.h"
7 //#include "SHARC.h"
8 #include <math.h>
9 
10 using namespace csl;
11 
12 // Generic Oscillator implementation
13 
14 // Constructor: Parameters are optional. Defaults to freq 220, amp 1 and phase & offset of 0
15 
16 Oscillator::Oscillator(float frequency, float ampl, float offset, float phase)
17  : UnitGenerator(),
18  Phased(frequency, phase),
19  Scalable(ampl, offset) { /* no-op */ }
20 
21 Oscillator::Oscillator(UnitGenerator & frequency, float ampl, float offset, float phase)
22  : UnitGenerator(),
23  Phased(frequency, phase),
24  Scalable(ampl, offset) { /* no-op */ }
25 
26 Oscillator::Oscillator(UnitGenerator & frequency, UnitGenerator & ampl, float offset, float phase)
27  : UnitGenerator(),
28  Phased(frequency, phase),
29  Scalable(ampl, offset) { /* no-op */ }
30 
32 
34  logMsg("an Oscillator");
36 }
37 
38 // Wavetable oscillator methods
39 // Constructors -- default creates a sine wave table
40 
41 //WavetableOscillator::WavetableOscillator() : Oscillator() {
42 // mWavetable.setSize(1, DEFAULT_WAVETABLE_SIZE);
43 // mInterpolate = kTruncate;
44 //// mWavetable.allocateBuffers();
45 //// fillSine();
46 //}
47 
48 WavetableOscillator::WavetableOscillator(float frequency, float ampl, float offset, float phase)
49  : Oscillator(frequency, ampl, offset, phase) {
51 // mWavetable.allocateBuffers();
53 // fillSine();
54 }
55 
56 //WavetableOscillator::WavetableOscillator(SampleBuffer samps, unsigned size) : Oscillator() {
57 // mWavetable.setSize(1, size);
58 // mInterpolate = kTruncate;
59 // setWaveform(samps, size);
60 //}
61 
63  mWavetable.setSize(1, wave.mNumFrames);
65  setWaveform(wave);
66 }
67 
68 ///< Destructor
69 
72 }
73 
74 // Plug in a waveform from a buffer or a simple sample array
75 
76 void WavetableOscillator::setWaveform(Buffer & wave, bool freBufs) {
77  if (freBufs)
81  if (mWavetable.buffers() == NULL)
83  for (unsigned i = 0; i < mWavetable.mNumChannels; i++)
84  mWavetable.setBuffer(i, wave.buffer(i));
90 }
91 
92 //void WavetableOscillator::setWaveform(SampleBuffer samps, unsigned size) {
93 // mWavetable.freeBuffers();
94 // mWavetable.setSize(1, size);
95 // mWavetable.setBuffer(0, samps);
96 // mWavetable.mMonoBufferByteSize = size * sizeof(sample);
97 // mWavetable.mIsPopulated = true;
98 // mWavetable.mAreBuffersZero = false;
99 // mWavetable.mAreBuffersAllocated = true;
100 // mWavetable.mDidIAllocateBuffers = false;
101 //}
102 
103 //// Shared buffer with a sine of length CGestalt::maxBufferFrames()
104 
105 static Buffer * sSineTable = 0;
106 
107 // Create the default wavetable -- 1 cycle of a sine
108 
110  if ( ! sSineTable) { // create shared sine table lazily
112  sSineTable->allocateBuffers(); // make space
114  float incr = CSL_TWOPI / DEFAULT_WTABLE_SIZE;
115  float accum = 0; // sine fill loop
116  for (unsigned i = 0; i < DEFAULT_WTABLE_SIZE; i++) {
117  *ptr++ = sinf(accum);
118  accum += incr;
119  }
120  }
122  mWavetable.setBuffer(0, sSineTable->monoBuffer(0)); // point to the shared sine waveform
123  mWavetable.mAreBuffersAllocated = true; // fib a bit
125 }
126 
127 // Oscillate a buffer-full of the stored waveform
128 
129 void WavetableOscillator::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
130  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
131  if ( ! mWavetable.mAreBuffersAllocated) // lazy sine init
132  fillSine();
133  SampleBuffer waveform = mWavetable.monoBuffer(0);
134  unsigned tableLength = mWavetable.mNumFrames;
135  float rateRecip = (float) tableLength / (float) mFrameRate;
136  float phase = mPhase; // get a local copy of the phase
137  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
138  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
139  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
140 #ifdef CSL_DEBUG
141  logMsg("WavetableOscillator nextBuffer");
142 #endif
143  if ( ! waveform)
144  return;
145  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
146  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
147  unsigned int index;
148  sample samp1, samp2;
149  float fraction;
150  switch (mInterpolate) {
151  case kTruncate: // truncating wavetable lookup
152  for (unsigned i = 0; i < numFrames; i++) { // sample loop
153  while (phase >= tableLength) // wrap-around phase
154  phase -= tableLength;
155  while (phase < 0) // wrap-around phase
156  phase += tableLength;
157  index = (unsigned int) floorf(phase); // truncate phase to an integer
158  samp1 = waveform[index]; //// WAVE TABLE ACCESS ////
159  *buffer++ = (samp1 * scaleValue) + offsetValue; // get and scale the table item (truncating look-up)
160  phase += (freqValue * rateRecip);
161  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
162  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
163  }
164  break;
165  case kLinear:
166  for (unsigned i = 0; i < numFrames; i++) { // sample loop
167  index = (unsigned int) floorf(phase);
168  fraction = phase - (float) index;
169  samp1 = waveform[index]; // get sample
170  if (index < (tableLength - 1))
171  samp2 = waveform[index+1]; // and next sample
172  else
173  samp2 = waveform[0];
174  samp1 += (samp2 - samp1) * fraction; // and interpolate linear-wise
175  *buffer++ = (samp1 * scaleValue) + offsetValue; // get and scale the table item (truncating look-up)
176  phase += (freqValue * rateRecip);
177  while (phase >= tableLength) // wrap-around phase
178  phase -= tableLength;
179  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
180  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
181  }
182  break;
183  default:
184  throw LogicError("Unimplemented truncation policy");
185  }
186  mPhase = phase; // store the temp phase back to the member variable
187 }
188 
189 // CompOrCacheOscillator implementation
190 
191 // Arguments are optional. Defaults to: Cache = false, freq = 220, phase = 0.0.
192 
193 CompOrCacheOscillator::CompOrCacheOscillator(bool whether, float frequency, float phase)
194  : WavetableOscillator(frequency, 1.0f, 0.0f, phase),
195  Cacheable(whether) { }
196 
197 // Create the default wavetable cache
198 
200  mUseCache = true;
203 }
204 
205 // nextBuffer either calls the inherited wavetable method, or does the computation on-demand here
206 
207 void CompOrCacheOscillator::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
208  if (mUseCache) // if we cache -- use the wavetable
209  return WavetableOscillator::nextBuffer(outputBuffer, outBufNum);
210  // otherwise do the synthesis on demand
211  outputBuffer.zeroBuffers();
212  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum);
213  this->nextWaveInto(buffer, outputBuffer.mNumFrames, false);
214 }
215 
216 // Sine methods
217 
218 // Constructor with variable number of arguments. Defaults to f = 220, amp = 1, offset & phase = 0.
219 
220 Sine::Sine(float frequency, float ampl, float offset, float phase)
221  : Oscillator(frequency, ampl, offset, phase) { }
222 
223 // the computed sine's nextBuffer
224 
225 void Sine::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
226  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
227  float rateRecip = CSL_TWOPI / mFrameRate;
228  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
229  float phase = mPhase;
230  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
231  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
232 #ifdef CSL_DEBUG
233  logMsg("Sine nextBuffer");
234 #endif
235  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
236  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
237 
238 // fprintf(stderr, " :%d: %5.3f", numFrames, scaleValue);
239  for (unsigned i = 0; i < numFrames; i++) { // sample loop
240  *buffer++ = (sinf(phase) * scaleValue) + offsetValue; // compute and store (scaled and offset) sine value
241  phase += (freqValue * rateRecip); // increment phase
242  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
243  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
244  }
245  while (phase >= CSL_TWOPI) // wraparound after 2pi radians
246  phase -= CSL_TWOPI;
247  mPhase = phase;
248 }
249 
250 // FSine methods
251 
252 // Constructor with variable number of arguments. Defaults to f = 220, amp = 1, offset & phase = 0.
253 
254 FSine::FSine(float frequency, float ampl, float offset, float phase)
255  : Oscillator(frequency, ampl, offset, phase) { }
256 
257 // the computed sine's nextBuffer
258 
259 void FSine::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
260  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
261  float rateRecip = CSL_TWOPI / mFrameRate;
262  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
263  float phase = mPhase;
264  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
265  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
266 #ifdef CSL_DEBUG
267  logMsg("Sine nextBuffer");
268 #endif
269  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
270  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
271 
272 // fprintf(stderr, " :%d: %5.3f", numFrames, scaleValue);
273  for (unsigned i = 0; i < numFrames; i++) { // sample loop
274  *buffer++ = (sinf(phase) * scaleValue) + offsetValue; // compute and store (scaled and offset) sine value
275  phase += (freqValue * rateRecip); // increment phase
276  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
277  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
278  }
279  while (phase >= CSL_TWOPI) // wraparound after 2pi radians
280  phase -= CSL_TWOPI;
281  mPhase = phase;
282 }
283 
284 // Sawtooth methods
285 
286 // Constructor with variable number of arguments. Defaults to f = 220, amp = 1, offset & phase = 0
287 
288 Sawtooth::Sawtooth(float frequency, float ampl, float offset, float phase)
289  : Oscillator(frequency, ampl, offset, phase) { }
290 
291 void Sawtooth::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
292  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
293  float rateRecip = 1.0f / mFrameRate;
294  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
295  float phase = mPhase;
296  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
297  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
298 #ifdef CSL_DEBUG
299  logMsg("Sine nextBuffer");
300 #endif
301  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
302  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
303 
304  for (unsigned i = 0; i < numFrames; i++) { // sample loop
305  *buffer++ = phase * scaleValue + offsetValue; // store the scaled and offset phase value
306  phase += (freqValue * rateRecip); // increment phase
307  if (phase >= 1.0f)
308  phase -= 2.0f;
309  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
310  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
311  }
312  mPhase = phase;
313 }
314 
315 // SquareSquare methods
316 
317 // Constructor with variable number of arguments. Defaults to f = 220, amp = 1, offset & phase = 0
318 
319 Square::Square(float frequency, float ampl, float offset, float phase)
320  : Oscillator(frequency, ampl, offset, phase) { }
321 
322 void Square::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
323  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
324  float rateRecip = 1.0f / mFrameRate;
325  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
326  float phase = mPhase;
327  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
328  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
329 #ifdef CSL_DEBUG
330  logMsg("Sine nextBuffer");
331 #endif
332  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
333  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
334 
335  for (unsigned i = 0; i < numFrames; i++) { // sample loop
336  *buffer++ = ((phase > 0.0) ? 1.0f : -1.0f) * scaleValue + offsetValue; // store +- 1
337  phase += (freqValue * rateRecip); // increment phase
338  if (phase >= 1.0f)
339  phase -= 2.0f;
340  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
341  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
342  }
343  mPhase = phase;
344 }
345 
346 // Impulse methods
347 
349 
350 Impulse::Impulse(float delay) : Oscillator() { mCounter = (int) delay; }
351 
352 Impulse::Impulse(float frequency, float ampl)
353  : Oscillator(frequency, ampl) { mCounter = 0; }
354 
355 Impulse::Impulse(float frequency, float ampl, float offset)
356  : Oscillator(frequency, ampl, offset) { mCounter = 0; }
357 
358 Impulse::Impulse(float frequency, float ampl, float offset, float phase)
359  : Oscillator(frequency, ampl, offset, phase) { mCounter = 0; }
360 
361 // the computed Impulse's next_buffer
362 
363 void Impulse::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
364  SampleBuffer buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
365  unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
366  unsigned i, j;
367  unsigned count = mCounter;
368  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value as above
369  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values as above
370 #ifdef CSL_DEBUG
371  logMsg("Sine nextBuffer");
372 #endif
373  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
374  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
375 
376  if (count < 0) { // Impulse is done. Output only zeros.
377  for (i = 0; i < numFrames; i++)
378  *buffer++ = 0;
379  } else if (count < numFrames) {
380  for (i = 0; i < count; i++)
381  *buffer++ = 0;
382  *buffer++ = scaleValue;
383  for (j = count+1; j < numFrames; j++)
384  *buffer++ = 0;
385  } else {
386  for (i = 0; i < numFrames; i++)
387  *buffer++ = 0;
388  }
389  mCounter = count - numFrames;
390 }
391 
392 // SumOfSines
393 
395 
396 SumOfSines::SumOfSines(float frequency)
397  : CompOrCacheOscillator(false, frequency) { }
398 
399 SumOfSines::SumOfSines(PartialDescriptionMode format, unsigned partialCount, ...)
401  float num=0, amp=0, pha=0;
402  Partial * p;
403  va_list ap;
404  va_start(ap, partialCount);
405  for (unsigned i = 0; i < partialCount; i++) {
406  switch (format) {
407  case kFrequency: // if 1 term per partial, it's the amplitude
408  num = (float) (i + 1);
409  amp = va_arg(ap, double);
410  pha = 0.0;
411  break;
412  case kFreqAmp: // if 2 terms per partial, they're num, ampl
413  num = va_arg(ap, double);
414  amp = va_arg(ap, double);
415  pha = 0.0;
416  break;
417  case kFreqAmpPhase: // if 3 terms per partial, they're num, ampl
418  num = va_arg(ap, double);
419  amp = va_arg(ap, double);
420  pha = va_arg(ap, double);
421  break;
422  }
423  p = new Partial;
424  p->number = num;
425  p->amplitude = amp;
426  p->phase = pha;
427  mPartials.push_back(p);
428  }
429  va_end(ap);
430 }
431 
432 // given a SHARC spectrum
433 #include "SHARC.h"
434 
436  Partial * harm;
437  for (unsigned i = 0; i < spect._num_partials; i++) {
438  harm = spect._partials[i];
439 // fprintf(stderr, "\t%g @ %.5f @ %.5f\n", harm->number, harm->amplitude, harm->phase);
440  this->addPartial(harm->number, harm->amplitude, harm->phase);
441  }
442  this->createCache(); // make the cached wavetable
443 }
444 
445 // 1/f spectrum + noise
446 
447 SumOfSines::SumOfSines(unsigned numHarms, float noise) {
448  for (unsigned i = 0; i < numHarms; i++) {
449  float ampl = fRandV(noise) / (float) (i + 2);
450  float phas = fRandV(CSL_PI);
451 // fprintf(stderr, "\t%d @ %.5f @ %.5f\n", i, ampl, phas);
452  this->addPartial(i, ampl, phas);
453  }
454  this->createCache(); // make the cached wavetable
455 }
456 
457 SumOfSines::SumOfSines(float frequency, unsigned numHarms, float noise)
458  : CompOrCacheOscillator(false, frequency) {
459  for (unsigned i = 0; i < numHarms; i++) {
460  this->addPartial(i, fRandM(0.5f, 1.3f) / (float) i, fRandV(CSL_PI));
461  }
462  this->createCache(); // make the cached wavetable
463 }
464 
465 // Methods to add partials
466 
467 void SumOfSines::addPartial(float nu, float amp) {
468  Partial * p = new Partial;
469  p->number = nu;
470  p->amplitude = amp;
471  p->phase = 0.0;
472  mPartials.push_back(p);
473 }
474 
475 void SumOfSines::addPartial(float nu, float amp, float phase) {
476  Partial * p = new Partial;
477  p->number = nu;
478  p->amplitude = amp;
479  p->phase = phase;
480  mPartials.push_back(p);
481 }
482 
484  mPartials.push_back(pt);
485 }
486 
487 void SumOfSines::addPartials(unsigned num_p, Partial ** pt) {
488  Partial ** pt_ptr = pt;
489  for (unsigned i = 0; i < num_p; i++)
490  mPartials.push_back(*pt_ptr++);
491 }
492 
493 
494 void SumOfSines::addPartials(int argc, void ** argv) {
495  float ** v_ptr = (float ** ) argv;
496  int i = 0;
497  while (i < argc) {
498  Partial * part = new Partial;
499  part->number = * v_ptr[i++];
500  part->amplitude = * v_ptr[i++];
501  mPartials.push_back(part);
502  }
503 }
504 
506  mPartials.clear();
507 }
508 
509 // Do sum-of-sines additive synthesis into the given buffer
510 
511 void SumOfSines::nextWaveInto(SampleBuffer dest, unsigned count, bool oneHz) {
512  float incr, t_incr, phase, ampl;
513  SampleBuffer out_ptr;
514  unsigned numFrames = count; // the number of frames to fill
515  DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value
516  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
517 
518  if (oneHz) { // if we're creating a wavetable
519  incr = CSL_TWOPI / (float) count;
520  } else { // otherwise compute phase increment scale
521  incr = CSL_TWOPI / (float) mFrameRate;
522  LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
523  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
524  }
525  for (unsigned i = 0; i < mPartials.size(); i++) { // partials loop
526  Partial * p = mPartials[i];
527  out_ptr = dest;
528  phase = p->phase;
529  t_incr = incr * p->number;
530  ampl = p->amplitude;
531 // fprintf(stderr, "\t\tp%d = i %g : a %g : p %g\n", i, t_incr, ampl, phase);
532  if (oneHz) {
533  for (unsigned j = 0; j < numFrames; j++) { // sample loop
534  *out_ptr++ += (sinf(phase) * ampl);
535  phase += t_incr;
536  }
537  } else {
538  for (unsigned j = 0; j < numFrames; j++) { // sample loop
539  *out_ptr++ += (sinf(phase) * ampl * scaleValue) + offsetValue;
540  phase += (t_incr * freqValue);
541  UPDATE_PHASED_CONTROLS; // update the dynamic frequency
542  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
543 // if (j == 1) fprintf(stderr, "\t\t\t%g : %g : %g\n", freqValue, scaleValue, offsetValue);
544  }
545  }
546  if ( ! oneHz) {
547  freqPort->resetPtr(); // reset control pointers after each loop through a partial
548  scalePort->resetPtr();
549  offsetPort->resetPtr();
550  freqValue = freqPort->nextValue();
551  scaleValue = scalePort->nextValue();
552  offsetValue = offsetPort->nextValue();
553  }
554  while (phase > CSL_TWOPI) // wrap phase here
555  phase -= CSL_TWOPI;
556  p->phase = phase;
557  }
558 }
559 
561  unsigned siz = mPartials.size();
562  logMsg("a SumOfSines: %d partials", siz);
563  for (unsigned i = 0; i < siz; i++)
564  fprintf(stderr, "\tP: %g, %g, %g\n", mPartials[i]->number, mPartials[i]->amplitude, mPartials[i]->phase);
565  Scalable::dump();
566 }