CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
31 Oscillator::~Oscillator() { }
32
33 void Oscillator::dump() {
34 logMsg("an Oscillator");
35 Scalable::dump();
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) {
50 mWavetable.setSize(1, DEFAULT_WAVETABLE_SIZE);
51 // mWavetable.allocateBuffers();
52 mInterpolate = kTruncate;
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
62 WavetableOscillator::WavetableOscillator(Buffer & wave) : Oscillator() {
63 mWavetable.setSize(1, wave.mNumFrames);
64 mInterpolate = kTruncate;
65 setWaveform(wave);
66 }
67
68 ///< Destructor
69
70 WavetableOscillator::~WavetableOscillator() {
71 mWavetable.freeBuffers();
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)
78 mWavetable.freeBuffers();
79 mWavetable.mNumChannels = wave.mNumChannels;
80 mWavetable.mNumFrames = wave.mNumFrames;
81 if (mWavetable.buffers() == NULL)
82 mWavetable.setBuffers(new SampleBuffer[mNumChannels]);
83 for (unsigned i = 0; i < mWavetable.mNumChannels; i++)
84 mWavetable.setBuffer(i, wave.buffer(i));
85 mWavetable.mMonoBufferByteSize = wave.mMonoBufferByteSize;
86 mWavetable.mIsPopulated = wave.mIsPopulated;
87 mWavetable.mAreBuffersZero = wave.mAreBuffersZero;
88 mWavetable.mAreBuffersAllocated = wave.mAreBuffersAllocated;
89 mWavetable.mDidIAllocateBuffers = false;
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
109 void WavetableOscillator::fillSine() {
110 if ( ! sSineTable) { // create shared sine table lazily
111 sSineTable = new Buffer(1, DEFAULT_WTABLE_SIZE);
112 sSineTable->allocateBuffers(); // make space
113 SampleBuffer ptr = sSineTable->monoBuffer(0);
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 }
121 mWavetable.setSize(1, DEFAULT_WTABLE_SIZE);
122 mWavetable.setBuffer(0, sSineTable->monoBuffer(0)); // point to the shared sine waveform
123 mWavetable.mAreBuffersAllocated = true; // fib a bit
124 mWavetable.mDidIAllocateBuffers = false;
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
199 void CompOrCacheOscillator::createCache(void) {
200 mUseCache = true;
201 mWavetable.allocateBuffers();
202 this->nextWaveInto(mWavetable.monoBuffer(0), mWavetable.mNumFrames, 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
348 Impulse::Impulse() : Oscillator() { mCounter = 0; }
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
394 SumOfSines::SumOfSines() : CompOrCacheOscillator() { }
395
396 SumOfSines::SumOfSines(float frequency)
397 : CompOrCacheOscillator(false, frequency) { }
398
399 SumOfSines::SumOfSines(PartialDescriptionMode format, unsigned partialCount, ...)
400 : CompOrCacheOscillator(false) {
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
435 SumOfSines::SumOfSines(SHARCSpectrum & spect) {
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
483 void SumOfSines::addPartial(Partial * pt) {
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
505 void SumOfSines::clearPartials() {
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
560 void SumOfSines::dump() {
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 }