CSL  6.0
Envelope.cpp
Go to the documentation of this file.
1 //
2 // Envelope.cpp -- Implementation of LineSegment and Envelope classes
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "Envelope.h"
7 #include <stdlib.h>
8 #include <iostream>
9 #include <math.h>
10 
11 //#define CSL_DEBUG
12 
13 using namespace csl;
14 
15 /// LineSegment class
16 
17 /// Constructors
18 
20  UnitGenerator(), mMode(kLine), mCurrentValue(0), mCurrentFrame(0) { }
21 
22 LineSegment::LineSegment(float d, float s, float e, LineMode mode) :
23  UnitGenerator(),
24  mStart(s), mEnd(e), mDuration(d), mMode(mode), mCurrentValue(s), mCurrentFrame(0) {
25  if (mode == kExpon) {
26  if (mStart == 0) {
27  mStart = 0.00001f; // Arbitrary small value.
28 // logMsg("Start value can't be '0' for exponential segments. Corrected to be 0.00001.");
29  }
30  if (mEnd == 0) {
31  mEnd = 0.00001f;
32 // logMsg("End value can't be '0' for exponential segments. Corrected to be 0.00001.");
33  }
34  }
35 }
36 
37 /// Reset method
38 
41  mCurrentFrame = 0;
42 }
43 
45  logMsg("\tLineSegment: %g to %g in %g (%s)", mStart, mEnd, mDuration,
46  (mMode == kLine ? "linear" : "exponential"));
47 }
48 
49 void LineSegment::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
50  nextBuffer(outputBuffer, outBufNum, 0, 0);
51 }
52 
53 void LineSegment::nextBuffer(Buffer &outputBuffer, unsigned outBufNum, Port * scalePort, Port * offsetPort)
54  throw (CException) {
55  unsigned i;
56  float rate = (float) mFrameRate;
57  unsigned numFrames = outputBuffer.mNumFrames;
58  SampleBuffer outPtr = outputBuffer.buffer(outBufNum);
59  float scaleValue = 1, offsetValue = 0; // used for dynamic input;
60 
61  /// calculate the increment for the linear interpolation, the number of frames to calculate
62  /// and the number of frames that are constant (at the end of the interpolations)
63  unsigned numFramesToCalc = (int)(mDuration * rate) - mCurrentFrame;
64  unsigned constantFrames;
65 
66  /// This test to see if we're at the end works for now, but we should use a bool to check if we are done
67  /// in case mCurrentFrame loops
68  if (numFramesToCalc <= 0) {
69  numFramesToCalc = 0;
70  constantFrames = numFrames;
71  mCurrentValue = mEnd;
72  } else {
73  if (numFramesToCalc > numFrames)
74  numFramesToCalc = numFrames;
75  constantFrames = numFrames - numFramesToCalc;
76  }
77  float currentValue = mCurrentValue;
78  float increment;
79 #ifdef CSL_DEBUG
80 // logMsg("LineSegment nextBuffer");
81 #endif
82  switch(mMode) {
83  case kLine:
84  increment = (mEnd - mStart) / (mDuration * rate);
85  for (i = 0; i < numFramesToCalc; i++) { ///< Generate the interpolated frames
86  CHECK_UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
87  *outPtr++ = (currentValue * scaleValue) + offsetValue;
88  currentValue += increment;
89  }
90  break;
91  case kExpon:
92  increment = pow(mEnd / mStart, 1/(mDuration * rate));
93  for (i = 0; i < numFramesToCalc; i++) { ///< Generate the interpolated frames
94  CHECK_UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
95  *outPtr++ = (currentValue * scaleValue) + offsetValue;
96  currentValue *= increment;
97  }
98  break;
99  default:
100  break;
101  }
102  for (i = 0; i < constantFrames; i++) { ///< Generate the constant frames
103  CHECK_UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
104  *outPtr++ = (mEnd * scaleValue) + offsetValue;
105  }
106  if (mCurrentValue != mEnd) {
107  mCurrentFrame += numFrames; ///< if we're not already at the end increment my internal counters
108  mCurrentValue = currentValue;
109  }
110 // fprintf(stderr, " _%5.3f_ ", (currentValue * scaleValue) + offsetValue);
111 }
112 
113 /// Envelope class
114 
115 /// Lots of useful constructors
116 
117 Envelope::Envelope(LineMode mode, float t, float x1, float y1, float x2, float y2, float x3, float y3,
118  float x4, float y4, float x5, float y5, float x6, float y6)
119  : UnitGenerator(), Scalable(1, 0), mDuration(t) {
120  mSegmentMap[x1] = new LineSegment(0, 0, y1, mode);
121  if (x2 != 0) mSegmentMap[x2] = new LineSegment(0, 0, y2, mode);
122  if (x3 != 0) mSegmentMap[x3] = new LineSegment(0, 0, y3, mode);
123  if (x4 != 0) mSegmentMap[x4] = new LineSegment(0, 0, y4, mode);
124  if (x5 != 0) mSegmentMap[x5] = new LineSegment(0, 0, y5, mode);
125  if (x6 != 0) mSegmentMap[x6] = new LineSegment(0, 0, y6, mode);
126  this->createSegments();
127 }
128 
129 Envelope::Envelope(LineMode mode, float t, unsigned int size, float x[], float y[])
130  : UnitGenerator(), Scalable(1, 0), mDuration(t) {
131  for (unsigned int i = 0; i < size; i++)
132  mSegmentMap[x[i]] = new LineSegment(0, 0, y[i], mode);
133  this->createSegments();
134 }
135 
136 Envelope::Envelope(float t, float x1, float y1, float x2, float y2, float x3, float y3,
137  float x4, float y4, float x5, float y5, float x6, float y6)
138  : UnitGenerator(), Scalable(1.0f, 0.0f), mDuration(t) {
139  mSegmentMap[x1] = new LineSegment(0, 0, y1);
140  if (x2 != 0) mSegmentMap[x2] = new LineSegment(0, 0, y2);
141  if (x3 != 0) mSegmentMap[x3] = new LineSegment(0, 0, y3);
142  if (x4 != 0) mSegmentMap[x4] = new LineSegment(0, 0, y4);
143  if (x5 != 0) mSegmentMap[x5] = new LineSegment(0, 0, y5);
144  if (x6 != 0) mSegmentMap[x6] = new LineSegment(0, 0, y6);
145  this->createSegments();
146 }
147 
148 Envelope::Envelope(float t, unsigned int size, float x[], float y[])
149  : UnitGenerator(), Scalable(1, 0), mDuration(t) {
150  for (unsigned int i = 0; i < size; i++)
151  mSegmentMap[x[i]] = new LineSegment(0, 0, y[i]);
152  this->createSegments();
153 }
154 
156  for (unsigned i = 0; i < mSegmentMap.size(); ++i)
157  delete mSegments[i];
158  if (mValues)
159  delete[] mValues;
160  if (mSegments)
161  free(mSegments);
162 }
163 
165  mValues = new float[mSegmentMap.size()];
166  mSegments = (LineSegment ** ) malloc(mSegmentMap.size() * (sizeof(char *)));
168 }
169 
171  unsigned i = 0;
172  mSize = mSegmentMap.size();
173  Breakpoints::iterator idx;
174  // The very first segment is not really used.
175  // The number of segments is always 1 less than the number of points.
176  for (idx = mSegmentMap.begin(); idx != mSegmentMap.end(); ++idx) {
177  mValues[i] = idx->first;
178  mSegments[i] = idx->second;
179  i++;
180  }
181  mSegments[0]->setStart(mSegments[0]->end());
182  mSegments[0]->setDuration(float(mValues[0]));
183  for (i = 1; i < mSize; ++i) {
184  mSegments[i]->setStart(mSegments[i - 1]->end());
185  mSegments[i]->setDuration(float(mValues[i] - mValues[i - 1]));
186  }
187  mCurrentMark = mDuration; // set to end
188 }
189 
190 /////////////////////// Operations ///////////////////////////////////
191 
192 void Envelope::addBreakpoint(float startTime, float tvalue) {
193  mSegmentMap[startTime] = new LineSegment(0, 0, tvalue);
194  LineSegment **tempLinsegPtr = mSegments;
195  float *tempPtr = mValues;
196 
197  this->createSegments();
198  if (startTime > mDuration)
199  mDuration = startTime;
200  if (tempPtr)
201  delete[] tempPtr;
202  if (tempLinsegPtr)
203  free(tempLinsegPtr);
204 }
205 
207  for (unsigned i = 0; i < mSize; i++)
208  mSegments[i]->setMode(mode);
209 }
210 
212 // float diff = mCurrentMark - mDuration;
213 // if ((diff > 0.0) && (diff < 0.1))
214 // fprintf(stderr, " %5.4f = %s\n", diff, (mCurrentMark < mDuration) ? "true" : "false");
215  return (mCurrentMark < mDuration);
216 }
217 
218 /// Scaling operations
219 
220 void Envelope::setDuration(float d) {
221  //if ((mDuration == 0.0f) || (! isnormal(mDuration))) {
222  if (mDuration == 0.0f) {
223  logMsg(kLogError, "Impossible env dur");
224  throw RunTimeError("Impossible env dur");
225  }
226  this->scaleTimes(d / mDuration);
227 }
228 
229 void Envelope::scaleTimes(float s) {
230  if (s != 1) {
231  for (unsigned i = 0; i < mSize; ++i) {
232  mSegmentMap.erase(mValues[i]); // Erase old values.
233  mValues[i] *= s; // update the stored values to the new scaled ones.
234  }
235  for (unsigned i = 0; i < mSize; ++i) {
236  mSegmentMap[mValues[i]] = mSegments[i]; // Add the new values to the map
237  mSegments[i]->reset(); // Reset all segments.
238  }
239  }
240  mDuration *= s;
242 }
243 
244 // scale values so that the env's max is s
245 
246 void Envelope::scaleValues(float s) {
247  float maxV = 0.0f;
248  for (unsigned i = 0; i < mSize; ++i) {
249  LineSegment * seg = mSegments[i];
250  if (seg->start() > maxV) maxV = seg->start();
251  if (seg->end() > maxV) maxV = seg->end();
252  }
253  float scale = s / maxV;
254  for (unsigned i = 0; i < mSize; ++i) {
255  LineSegment * seg = mSegments[i];
256  seg->setStart(seg->start() * scale);
257  seg->setEnd(seg->end() * scale);
258  }
259 }
260 
261 /// Pretty-printer
262 
264  logMsg("Envelope Duration = %g", mDuration);
265  fprintf(stderr, "\tat 0 seconds \t\t");
266  mSegments[0]->dump();
267  for (unsigned i = 1; i < mSize; i++) {
268  fprintf(stderr, "\tat %g seconds \t\t", mValues[i-1]);
269  mSegments[i]->dump();
270  }
271  Scalable::dump();
272 }
273 
274 /// Reset time to 0.0 to restart envelope
275 
277  mCurrentMark = 0.0f;
278  for (unsigned i = 0; i < mSize; ++i)
279  mSegments[i]->reset();
280 }
281 
282 // trigger means reset
283 
285  reset();
286 }
287 
288 //
289 // Next buffer calculation -- Here's where the work gets done
290 //
291 
292 void Envelope::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
293  SampleBuffer outPtr = outputBuffer.buffer(outBufNum);
294  unsigned numFrames = outputBuffer.mNumFrames;
295  unsigned i, tempFrames;
296  float rate = mFrameRate;
297  float endMark, x;
298  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
299 #ifdef CSL_DEBUG
300 // logMsg("Envelope nextBuffer");
301 #endif
302  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
303  // if the envelope is finished, just write the final value into the buffer
304  if (mCurrentMark >= mDuration) {
305  x = mSegments[mSize - 1]->end(); // mPoints[mSize - 1]->y;
306  for (i = 0; i < numFrames; i++) {
307  *outPtr++ = (x * scaleValue) + offsetValue;
308  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
309  }
310  return;
311  } // find out what segment we're in and let the segment fill the buffer
312 // if (mCurrentMark < mValues[0]) {
313 //
314 // }
315  for (i = 0; i < mSize; ++i) {
316  x = mValues[i];
317  if (mCurrentMark < x) {
318  endMark = mCurrentMark + ((float)numFrames / rate);
319  if (endMark < x) { // if the current next_buffer request all falls into one line segment
320  mSegments[i]->nextBuffer(outputBuffer, outBufNum, scalePort, offsetPort);
321  mCurrentMark += ((float) (numFrames + 1) / rate);
322  // fprintf(stderr, "E: %5.3f", *outPtr);
323  return;
324  } else { // if the current next_buffer request spans line segments, go
325  // to the end of this line segment and call nextBuffer again
326 #ifdef CSL_DEBUG
327  logMsg("\t\tEnvelope crossing: current mark: %g point: %g @ %g ls: %g to %g in %g",
328  mCurrentMark, mValues[i], mSegments[i]->end(),
329  mSegments[i]->start(), mSegments[i]->end(), mSegments[i]->duration());
330 #endif
331  tempFrames = (unsigned) ((mValues[i] - mCurrentMark) * rate);
332  outputBuffer.mNumFrames = tempFrames;
333  // get the first segment
334  mSegments[i]->nextBuffer(outputBuffer, outBufNum, scalePort, offsetPort);
335 
336  // update pointers
337  mCurrentMark += ((float) (numFrames + 1) / rate);
338  outputBuffer.setBuffer(outBufNum, outputBuffer.buffer(outBufNum) + tempFrames);
339  outputBuffer.mNumFrames = numFrames - tempFrames;
340  // call myself recursively
341  this->nextBuffer(outputBuffer, outBufNum);
342  // clean up
343  mCurrentMark += ((float) (numFrames + 1) / rate);
344  outputBuffer.setBuffer(outBufNum, outPtr);
345  outputBuffer.mNumFrames = numFrames;
346  if (i == (mSize - 1)) {
347 #ifdef CSL_DEBUG
348  logMsg("Envelope finished");
349 #endif
350  mCurrentMark = mDuration;
351  }
352  return;
353  }
354  }
355  }
356  logMsg(kLogError, "Envelope nextBuffer: it shouldn't get here %f", rate);
357  this->dump();
358  return; // shouldn't ever get here (THROW AN EXCEPTION IF CONTROL GETS HERE!)
359 }
360 
361 /// ~~~~~~~ Atack / Decay / Sustain / Release Envelope ~~~~~~~~~~~
362 
363 /// Minimal version - ADSR . . . call the Super constructor, passing the appropriate points.
364 
365 csl::ADSR::ADSR(LineMode mode, float t, float a, float d, float s, float r)
366  : Envelope(mode, t, 0.0, 0.0, a, 1.0, a + d, s, t - r, s, t, 0.0) { };
367 
368 /// with initial delay - IADSR
369 
370 csl::ADSR::ADSR(LineMode mode, float t, float i, float a, float d, float s, float r)
371  : Envelope(mode, t, i, 0.0, i + a, 1.0, i + a + d, s, t - r, s, t, 0.0) { };
372 
373 /// Minimal version - ADSR . . . call the Super constructor, passing the appropriate points.
374 
375 csl::ADSR::ADSR(float t, float a, float d, float s, float r)
376  : Envelope(t, 0.0, 0.0, a, 1.0, a + d, s, t - r, s, t, 0.0) { };
377 
378 /// with initial delay - IADSR
379 
380 csl::ADSR::ADSR(float t, float i, float a, float d, float s, float r)
381  : Envelope(t, i, 0.0, i + a, 1.0, i + a + d, s, t - r, s, t, 0.0) { };
382 
383 /// Operations --
384 
385 void csl::ADSR::setDuration(float d) {
386 // if (d <= mValues[3])
388 // else {
389 // this->dump();
390 // float oldD = mDuration - mValues[3];
391 // mDuration = d;
392 // mSegmentMap[mDuration - oldD] = mSegmentMap[mValues[3]];
393 // mSegmentMap.erase(mValues[3]);
394 // this->calculateSegments();
395 // this->dump();
396 // }
397 }
398 
399 void csl::ADSR::setDelay(float del) {
400  mSegmentMap[del] = mSegmentMap[mValues[0]]; // Add a new "initial delay key" and then remove the old one.
401  mSegmentMap[del + mSegments[1]->duration()] = mSegmentMap[mValues[1]]; // update the value of the next
402  if (mValues[0] != del) { // If value is different, then erase the old value.
403  mSegmentMap.erase(mValues[0]);
404  mSegmentMap.erase(mValues[1]);
405  }
406  this->calculateSegments();
407 }
408 
409 void csl::ADSR::setAttack(float attack) {
410  mSegmentMap[mValues[0] + attack] = mSegmentMap[mValues[1]]; // Add a new "attack key" and then remove the old one.
411  mSegmentMap[mValues[0] + attack + mSegments[2]->duration()] = mSegmentMap[mValues[2]]; // update the value of the next
412  if (mValues[1] != mValues[0] + attack) { // If value is different, then erase the old value.
413  mSegmentMap.erase(mValues[1]);
414  mSegmentMap.erase(mValues[2]);
415  }
416  this->calculateSegments();
417 }
418 
419 void csl::ADSR::setDecay(float decay) {
420  mSegmentMap[mValues[1] + decay] = mSegmentMap[mValues[2]];
421  if (mValues[2] != mValues[1] + decay)
422  mSegmentMap.erase(mValues[2]);
423  this->calculateSegments();
424 }
425 
426 void csl::ADSR::setSustain(float sustain) {
427  mSegments[2]->setEnd(sustain);
428  mSegments[3]->setEnd(sustain);
429  this->calculateSegments();
430 }
431 
432 void csl::ADSR::setRelease(float trelease) {
433  mSegmentMap[mDuration - trelease] = mSegmentMap[mValues[3]];
434  if (mValues[3] != mDuration - trelease)
435  mSegmentMap.erase(mValues[3]);
436  this->calculateSegments();
437 }
438 
439 // Trigger the release segment
440 
441 void csl::ADSR::release(void) {
442  mCurrentMark = mValues[3];
443 }
444 
445 /// ~~~~~~~ Atack / Release Envelope ~~~~~~~~~~~
446 
447 /// Minimal version - AR
448 
449 AR::AR(LineMode mode, float t, float a, float r)
450  : Envelope(mode, t, 0.0, 0.0, a, 1.0, t - r, 1.0, t, 0.0) { };
451 
452 /// with initial delay - I-AR
453 
454 AR::AR(LineMode mode, float t, float i, float a, float r)
455  : Envelope(mode, t, i, 0.0, i + a, 1.0, t - r, 1.0, t, 0.0) { };
456 
457 /// Minimal version - AR
458 
459 AR::AR(float t, float a, float r)
460  : Envelope(t, 0.0, 0.0, a, 1.0, t - r, 1.0, t, 0.0) { };
461 
462 /// with initial delay - I-AR
463 
464 AR::AR(float t, float i, float a, float r)
465  : Envelope(t, i, 0.0, i + a, 1.0, t - r, 1.0, t, 0.0) { };
466 
467 /// Operations
468 
469 void AR::setDuration(float d) {
470 // if (d <= mValues[2])
472 // else {
473 // float oldD = mDuration - mValues[2];
474 // mDuration = d;
475 // mSegmentMap[mDuration - oldD] = mSegmentMap[mValues[2]];
476 // mSegmentMap.erase(mValues[2]);
477 // this->calculateSegments();
478 // }
479 }
480 
481 void AR::setDelay(float del) {
482  mSegmentMap[del] = mSegmentMap[mValues[0]];
483  if (mValues[0] != del) // If value is different, then erase the old value.
484  mSegmentMap.erase(mValues[0]);
485  this->calculateSegments();
486 }
487 
488 void AR::setAttack(float attack) {
489  mSegmentMap[mValues[0] + attack] = mSegmentMap[mValues[1]];
490  if (mValues[1] != mValues[0] + attack) // If value is different, then erase the old value.
491  mSegmentMap.erase(mValues[1]);
492  this->calculateSegments();
493 }
494 
495 void AR::setRelease(float trelease) {
496  mSegmentMap[mDuration - trelease] = mSegmentMap[mValues[2]];
497  if (mValues[2] != mDuration - trelease)
498  mSegmentMap.erase(mValues[2]);
499  this->calculateSegments();
500 }
501 
502 void AR::setAll(float d, float a, float r) {
503  mDuration = d;
504  mSegmentMap[mValues[0] + a] = mSegmentMap[mValues[1]];
505  mSegmentMap[mDuration - r] = mSegmentMap[mValues[2]];
506  mSegmentMap[mDuration] = mSegmentMap[mValues[3]];
507  if (mValues[2] != a) mSegmentMap.erase(mValues[1]);
508  if (mValues[3] != r) mSegmentMap.erase(mValues[2]);
509  if (mValues[4] != d) mSegmentMap.erase(mValues[3]);
510 
511  this->calculateSegments();
512 }
513 
514 /// trigger the release segment
515 
516 void AR::release(void) {
517  mCurrentMark = mValues[2];
518 }
519 
520 
521 /// ~~~~~ Triangle class ~~~~~
522 
523 // simple constructor
524 
525 Triangle::Triangle(LineMode mode, float t, float a)
526  : Envelope(mode, t, 0.0, 0.0, t/2, a, t, 0.0) { }
527 
528 // versions with initial delay segments
529 
530 Triangle::Triangle(LineMode mode, float t, float i, float a)
531  : Envelope(mode, t, i, 0.0, (t-i)/2, a, t, 0.0) { }
532 
533 // simple constructor
534 
535 Triangle::Triangle(float t, float a)
536  : Envelope(t, 0.0, 0.0, t/2, a, t, 0.0) { }
537 
538 // versions with initial delay segments
539 
540 Triangle::Triangle(float t, float i, float a)
541  : Envelope(t, i, 0.0, (t-i)/2, a, t, 0.0) { }
542 
543 
544 /// ~~~~~~~~ RandEnvelope envelope class ~~~~~~~
545 
546 // Constructors
547 
548 RandEnvelope::RandEnvelope(float frequency, float amplitude, float offset, float step)
549  : Envelope(), mFrequency(frequency), mAmplitude(amplitude),
550  mStep(step), mOffset(offset), mWalk(false) {
551  mSize = 0;
552  if (mStep == 0)
553  mStep = mAmplitude / 2.0;
554  initSegment();
555  mValues = 0;
556  mSegments = 0;
557 }
558 
559 // Prepare by putting an ending value in the line segment
560 
562  mLastVal = fRandZ() * 2.0 - 1.0;
564  nextSegment();
565 }
566 
567 // To choose the next segment
568 
570  float next = 0.0f, randVal;
572  if ( ! mWalk) { // pick a new random and constrain it to the proper range
573  randVal = (fRandZ() * 2.0 - 1.0) * (mStep / mAmplitude);
574  next = mLastVal + randVal;
575  if (next > 1.0)
576  next = mLastVal - randVal;
577  if (next < -1.0)
578  next = mLastVal + randVal;
579  mLastVal = next;
580  next = next * mAmplitude + mOffset;
581 // logMsg("RE %5.3f\n", next);
582  } else {
583  // what to do here?
584  }
585  mSegment.setEnd(next);
586  mSegment.setDuration((float) (1.0 / mFrequency));
587  mSegment.reset();
588  mCurrentIndex = 0;
589  mSegmentLength = (unsigned) (mSegment.duration() * mFrameRate);
590 }
591 
592 // NextBuffer for rand
593 
594 void RandEnvelope::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
595  SampleBuffer outPtr = outputBuffer.buffer(outBufNum);
596  unsigned numFrames = outputBuffer.mNumFrames;
597  unsigned endMark = mCurrentIndex + numFrames;
598  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
599 
600  // if we can answer the request with the current line segment...
601  if (endMark < mSegmentLength) {
602  mSegment.nextBuffer(outputBuffer, outBufNum, scalePort, offsetPort);
603  mCurrentIndex += numFrames;
604  return;
605  }
606  // else, do some, then create update the line segment
607  unsigned tempFrames = mSegmentLength - mCurrentIndex;
608  outputBuffer.mNumFrames = tempFrames;
609  mSegment.nextBuffer(outputBuffer, outBufNum, scalePort, offsetPort);
610  // update pointers
611  nextSegment();
612  outputBuffer.setBuffer(outBufNum, outputBuffer.buffer(outBufNum) + tempFrames);
613  outputBuffer.mNumFrames = numFrames - tempFrames;
614  // call the next line segment (must be long enough to fill the buffer)
615  mSegment.nextBuffer(outputBuffer, outBufNum, scalePort, offsetPort);
616  // clean up
617  mCurrentIndex = numFrames - tempFrames;
618  outputBuffer.setBuffer(outBufNum, outPtr);
619  outputBuffer.mNumFrames = numFrames;
620  return;
621 }
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
Definition: CSL_Types.h:194
void dump()
reset internal time to restart envelope
Definition: Envelope.cpp:44
float end()
Returns the target value of the line segment.
Definition: Envelope.h:52
#define UPDATE_SCALABLE_CONTROLS
Definition: CSL_Core.h:444
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
AR()
Various Constructors.
Definition: Envelope.h:202
float mDuration
Total duration, typically in seconds.
Definition: Envelope.h:118
virtual void dump()
Pretty-printer.
Definition: Envelope.cpp:263
unsigned mCurrentFrame
cache
Definition: Envelope.h:77
Triangle()
Various Constructors.
Definition: Envelope.h:230
static unsigned mFrameRate
default sample rate (tested up to 96000)
Definition: CGestalt.cpp:32
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
virtual void trigger()
reset internal time to restart envelope
Definition: Envelope.cpp:284
virtual void setDuration(float d)
set/scale durations
Definition: Envelope.cpp:220
LineSegment mSegment
single line segment
Definition: Envelope.h:278
#define CHECK_UPDATE_SCALABLE_CONTROLS
Definition: CSL_Core.h:448
unsigned mFrameRate
trigger ignored here
Definition: CSL_Core.h:288
void setAttack(float attack)
Definition: Envelope.cpp:409
Illegal operation at run time.
RandEnvelope(float frequency=1, float amplitude=1, float offset=0, float step=0)
defaults are 1 Hz, +- 1.0 range
Definition: Envelope.cpp:548
void setRelease(float release)
Definition: Envelope.cpp:432
void nextSegment()
choose the values for the next line segment
Definition: Envelope.cpp:569
virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
The main FrameStream work method.
Definition: Envelope.cpp:292
float mOffset
DC offset.
Definition: Envelope.h:274
LineMode mMode
How am I to calculate the values from start to end values of the line.
Definition: Envelope.h:75
void setAll(float d, float a, float r)
Definition: Envelope.cpp:502
void setEnd(float tend)
Definition: Envelope.h:56
void initSegment()
set up the line segment
Definition: Envelope.cpp:561
unsigned mSize
Definition: Envelope.h:123
float duration()
Returns the total time it will take to get from start to end value.
Definition: Envelope.h:53
void setStart(float tstart)
Definition: Envelope.h:57
void createSegments()
Allocate memory for the segments.
Definition: Envelope.cpp:164
float mCurrentValue
Internal book-keeping.
Definition: Envelope.h:76
#define kExpon
Definition: Envelope.h:37
Scalable – mix-in class with scale and offset control inputs (may be constants or generators)...
Definition: CSL_Core.h:403
A linearly interpolated segment – this has start and end values, and a duration (in seconds)...
Definition: Envelope.h:45
void release(void)
Definition: Envelope.cpp:441
void setDuration(unsigned tduration)
Overloaded to accept either float or unsigned.
Definition: Envelope.h:58
virtual void scaleTimes(float s)
scale durations
Definition: Envelope.cpp:229
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
next buffer interpolator
Definition: Envelope.cpp:49
Breakpoints mSegmentMap
list of envelope breakpoints
Definition: Envelope.h:120
bool mWalk
whether to produce random values or a random walk
Definition: Envelope.h:277
void setAttack(float attack)
Definition: Envelope.cpp:488
static size_t size
Definition: fft_N.c:40
float mAmplitude
scale (+-)
Definition: Envelope.h:272
void setDelay(float del)
Definition: Envelope.cpp:481
void setDuration(float d)
Special accessors.
Definition: Envelope.cpp:385
void reset()
reset counters
Definition: Envelope.cpp:39
int LineMode
Definition: Envelope.h:38
#define kLine
LineSegment flags for line interpolation.
Definition: Envelope.h:36
float mStep
max step between values (+-)
Definition: Envelope.h:273
void addBreakpoint(float startTime, float value)
Definition: Envelope.cpp:192
unsigned mSegmentLength
line segment's length in frames
Definition: Envelope.h:276
void calculateSegments()
Calculate the internal data.
Definition: Envelope.cpp:170
float mEnd
Ending value.
Definition: Envelope.h:73
#define LOAD_SCALABLE_CONTROLS
Load the scale/offset-related values at the start.
Definition: CSL_Core.h:436
void setDelay(float del)
Definition: Envelope.cpp:399
float fRandZ(void)
A variety of useful random-number functions.
Definition: CGestalt.cpp:414
virtual void reset()
reset internal time to restart envelope
Definition: Envelope.cpp:276
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
scale durations
Definition: Envelope.cpp:594
virtual bool isActive()
This answers whether I'm active (ptr < end)
Definition: Envelope.cpp:211
float mFrequency
frequency for picking new values
Definition: Envelope.h:271
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
float mDuration
Length of the line segment (IN SECONDS)
Definition: Envelope.h:74
virtual void scaleValues(float s)
scale values so the max is s
Definition: Envelope.cpp:246
void setSustain(float sustain)
Definition: Envelope.cpp:426
void setDecay(float decay)
Definition: Envelope.cpp:419
float start()
Accessors.
Definition: Envelope.h:51
float mStart
Start value.
Definition: Envelope.h:72
Port – used to represent constant, control-rate or signal inputs and outputs in named maps; holds a ...
Definition: CSL_Core.h:312
float mLastVal
last line segment ending value (unscaled and unoffset)
Definition: Envelope.h:270
LineSegment()
empty constructor
Definition: Envelope.cpp:19
virtual ~Envelope()
Definition: Envelope.cpp:155
forward declaration
Definition: CSL_Core.h:241
float * mValues
Definition: Envelope.h:122
unsigned mCurrentIndex
current index in line segment
Definition: Envelope.h:275
void setDuration(float d)
Special accessors.
Definition: Envelope.cpp:469
void setMode(LineMode mode)
Definition: Envelope.cpp:206
Envelope: a collection of LineSegments; may have an input (scale) and act like a processor, or have no input and act like a control UGen. I inherit Scalable setScale, setOffset for inputs.
Definition: Envelope.h:89
void setRelease(float release)
Definition: Envelope.cpp:495
LineSegment ** mSegments
array of line segments that for the envelope
Definition: Envelope.h:121
float mCurrentMark
How far we have read.
Definition: Envelope.h:119
virtual void dump()
pretty-print the receiver's input/controls map
Definition: CSL_Core.cpp:926
void release(void)
Operations.
Definition: Envelope.cpp:516
Base class of CSL exceptions (written upper-case). Has a string message.
#define DECLARE_SCALABLE_CONTROLS
Macros for all the Scalable UnitGenerators (note that these don't end with ";")
Definition: CSL_Core.h:429