CSL  6.0
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.buffer(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
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.buffer(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->buffer(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.buffer(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 
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.buffer(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->buffer(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->buffer(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->buffer(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.buffer(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 
235  logMsg("a SineAsScaled"); // print a message
236  Scalable::dump(); // this dumps the input port map
237 }
#define UPDATE_SCALABLE_CONTROLS
Definition: CSL_Core.h:444
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
#define CSL_FREQUENCY
Definition: CSL_Types.h:278
#define DECLARE_PHASED_CONTROLS
Macros for all the Phased UnitGenerators (note that these don't end with ";") These make some assumpt...
Definition: CSL_Core.h:520
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
~SimpleSine()
Destructor.
Definition: SimpleSines.cpp:23
Phased – a mix-in for objects with phase accumulators (local float) and frequency controls (an input...
Definition: CSL_Core.h:497
virtual SampleBuffer buffer(unsigned bufNum)
convenience accessors for sample buffers
Definition: CSL_Core.cpp:66
SineAsPhased()
Constructors.
Definition: SimpleSines.cpp:52
float mValue
my value (in case I'm fixed [mUGen == NULL])
Definition: CSL_Core.h:322
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
the monoNextBuffer method is where the DSP takes place
Definition: SimpleSines.cpp:29
void dump()
pretty-print the receiver
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
the monoNextBuffer method is where the DSP takes place
~SineAsScaled()
Destructor.
Scalable – mix-in class with scale and offset control inputs (may be constants or generators)...
Definition: CSL_Core.h:403
float sample
(could be changed to int, or double)
Definition: CSL_Types.h:191
#define UPDATE_PHASED_CONTROLS
Update the freq-related value in the loop.
Definition: CSL_Core.h:534
SimpleSine()
Constructors.
Definition: SimpleSines.cpp:17
void dump()
pretty-print the receiver
SineAsScaled()
Constructors.
#define CSL_TWOPI
Definition: CSL_Types.h:336
#define LOAD_PHASED_CONTROLS
Load the freq-related values at the start of the callback; if the frequency is a dynamic UGen input...
Definition: CSL_Core.h:528
#define LOAD_SCALABLE_CONTROLS
Load the scale/offset-related values at the start.
Definition: CSL_Core.h:436
UnitGenerator * mUGen
my unit generator (pointer or NULL)
Definition: CSL_Core.h:320
Buffer * mBuffer
the buffer used to hold my output
Definition: CSL_Core.h:321
~SineAsPhased()
Destructor.
Definition: SimpleSines.cpp:58
#define CSL_OFFSET
Definition: CSL_Types.h:274
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
Port – used to represent constant, control-rate or signal inputs and outputs in named maps; holds a ...
Definition: CSL_Core.h:312
forward declaration
Definition: CSL_Core.h:241
#define CSL_SCALE
Definition: CSL_Types.h:273
virtual void dump()
pretty-print the receiver's input/controls map
Definition: CSL_Core.cpp:926
Base class of CSL exceptions (written upper-case). Has a string message.
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
the monoNextBuffer method is where the DSP takes place
#define DECLARE_SCALABLE_CONTROLS
Macros for all the Scalable UnitGenerators (note that these don't end with ";")
Definition: CSL_Core.h:429