CSL  6.0
BasicFMInstrument.cpp
Go to the documentation of this file.
1 //
2 // BasicFMInstrument.cpp -- Simple FM example instrument class.
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 // Implementation of the 2-envelope FM example as an instrument class.
6 // This example shows how to create an instrument class from a DSP graph and set up its accessors for use with OSC.
7 
8 #include "BasicFMInstrument.h"
9 
10 using namespace csl;
11 
12 #define BASE_FREQ 110.0
13 
14 // The constructor initializes the DSP graph's UGens
15 
16 // ADSR mAEnv, mIEnv; ///< amplitude & modulation index envelopes
17 // Osc mCar, mMod; ///< 2 sine oscillators, carrier and modulator
18 // Panner mPanner; ///< stereo panner
19 
20 FMInstrument::FMInstrument() : // initializers for the UGens
21  Instrument(), // inherited constructor
22  mAEnv(0.25, 0.05, 0.05, 0.5, 0.14), // set up 2 standard ADSRs
23  mIEnv(0.25, 0.1, 0.0, 1.0, 0.1),
24  mMod(BASE_FREQ), // modulator osc
25  mPanner(mCar, 0.0) { // init the panner
26  mIEnv.scaleValues(BASE_FREQ); // scale the index envelope by the mod. freq
27  mMod.setScale(mIEnv);
28  mMod.setOffset(BASE_FREQ);
29  mCar.setFrequency(mMod);
30  mCar.setScale(mAEnv);
31  mNumChannels = 2;
32 
33  mName = "Basic_FM";
34  mGraph = & mPanner; // store the root of the graph as the inst var _graph
35  mUGens["Carrier"] = & mCar; // add ugens that can be monitored to the map
36  mUGens["Modulator"] = & mMod;
37  mUGens["F env"] = & mIEnv;
38  mUGens["A env"] = & mAEnv;
39  mUGens["Panner"] = & mPanner;
40 
41  mEnvelopes.push_back(& mAEnv); // list envelopes for retrigger
42  mEnvelopes.push_back(& mIEnv);
43  // set up accessor vector
44  mAccessors.push_back(new Accessor("du", set_duration_f, CSL_FLOAT_TYPE));
45  mAccessors.push_back(new Accessor("am", set_amplitude_f, CSL_FLOAT_TYPE));
46  mAccessors.push_back(new Accessor("in", set_index_f, CSL_FLOAT_TYPE));
47  mAccessors.push_back(new Accessor("cf", set_c_freq_f, CSL_FLOAT_TYPE));
48  mAccessors.push_back(new Accessor("mf", set_m_freq_f, CSL_FLOAT_TYPE));
49  mAccessors.push_back(new Accessor("po", set_position_f, CSL_FLOAT_TYPE));
50  mAccessors.push_back(new Accessor("aa", set_attack_f, CSL_FLOAT_TYPE));
51  mAccessors.push_back(new Accessor("ad", set_decay_f, CSL_FLOAT_TYPE));
52  mAccessors.push_back(new Accessor("as", set_sustain_f, CSL_FLOAT_TYPE));
53  mAccessors.push_back(new Accessor("ar", set_release_f, CSL_FLOAT_TYPE));
54  mAccessors.push_back(new Accessor("ia", set_iattack_f, CSL_FLOAT_TYPE));
55  mAccessors.push_back(new Accessor("id", set_idecay_f, CSL_FLOAT_TYPE));
56  mAccessors.push_back(new Accessor("is", set_isustain_f, CSL_FLOAT_TYPE));
57  mAccessors.push_back(new Accessor("ir", set_irelease_f, CSL_FLOAT_TYPE));
58 }
59 
60 
61 // copy constructor
62 
64  Instrument(in),
65  mAEnv(in.mAEnv),
66  mIEnv(in.mIEnv),
67  mCar(in.mCar),
68  mMod(in.mMod),
69  mPanner(in.mPanner) { }
70 
71 // The destructor frees the stuff we allocated
72 
74 
75 // Plug function for use by OSC setter methods
76 
77 void FMInstrument::setParameter(unsigned selector, int argc, void **argv, const char *types) {
78  if (argc == 1) {
79  float d = * (float *) argv[0];
80  if (types[0] == 'i')
81  d = (float) (* (int *) argv[0]);
82  switch (selector) { // switch on which parameter is being set
83  case set_duration_f:
84  mAEnv.setDuration(d);
85  mIEnv.setDuration(d);
86  break;
87  case set_amplitude_f:
88  mAEnv.scaleValues(d); break;
89  case set_index_f:
90  mIEnv.scaleValues(d); break;
91  case set_c_freq_f:
92  mMod.setOffset(d);
93  // printf("\tcf %g\n", * (float *)d);
94  break;
95  case set_m_freq_f:
96  mMod.setFrequency(d); break;
97  case set_position_f:
98  mPanner.setPosition(d);
99  // printf("\tpo %g\n", * (float *)d);
100  break;
101  case set_attack_f:
102  mAEnv.setAttack(d); break;
103  case set_decay_f:
104  mAEnv.setDecay(d); break;
105  case set_sustain_f:
106  mAEnv.setSustain(d); break;
107  case set_release_f:
108  mAEnv.setRelease(d); break;
109  case set_iattack_f:
110  mIEnv.setAttack(d); break;
111  case set_idecay_f:
112  mIEnv.setDecay(d); break;
113  case set_isustain_f:
114  mIEnv.setSustain(d); break;
115  case set_irelease_f:
116  mIEnv.setRelease(d); break;
117  default:
118  logMsg(kLogError, "Unknown selector in FMInstrument set_parameter selector: %d\n", selector);
119  }
120  } else { // multiple args
121  logMsg(kLogError, "Unknown multi-arg (%d) setter in FMInstrument: %s\n", argc, types);
122  }
123 }
124 
125 // Formats (4, 6 or 14 arguments):
126 // dur, ampl, fr, pos
127 // dur, ampl, c_fr, m_fr, ind, pos
128 // dur, ampl, c_fr, m_fr, ind, pos, att, dec, sus, rel, i_att, i_dec, i_sus, i_rel
129 
130 void FMInstrument::parseArgs(int argc, void **argv, const char *types) {
131  float ** fargs = (float **) argv;
132  unsigned nargs;
133  if (strcmp(types, "ffff") == 0) {
134  nargs = 4;
135  printf("\tFM: d %5.2f a %5.2f f %7.1f p %5.2f\n",
136  *fargs[0], *fargs[1], *fargs[2], *fargs[3]);
137  } else if (strcmp(types, "ffffff") == 0) {
138  nargs = 6;
139  printf("\tFM: d %g a %g c %g m %g i %g p %g\n",
140  *fargs[0], *fargs[1], *fargs[2], *fargs[3], *fargs[4], *fargs[5]);
141  } else if (strcmp(types, "ffffffffffffff") == 0)
142  nargs = 14;
143  else {
144  logMsg(kLogError, "Invalid type string in OSC message, expected \"ff...ff\" got \"%s\"\n", types);
145  return;
146  }
147  mAEnv.setDuration(*fargs[0]);
148  mIEnv.setDuration(*fargs[0]);
149  mAEnv.scaleValues(*fargs[1]);
150  mMod.setOffset(*fargs[2]);
151  mMod.setFrequency(*fargs[2]);
152 
153  if (nargs == 4) {
154  mIEnv.setScale(*fargs[2]);
155  mPanner.setPosition(*fargs[3]);
156  }
157  if (nargs == 6) {
158  mIEnv.setScale(*fargs[4] * *fargs[2]);
159  mPanner.setPosition(*fargs[5]);
160  }
161  if (nargs == 14) {
162  printf("\t\ta %g d %g s %g r %g\t\ta %g d %g s %g r %g\n",
163  *fargs[6], *fargs[7], *fargs[8], *fargs[9], *fargs[10], *fargs[11], *fargs[12], *fargs[13]);
164  mAEnv.setAttack(*fargs[6]);
165  mAEnv.setDecay(*fargs[7]);
166  mAEnv.setSustain(*fargs[8]);
167  mAEnv.setRelease(*fargs[9]);
168  mIEnv.setAttack(*fargs[10]);
169  mIEnv.setDecay(*fargs[11]);
170  mIEnv.setSustain(*fargs[12]);
171  mIEnv.setRelease(*fargs[13]);
172  }
173 }
174 
175 // Play a note with a given arg list
176 
177 void FMInstrument::playOSC(int argc, void **argv, const char *types) {
178  this->parseArgs(argc, argv, types);
179  this->play();
180 }
181 
182 // Play a note specifying all parameters
183 
184 void FMInstrument::playNote(float dur, float ampl, float c_fr, float m_fr, float ind, float pos,
185  float att, float dec, float sus, float rel,
186  float i_att, float i_dec, float i_sus, float i_rel) {
187  mAEnv.setDuration(dur);
188  mIEnv.setDuration(dur);
189  mAEnv.scaleValues(ampl);
190  mMod.setOffset(c_fr);
191  mMod.setFrequency(m_fr);
192  mIEnv.scaleValues(ind * m_fr);
193  mPanner.setPosition(pos);
194  mAEnv.setAttack(att);
195  mAEnv.setDecay(dec);
196  mAEnv.setSustain(sus);
197  mAEnv.setRelease(rel);
198  mIEnv.setAttack(i_att);
199  mIEnv.setDecay(i_dec);
200  mIEnv.setSustain(i_sus);
201  mIEnv.setRelease(i_rel);
202  this->play();
203 }
204 
205 
206 void FMInstrument::playMIDI(float dur, int chan, int key, int vel) {
207  mAEnv.setDuration(dur);
208  mIEnv.setDuration(dur);
209  mAEnv.scaleValues(sqrtf((float) vel / 128.0f));
210  mMod.setOffset(keyToFreq(key));
211  mMod.setFrequency(keyToFreq(key));
212 // mIEnv.scaleValues(keyToFreq(key));
213  this->play();
214 }
215 
216 ///////////////////////////////////////////////////
217 
218 // FancyFMInstrument
219 
220 // Envelope mVibEnv; ///< vibrato envelope
221 // ADSR mChiffEnv; ///< attack-chiff envelope
222 // Sine mVibrato; ///< sine oscillator for vibrato
223 // WhiteNoise mChiff; ///< chiff noise
224 // Butter mChFilter; ///< chiff filter
225 // Freeverb mReverb;
226 
227 FancyFMInstrument::FancyFMInstrument() : // initializers for the UGens
228  FMInstrument(),
229  mVibEnv(kExpon, 3, 0.0, 0.1, 2, 1.0, 3, 0.1), ///< Triangle-like AR vibrato envelope
230  mChiffEnv(3, 0.01, 0.01, 0.0, 2), ///< attack-chiff envelope
231  mVibrato(6), ///< sine oscillator for vibrato
232  mChFilter(mChiff, BW_BAND_PASS, 4000.f, 200.f), ///< chiff filter
233  mReverb(mPanner) { // reverb the panner
234  mVibEnv.setScale(8); // scale vibrato envelope
235  mVibrato.setScale(mVibEnv);
236  mVibrato.setOffset(BASE_FREQ); // shift vibrato up
237 
238  mChiffEnv.setScale(0.8); // scale chiff envelope
239  mChFilter.setScale(mChiffEnv); // apply chiff envelope
240  mCar.setOffset(mChFilter); // add in chiff
241 
242  mMod.setOffset(mVibrato); // add in vibrato and base freq
243 
244  mName = "Fancy_FM";
245  mUGens["Vibrato"] = & mVibrato;
246  mUGens["Vib env"] = & mVibEnv;
247  mUGens["Attack chiff filter"] = & mChFilter;
248  mUGens["Attack chiff env"] = & mChiffEnv;
249  mUGens["Attack noise"] = & mChiff;
250  mUGens["Reverb"] = & mReverb;
251  mEnvelopes.push_back(& mVibEnv); // list envelopes for retrigger
252  mEnvelopes.push_back(& mChiffEnv);
253 }
254 
255 // The destructor frees the stuff we allocated
256 
258 
259 void FancyFMInstrument::setParameter(unsigned selector, int argc, void **argv, const char *types) {
260  FMInstrument::setParameter(selector, argc, argv, types); // call superclass' version
261  if (argc == 1) {
262  float d = * (float *) argv[0];
263  if (types[0] == 'i')
264  d = (float) (* (int *) argv[0]);
265  switch (selector) { // switch on which parameter is being set
266  case set_duration_f:
268  mVibEnv.setDuration(d);
269  break;
270  case set_c_freq_f:
271  mVibrato.setOffset(d); // shift vibrato up
272  mMod.setOffset(mVibrato);
273  break;
274  case set_vib_depth_f:
275  mVibEnv.setScale(d); break;
276  case set_chiff_amt_f:
277  mChiffEnv.setScale(d); break;
278  default:
279  break;
280  }
281  } else // multiple args
282  logMsg(kLogError, "Unknown multi-arg (%d) setter in FMInstrument: %s\n", argc, types);
283 }
284 
285 void FancyFMInstrument::playOSC(int argc, void **argv, const char *types) {
286  float ** fargs = (float **) argv;
287  this->parseArgs(argc, argv, types);
288  mVibrato.setOffset(*fargs[2]); // shift vibrato up
289  mMod.setOffset(mVibrato); // add in vibrato and base freq
290  mMod.setOffset(*fargs[2]);
291  mVibrato.setFrequency(4.0 + (4.0 * fRandZ()));
292  mChiffEnv.setAttack(0.05 * fRandZ());
293  mChiffEnv.setDecay(0.05 * fRandZ());
294  this->play();
295 }
296 
297 
298 void FancyFMInstrument::playMIDI(float dur, int chan, int key, int vel) {
299  mAEnv.setDuration(dur);
300  mIEnv.setDuration(dur);
301  mAEnv.scaleValues(sqrtf((float) vel / 128.0f));
302  mVibrato.setOffset(keyToFreq(key)); // shift vibrato up
303  mMod.setOffset(mVibrato); // add in vibrato and base freq
304  mMod.setOffset(keyToFreq(key));
305  mVibrato.setFrequency(4.0 + (4.0 * fRandZ()));
306  mChiffEnv.setAttack(0.05 * fRandZ());
307  mChiffEnv.setDecay(0.05 * fRandZ());
308  this->play();
309 }
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
#define set_idecay_f
Definition: Instrument.h:31
#define set_index_f
Definition: Instrument.h:35
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
#define set_amplitude_f
Definition: Instrument.h:20
virtual void setDuration(float d)
set/scale durations
Definition: Envelope.cpp:220
#define set_decay_f
Definition: Instrument.h:26
void setParameter(unsigned selector, int argc, void **argv, const char *types)
Plug functions.
virtual void setParameter(unsigned selector, int argc, void **argv, const char *types)
Plug functions.
#define set_attack_f
Definition: Instrument.h:25
void setAttack(float attack)
Definition: Envelope.cpp:409
#define BASE_FREQ
void setRelease(float release)
Definition: Envelope.cpp:432
#define set_vib_depth_f
Definition: Instrument.h:39
UnitGenerator * mGraph
Caches.
Definition: Instrument.h:87
FancyFMInstrument()
Constructor.
void parseArgs(int argc, void **argv, const char *types)
Play functions.
float keyToFreq(unsigned midiKey)
MIDI Conversions.
Definition: CGestalt.cpp:483
AccessorVector mAccessors
the accessor vector
Definition: Instrument.h:91
Butter mChFilter
chiff filter
virtual void play()
Definition: Instrument.cpp:70
string mName
my name
Definition: Instrument.h:88
virtual void playOSC(int argc, void **argv, const char *types)
#define kExpon
Definition: Envelope.h:37
#define set_c_freq_f
Definition: Instrument.h:36
WhiteNoise mChiff
chiff noise
FMInstrument.
Osc mVibrato
sine oscillator for vibrato
#define set_irelease_f
Definition: Instrument.h:33
#define set_duration_f
Instrument.h – The CSL pluggable instrument class. See the copyright notice and acknowledgment of au...
Definition: Instrument.h:19
#define BW_BAND_PASS
Definition: Filters.h:53
ADSR mIEnv
amplitude & modulation index envelopes
unsigned mNumChannels
my "expected" number of output channels
Definition: CSL_Core.h:292
void setPosition(UnitGenerator &pan)
Operations.
Definition: Mixer.cpp:279
#define set_isustain_f
Definition: Instrument.h:32
Instrument class (abstract)
Definition: Instrument.h:56
void setDuration(float d)
Special accessors.
Definition: Envelope.cpp:385
#define set_chiff_amt_f
Definition: Instrument.h:40
float fRandZ(void)
A variety of useful random-number functions.
Definition: CGestalt.cpp:414
void playMIDI(float dur, int chan, int key, int vel)
These are the additional UGens of the DSP graph (i.e., the FM instrument)
Osc mMod
2 sine oscillators, carrier and modulator
void playNote(float dur=1, float ampl=1, float c_fr=110, float m_fr=110, float ind=1, float pos=0, float att=0.1, float dec=0.1, float sus=0.5, float rel=0.1, float i_att=0.1, float i_dec=0.1, float i_sus=0.5, float i_rel=0.1)
#define set_iattack_f
Definition: Instrument.h:30
#define CSL_FLOAT_TYPE
Definition: Accessor.h:14
FMInstrument()
Constructor.
virtual void scaleValues(float s)
scale values so the max is s
Definition: Envelope.cpp:246
void setSustain(float sustain)
Definition: Envelope.cpp:426
The Accessor class has public data members.
Definition: Accessor.h:22
void setDecay(float decay)
Definition: Envelope.cpp:419
Panner mPanner
stereo panner
#define set_sustain_f
Definition: Instrument.h:27
#define set_position_f
Definition: Instrument.h:22
UGenVector mEnvelopes
the vector of envelopes to query or trigger
Definition: Instrument.h:90
#define set_m_freq_f
Definition: Instrument.h:37
void playMIDI(float dur, int chan, int key, int vel)
These are the UGens of the DSP graph (i.e., the FM instrument)
void setScale(UnitGenerator &scale)
set the receiver's scale member to a UGen or a float
Definition: CSL_Core.cpp:1039
Envelope mVibEnv
vibrato envelope
ADSR mChiffEnv
attack-chiff envelope
#define set_release_f
Definition: Instrument.h:28
void playOSC(int argc, void **argv, const char *types)
UGenMap mUGens
the map of ugens in the graph by name
Definition: Instrument.h:89