CSL 5.2

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

- File List
- File Members

SimpleSines.cpp
Go to the documentation of this file.
1 //
2 // SimpleSines.cpp -- implementation of the tutorial example oscillator classes
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5
6 #include "SimpleSines.h" // include the class header
7 #include <math.h> // this is for sin()
8
9 using namespace csl; // use the CSL namespace
10
11 //
12 // SimpleSine -- The simplest CSL sine oscillator class
13 //
14
15 // Constructors call UnitGenerator constructor and initialize the member variables
16
17 SimpleSine::SimpleSine() : UnitGenerator(), mFrequency(220.0), mPhase(0.0) { } // default freq = 220 Hz, phase = 0
18
19 SimpleSine::SimpleSine(float frequency) : UnitGenerator(), mFrequency(frequency), mPhase(0.0) { }
20
21 SimpleSine::SimpleSine(float frequency, float phase) : UnitGenerator(), mFrequency(frequency), mPhase(phase) { }
22
23 SimpleSine::~SimpleSine() { } ///< Destructor is a no-op
24
25 //
26 // The SimpleSine monoNextBuffer method plays one channel into the given buffer at a fixed frequency
27 //
28
29 void SimpleSine::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
30
31 sample * buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
32
33 float phaseIncrement = mFrequency * CSL_TWOPI / mFrameRate; // calculate the phase increment
34
35 #ifdef CSL_DEBUG
36 logMsg("SimpleSine nextBuffer"); // for verbose debugging (define CSL_DEBUG in CSL_Core.h)
37 #endif
38
39 for (unsigned i = 0; i < outputBuffer.mNumFrames; i++) { // this is the sample computation loop
40 *buffer++ = sin(mPhase); // compute and store sine value
41 mPhase += phaseIncrement; // increment the phase by the phase increment
42 }
43 while (mPhase >= CSL_TWOPI) // reduce phase to < 2pi radians when done
44 mPhase -= CSL_TWOPI;
45 } // that's all there is to it!
46
47
48 //
49 // SineAsPhased -- A sine oscillator that uses the Phased mix-in class
50 //
51 /// Constructors call UnitGenerator and Phased constructors
52 SineAsPhased::SineAsPhased() : UnitGenerator(), Phased(220.0) { }
53
54 SineAsPhased::SineAsPhased(float frequency) : UnitGenerator(), Phased(frequency) { }
55
56 SineAsPhased::SineAsPhased(float frequency, float phase) : UnitGenerator(), Phased(frequency, phase) { }
57
58 SineAsPhased::~SineAsPhased() { } ///< Destructor is a no-op
59
60 // This monoNextBuffer method looks the same as above, but handles dynamic frequency using
61 // the input port map (i.e., the mInputs[CSL_FREQUENCY] expression, which returns a Port object pointer)
62
63 #ifdef NOT_THIS_WAY // This is the really verbose way; see below for how to use the macros to make this easier
64
65 void SineAsPhased::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
66 sample * buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
67 float rateRecip = CSL_TWOPI / mFrameRate; // Calculate the phase increment multiplier
68
69 Port * freqPort = mInputs[CSL_FREQUENCY]; // get the frequency control port from the map
70 UnitGenerator * freqUG = freqPort->mUGen; // get its unit generator
71 bool freqDyn = (freqUG != NULL); // if it's NULL, we have a fixed freq.
72 sample * freq = NULL; // pointer to freq buffer (if used)
73 float freqC; // current frequency value
74
75 if (freqDyn) { // if we have a dynamic freq.
76 this->pullInput(freqPort, outputBuffer); // pull its buffer (this calls its nextBuffer method)
77 freq = freqPort->mBuffer->monoBuffer(0); // get the pointer to its buffer
78 freqC = *freq++; // grab the first value
79 } else // otherwise
80 freqC = freqPort->mValue; // get the port's constant value
81
82 for (unsigned i = 0; i < outputBuffer.mNumFrames; i++) { // the sample loop
83 *buffer++ = sin(mPhase); // compute and store sine value
84 mPhase += (freqC * rateRecip); // increment phase by possibly dynamic frequency
85 if (freqDyn) // if the freq. is dynamic
86 freqC = *freq++; // update it from the control input's buffer pointer
87 }
88 while (mPhase >= CSL_TWOPI) // wrap around after 2pi radians
89 mPhase -= CSL_TWOPI;
90 }
91
92 #endif
93
94 // This is the right way to do it (the terse version that uses these macros defined for Phased in CSL_Core.h).
95 // The added calls above are handled by #defines in the CSL_Core.h header file, so you can say things like
96 // DECLARE_PHASED_CONTROLS;
97 // LOAD_PHASED_CONTROLS;
98 // UPDATE_PHASED_CONTROLS;
99
100 void SineAsPhased::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
101 sample * buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
102 unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
103 float rateRecip = CSL_TWOPI / mFrameRate; // compute the phase increment scale
104
105 DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value as above
106 #ifdef CSL_DEBUG
107 logMsg("SineAsPhased nextBuffer"); // for verbose debugging
108 #endif
109 LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
110
111 for (unsigned i = 0; i < numFrames; i++) { // sample loop
112 *buffer++ = sin(mPhase); // compute and store sine value
113 mPhase += (freqValue * rateRecip); // increment phase
114 UPDATE_PHASED_CONTROLS; // update the dynamic frequency
115 }
116 while (mPhase > CSL_TWOPI) // wraparound after 2pi radians
117 mPhase -= CSL_TWOPI;
118 }
119
120 // Pretty-print the receiver for debugging
121
122 void SineAsPhased::dump() {
123 logMsg("a SineAsPhased"); // print a message
124 Phased::dump(); // this dumps the input port map
125 }
126
127 ///
128 /// SineAsScaled -- A sine oscillator with scale and offset
129 ///
130 /// Constructors call UnitGenerator, Phased, and Scalable constructors
131 SineAsScaled::SineAsScaled() : UnitGenerator(), Phased(220.0, 0.0), Scalable(1.0, 0.0) { }
132
133 SineAsScaled::SineAsScaled(float frequency) : UnitGenerator(), Phased(frequency, 0.0), Scalable(1.0, 0.0) { }
134
135 SineAsScaled::SineAsScaled(float frequency, float phase) : UnitGenerator(), Phased(frequency, phase), Scalable(1.0, 0.0) { }
136
137 SineAsScaled::SineAsScaled(float frequency, float phase, float ampl, float offset) : UnitGenerator(), Phased(frequency, phase), Scalable(ampl, offset) { }
138
139 SineAsScaled::~SineAsScaled() { } ///< Destructor is a no-op
140
141 // SineAsScaled monoNextBuffer method uses the dynamic frequency, scale, and offset
142
143 #ifdef NOT_THIS_WAY // This is the really verbose way; see below for how to use the macros to make this easier
144
145 void SineAsScaled::nextBuffer(Buffer & outBuf, unsigned outBufNum) throw (CException) {
146 sample * buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
147 float rateRecip = CSL_TWOPI / mFrameRate; // Calculate the phase increment multiplier
148
149 Port * freqPort = mInputs[CSL_FREQUENCY]; // get the frequency control port from the map
150 Port * scalePort = mInputs[CSL_SCALE]; // scale control port
151 Port * offsetPort = mInputs[CSL_OFFSET]; // offset control port
152
153 UnitGenerator * freqUG = freqPort->mUGen; // get its unit generator
154 UnitGenerator * scaleUG = scalePort->mUGen; // scale unit generator
155 UnitGenerator * offsetUG = offsetPort->mUGen; // offset UGen
156
157 bool freqDyn = (freqUG != NULL); // if it's NULL, we have a fixed freq.
158 bool scaleDyn = (scaleUG != NULL);
159 bool offsetDyn = (offsetUG != NULL);
160
161 sample * freq = NULL; // pointer to freq buffer (if used)
162 sample * scale = 0; // scale buffer pointer
163 sample * offset = 0; // offset buffer pointer
164 float freqC, scaleC, offsetC // constant values
165
166 if (freqDyn) { // if we have a dynamic freq.
167 this->pullInput(freqPort, outputBuffer); // pull its buffer (this calls its nextBuffer method)
168 freq = freqPort->mBuffer->monoBuffer(0); // get the pointer to its buffer
169 freqC = *freq++; // grab the first value
170 } else // otherwise
171 freqC = freqPort->mValue; // get the port's constant value
172
173 if (scaleDyn) { // if we have a dynamic scale
174 this->pullInput(scalePort, outputBuffer);
175 scale = scalePort->mBuffer->monoBuffer(0);
176 scaleC = *scale++;
177 } else
178 scaleC = scalePort->mValue;
179
180 if (offsetDyn) { // if we have a dynamic offset
181 this->pullInput(offsetPort, outputBuffer);
182 offset = offsetPort->mBuffer->monoBuffer(0);
183 offsetC = *offset++;
184 } else
185 offsetC = offsetPort->mValue;
186
187 for (unsigned i = 0; i < outputBuffer.mNumFrames; i++) { // the sample loop
188 *buffer++ = sin(mPhase); // compute and store sine value
189 mPhase += (freqC * rateRecip); // increment phase by possibly dynamic frequency
190
191 if (freqDyn) // if the freq. is dynamic
192 freqC = *freq++; // update it from the control input's buffer pointer
193 if (scaleDyn) // if the scale is dynamic
194 scaleC = *scale++;
195 if (offsetDyn) // if the offset is dynamic
196 offsetC = *offset++
197 }
198 while (mPhase >= CSL_TWOPI) // wrap a
199 while (mPhase >= CSL_TWOPI) // wraparound after 2pi radians
200 mPhase -= CSL_TWOPI;
201 }
202
203 #endif
204
205 // Again, the added calls above are handled by macros defined in the CSL_Core.h header file, so you can say things like
206 // DECLARE_SCALABLE_CONTROLS;
207 // LOAD_SCALABLE_CONTROLS;
208 // UPDATE_SCALABLE_CONTROLS;
209
210 void SineAsScaled::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
211 sample * buffer = outputBuffer.monoBuffer(outBufNum); // get pointer to the selected output channel
212 float rateRecip = CSL_TWOPI / mFrameRate;
213 unsigned numFrames = outputBuffer.mNumFrames; // the number of frames to fill
214 DECLARE_PHASED_CONTROLS; // declare the frequency buffer and value as above
215 DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values as above
216 #ifdef CSL_DEBUG
217 logMsg("SineAsScaled nextBuffer");
218 #endif
219 LOAD_PHASED_CONTROLS; // load the freqC from the constant or dynamic value
220 LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
221
222 for (unsigned i = 0; i < numFrames; i++) { // sample loop
223 *buffer++ = (sin(mPhase) * scaleValue) + offsetValue; // compute and store (scaled and offset) sine value
224 mPhase += (freqValue * rateRecip); // increment phase
225 UPDATE_PHASED_CONTROLS; // update the dynamic frequency
226 UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
227 }
228 while (mPhase >= CSL_TWOPI) // wrap around after 2pi radians
229 mPhase -= CSL_TWOPI;
230 }
231
232 // Pretty-print the receiver for debugging
233
234 void SineAsScaled::dump() {
235 logMsg("a SineAsScaled"); // print a message
236 Scalable::dump(); // this dumps the input port map
237 }