CSL 5.2

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

- File List
- File Members

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
63 FMInstrument::FMInstrument(FMInstrument& in) :
64 Instrument(in),
65 mAEnv(in.mAEnv),
66 mIEnv(in.mIEnv),
67 mMod(in.mMod),
68 mCar(in.mCar),
69 mPanner(in.mPanner) { }
70
71 // The destructor frees the stuff we allocated
72
73 FMInstrument::~FMInstrument() { }
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
257 FancyFMInstrument::~FancyFMInstrument() { }
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:
267 mChiffEnv.setDuration(d);
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 }