CSL  5.2
KarplusString.cpp
Go to the documentation of this file.
1 //
2 // KarplusString.h -- CSL "physical model" string class
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "KarplusString.h"
7 
8 using namespace csl;
9 
10 // Method implementations
11 
12 // Trivial constructors
13 
15  mIndex = 0;
16  mEnergy = 0;
17 }
18 
19 KarplusString::KarplusString(float frequency) : Scalable(), Phased(frequency) {
20  mIndex = 0;
21  mDelayLength = (int) (CGestalt::frameRate() / frequency);
22  mFrequency = frequency;
23  this->initDelayLine();
24 }
25 
26 /// Reset time to 0.0 to restart envelope
27 
29  WhiteNoise noise;
30  noise.nextBuffer(mDelayLine, 0); // write noise into the delay line
31  // estimate decay time for freq
32  mEnergy = 600 * (5 - (freqToKey(mFrequency) / 25));
33 }
34 
36  logMsg("a KarplusString: %d Hz", 400);
38 }
39 
40 /// initialize and fill (with noise) the delay line
41 
43  mDelayLine.setSize(1, mDelayLength); // set up and allocate space for the delay line
45  mEnergy = 0;
46  mIndex = 0;
47 }
48 
49 void KarplusString::setFrequency(float frequency) {
50  Phased::setFrequency(frequency);
51  mEnergy = 0;
52  mFrequency = frequency;
53  mDelayLength = (int) (CGestalt::frameRate() / frequency);
54  this->initDelayLine();
55 }
56 
57 /// The mono_next_buffer method does all the work
58 
59 void KarplusString::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
60 
61  sample samp, lastSample;
62  unsigned numFrames = outputBuffer.mNumFrames;
63  sample *outPtr = outputBuffer.buffer(outBufNum); // get the pointer to the output buffer to write into
64  sample *delayPtr = mDelayLine.buffer(0); // get the pointer to the delay line storage
65  if ( ! mEnergy)
66  return;
68 #ifdef CSL_DEBUG
69  logMsg("Karplus Strong String nextBuffer");
70 #endif
72 
73  for (unsigned i = 0; i < numFrames; i++) { // now do the KS recirculating noise filter
74  samp = delayPtr[mIndex]; // get the current sample in the delay line
75  if (mIndex > 0) // get the previous sample
76  lastSample = delayPtr[mIndex - 1];
77  else
78  lastSample = delayPtr[mDelayLength - 1];
79  samp += lastSample; // average the last 2 samples (cheap LPF)
80  samp *= 0.5;
81  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
82  *outPtr++ = samp * scaleValue + offsetValue; // write to output
83  delayPtr[mIndex] = samp; // write into the delay line
84  mIndex++; // increment and wrap the index
85  if (mIndex >= mDelayLength)
86  mIndex = 0;
87  }
88  if (mEnergy)
89  mEnergy--;
90 }