CSL 5.2

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

- File List
- File Members

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
14 KarplusString::KarplusString() : Scalable(), Phased() {
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
28 void KarplusString::trigger() {
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
35 void KarplusString::dump() {
36 logMsg("a KarplusString: %d Hz", 400);
37 Scalable::dump();
38 }
39
40 /// initialize and fill (with noise) the delay line
41
42 void KarplusString::initDelayLine() {
43 mDelayLine.setSize(1, mDelayLength); // set up and allocate space for the delay line
44 mDelayLine.allocateBuffers();
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;
67 DECLARE_SCALABLE_CONTROLS;
68 #ifdef CSL_DEBUG
69 logMsg("Karplus Strong String nextBuffer");
70 #endif
71 LOAD_SCALABLE_CONTROLS;
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 }