CSL 5.2

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

- File List
- File Members

Test_Envelopes.cpp
Go to the documentation of this file.
1 //
2 // Test_Envelopes.cpp -- C main functions for the basic CSL envelope and control patching tests.
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 // This program simply reads the run_tests() function (at the bottom of this file)
6 // and executes a list of basic CSL tests
7 //
8
9 #ifndef USE_JUCE
10 #define USE_TEST_MAIN // use the main() function in test_support.h
11 #include "Test_Support.cpp" // include all of CSL core and the test support functions
12 #else
13 #include "Test_Support.h"
14 #endif
15
16 /////////////////////// Here are the actual unit tests ////////////////////
17
18 /// Apply a glissando to a sine with a LineSegment
19
20 void testGliss() {
21 Osc vox;
22 LineSegment line(3, 2000, 60, kLine);
23 line.dump();
24 vox.setFrequency(line);
25 vox.setScale(0.3);
26 logMsg("playing gliss sin with linear segment...");
27 runTest(vox);
28 logMsg("done.\n");
29
30 LineSegment line2(3, 2000, 60, kExpon);
31 line2.dump();
32 vox.setFrequency(line2);
33 logMsg("playing gliss sin with exponential segment...");
34 runTest(vox);
35 logMsg("done.\n");
36 }
37
38 /// test an amplitude swell
39
40 void testSwell() {
41 Osc vox(220);
42 LineSegment line(3, 0.0, 0.5);
43 vox.setScale(line);
44 vox.dump();
45 logMsg("playing swell sin with line segment...");
46 runTest(vox);
47 logMsg("done.\n");
48 }
49
50 /// AM and FM using the dynamic scale and frequency inputs
51
52 void testARSin() {
53 Osc osc(220); // carrier to be enveloped
54 AR a_env(2, 0.6, 1.0); // AR constructor dur, att, rel
55 osc.setScale(a_env); // amplitude modulate the sine
56 logMsg("AR env dump");
57 osc.dump();
58 logMsg("playing AR sin...");
59 a_env.trigger();
60 runTest(osc);
61 logMsg("done.\n");
62 }
63
64 /// Do the same using the Envelope as an effect
65
66 void testARSin2() {
67 Osc osc(220); // carrier to be enveloped
68 AR a_env(2, 0.2, 1.0); // AR constructor dur, att, rel
69 a_env.setScale(osc); // amplitude modulate the sine
70 logMsg("playing AR sin 2...");
71 a_env.trigger();
72 runTest(a_env);
73 logMsg("done.\n");
74 }
75
76 /// Test an envelope applied to frequency
77
78 void testFrequencyEnv() {
79 Osc vox;
80 Envelope env(3, 0, 220, 0.7, 280, 1.3, 180, 2.0, 200, 3, 100);
81 logMsg("");
82 logMsg("BP env dump");
83 env.dump();
84 logMsg("");
85 vox.setFrequency(env);
86 vox.setScale(0.3);
87 logMsg("playing sin with BP envelope on frequency");
88 env.trigger();
89 runTest(vox);
90 logMsg("done.\n");
91 }
92
93 /// Test an envelope applied to frequency & scale
94
95 void testAMFMEnvs() {
96 Osc vox;
97 Envelope env(3, 0, 100, 0.7, 180, 1.3, 180, 2.0, 200, 3, 140);
98 Envelope env2(3, 0.0, 0, 1.0, 1, 2.5, 0, 2.75, 1, 3, 0);
99 vox.setFrequency(env);
100 vox.setScale(env2);
101 logMsg("playing sin with BP envelopes on frequency & scale");
102 fflush(stdout);
103 env.trigger();
104 env2.trigger();
105 runTest(vox);
106 logMsg("done.\n");
107 }
108
109
110 //////////////////////// Envelope tests ////////////////////////////////////////////
111
112 /// Demonstrate an ADSR
113
114 void testADSR2() {
115 float duration = 3.0; // total dur
116 float attack = 0.06; // att time
117 float decay = 0.1; // dec time
118 float sustain = 0.1; // sust value
119 float release = 1.5; // release time
120 ADSR adsr(duration, attack, decay, sustain, release); // constructor
121 Osc vox(220);
122 vox.setScale(adsr);
123 logMsg("playing sharp ADSR envelope.");
124 adsr.trigger();
125 runTest(vox);
126 logMsg("done.\n");
127
128 ADSR adsr2(duration, 0.5, 0, 1, 0.5);
129 vox.setScale(adsr2);
130 logMsg("playing gradual ADSR envelope.");
131 adsr2.trigger();
132 runTest(vox);
133 logMsg("done.\n");
134 }
135
136 /// FM using 2 oscs and 2 ADSRs
137
138 #define BASE_FREQ 440.0
139 //#define BASE_FREQ 8000.0
140
141 void testADSR_FM() {
142 ADSR a_env(3, 0.1, 0.1, 0.5, 1); // set up 2 standard ADSRs (3-sec duration)
143 ADSR i_env(3, 1.5, 0, 1, 0.4);
144 // percussive envelopes
145 // ADSR a_env(3, 0.02, 0.1, 0.05, 2); // set up 2 standard ADSRs (3-sec duration)
146 // ADSR i_env(3, 0.0001, 0.1, 0, 0);
147 Osc car(BASE_FREQ); // init the 2 oscillators (fc = fm)
148 Osc mod(BASE_FREQ*1.414);
149 // i_env.setScale(BASE_FREQ); // scale the index envelope by the mod. freq
150 i_env.setScale(BASE_FREQ);
151 mod.setScale(i_env);
152 mod.setOffset(BASE_FREQ);
153 car.setFrequency(mod);
154 car.setScale(a_env);
155 i_env.trigger();
156 a_env.trigger();
157 logMsg("playing ADSR FM\n");
158 // car.dump();
159 runTest(car);
160 logMsg("done.\n");
161 }
162
163 /// test the rand env as the freq of a SOS
164
165 void testRandFreqEnv() {
166 SumOfSines sos(kFrequency, 6, 0.2, 0.2, 0.1, 0.05, 0.02, 0.02);
167 sos.createCache(); // make the cached wavetable
168 AR a_env(6, 1, 1); // dur, att, rel
169 // RandEnvelope (frq, amp, offset, step)
170 RandEnvelope f_env(3, 80, 200, 40); // freq env = random walk
171 sos.setFrequency(f_env); // set the carrier's frequency
172 sos.setScale(a_env); // multiply index envelope by mod freq
173 logMsg("playing random gliss...");
174 // f_env.trigger(); // reset the envelopes to time 0
175 a_env.trigger();
176 runTest(sos, 6); // run the test to play a note on the root of the DSP graph
177 logMsg("done.\n");
178 }
179
180 /// Function to create and answer a RandFreqEnv UGen patch
181
182 UnitGenerator * createRandFreqEnvPatch(float dur) {
183 Osc * vox = new Osc; // declare an oscillator
184 RandEnvelope * a_env = new RandEnvelope(4, 0.5, 0.5, 0.5); // ampl env = random (frq, amp, off, step)
185 RandEnvelope * f_env = new RandEnvelope(3, 80, 200, 40); // freq env = random (frq, amp, off, step)
186 Osc * lfo = new Osc(fRandM(0.3, 0.6), 1, 0, fRandM(0, CSL_PI)); // LFO with rand frq/phase
187 Panner * pan = new Panner(*vox, *lfo); // stereo panner
188 vox->setFrequency(*f_env); // set the carrier's frequency
189 vox->setScale(*a_env); // multiply index envelope by mod freq
190 pan->setScale(0.04); // scale softer
191 return (pan); // return &pan
192 }
193
194 /// set up 50 RandFreqEnv patches
195
196 void test50RandFreqEnv() {
197 float duration = 20; // total dur
198 Mixer mix(2); // stereo mixer
199
200 for (unsigned i = 0; i < 50; i++) // play a mix of RandFreqEnvPatch instruments
201 mix.addInput(createRandFreqEnvPatch(duration));
202
203 logMsg("playing mix of 50 random gliss oscs...");
204 #ifndef CSL_WINDOWS
205 srand(getpid()); // seed the rand generator -- UNIX SPECIFIC CODE HERE
206 #endif
207 runTest(mix, duration);
208 logMsg("done.\n");
209 mix.deleteInputs(); // clean up
210 }
211
212 /// test the use of scaling
213
214 void testEnvScale() {
215 Osc vox; // declare 2 oscillators
216 LineSegment line(2, 60, 100);
217 vox.setFrequency(line); // set the carrier's frequency
218 ADSR a_env(2, 0.6, 0.1, 0.3, 1); // amplitude env = std ADSR
219 a_env.setScale(vox); // multiply index envelope by mod freq
220 logMsg("playing env as VCA...");
221 a_env.trigger();
222 runTest(a_env, 2); // run the test to play a note on the root of the DSP graph
223 logMsg("done.\n");
224 }
225
226 /// FM with vibrato (with AR-envelope), attack chiff (filtered noise with AR-envelope),
227 /// and random freq. drift and ampl. swell envelopes
228
229 void testFancy_FM() {
230 Osc car(BASE_FREQ); // init the 2 oscillators (fc = fm)
231 Osc mod(BASE_FREQ * 1.05);
232 ADSR a_env(3, 0.04, 0.2, 0.5, 1); // set up 2 standard ADSRs (3-sec duration)
233 ADSR i_env(3, 1.0, 0, 1, 1.0);
234
235 Envelope mVibEnv(kExpon, 3, 0.0, 0.1, 2, 1.0, 3, 0.1); // vibrato envelope (expon triangle)
236 ADSR mChiffEnv(3, 0.01, 0.01, 0.0, 2); // attack-chiff envelope
237 Osc mVibrato(6); // sine oscillator for vibrato
238 WhiteNoise mChiff; // attach chiff noise source
239 Butter mChFilter(mChiff, BW_BAND_PASS, 4000.f, 200.f); // and filter
240
241 mVibEnv.setScale(8); // scale vibrato envelope
242 mVibrato.setScale(mVibEnv); // apply vibrato envelope
243 mVibrato.setOffset(BASE_FREQ); // shift vibrato up
244
245 mChiffEnv.setScale(2.0); // scale chiff envelope
246 mChFilter.setScale(mChiffEnv); // apply chiff envelope
247 car.setOffset(mChFilter); // add in chiff
248
249 i_env.setScale(BASE_FREQ * 2); // scale mod index envelope
250 mod.setScale(i_env); // scale modulator
251 mod.setOffset(mVibrato); // add in vibrato and base freq
252 car.setFrequency(mod); // apply FM modulation
253 car.setScale(a_env); // apply ampl envelope
254
255 Panner mPanner(car, 0.0); // stereo panner
256 Freeverb mReverb(mPanner); // mono reverb
257 mReverb.setRoomSize(0.99); // longer reverb
258
259 i_env.trigger(); // GO -- trigger envelopes
260 a_env.trigger();
261 mVibEnv.trigger();
262 mChiffEnv.trigger();
263
264 logMsg("playing Fancy FM\n");
265 runTest(mReverb, 4); // run the test
266 runTest(mReverb, 4); // run the test
267 logMsg("done.\n");
268 }
269
270 /// Make an envelope from scratch by adding breakpoints
271
272 void testComplexEnvelope() {
273 float dur = 5; // total dur
274 SumOfSines sos(kFrequency, 5, 0.4, 0.2, 0.1, 0.05, 0.02);
275 sos.createCache(); // make the cached wavetable
276 Envelope a_env; // make an empty envelope
277 float tim = 0.0;
278 do { // add a bunch of break points to it
279 a_env.addBreakpoint(tim, fRandZ());
280 tim += fRandM(0.2, 0.5); // pick next time
281 } while (tim < dur);
282 a_env.addBreakpoint(dur, 0); // add final b-point
283 a_env.dump();
284 sos.setScale(a_env); // apply env
285 Panner pan(sos, fRand1()); // put sos in a panner
286 logMsg("playing mix of 50 random SOS oscs...");
287 a_env.trigger(); // trigger env
288 runTest(pan, dur);
289 logMsg("done.\n");
290 }
291
292 // create a UGen patch for a SOS note with a made-up envelope
293
294 UnitGenerator * sosNote(float dur, float frq, float amp) {
295 SumOfSines * sos = new SumOfSines(frq);
296 for (int i = 0; i < 30; i++) // add 30 partials per note
297 sos->addPartial((float)i, fRandZ(), fRandZ() * CSL_TWOPI);
298 sos->createCache(); // make the cached wavetable
299 Envelope * a_env = new Envelope; // make an empty envelope
300 float tim = 0.0;
301 do { // add a bunch of break points to it
302 a_env->addBreakpoint(tim, fRandZ());
303 tim += fRandM(0.3, 0.7); // pick next time
304 } while (tim < dur);
305 a_env->addBreakpoint(dur, 0);
306 a_env->setScale(amp); // make it quiet
307 sos->setScale(*a_env); // apply env
308 a_env->trigger();
309 Panner * pan = new Panner(*sos, fRand1());
310 return (pan); // return pan
311 }
312
313 void testManyRandSOS() {
314 float duration = 20; // total dur
315 Mixer mix(2); // stereo mixer
316 for (unsigned i = 0; i < 100; i++) // play a mix of SOS instruments
317 mix.addInput(sosNote(duration, fRandM(100, 300), 0.02));
318 logMsg("playing mix of 100 random-env SOS oscs...");
319 #ifndef CSL_WINDOWS
320 srand(getpid()); // seed the rand generator -- UNIX SPECIFIC CODE HERE
321 #endif
322 runTest(mix, duration);
323 logMsg("done.\n");
324 mix.deleteInputs(); // clean up
325 }
326
327 //////// RUN_TESTS Function ////////
328
329 #ifndef USE_JUCE
330
331 void runTests() {
332 // testGliss(); // Simple sine demo tests
333 // testSwell();
334 // testFrequencyEnv(); // Basic waveform tests
335 // testARSin(); // Ways of simple scaling
336 // testARSin2(); // Ways of simple scaling
337 // testAMFMEnvs();
338 // testADSR2(); // test truncating and interpolating wavetable osc
339 // testADSR_FM();
340 // testRandFreqEnv();
341 // testEnvScale();
342 testFancy_FM();
343 }
344
345 #else
346
347 // test list for Juce GUI
348
349 testStruct envTestList[] = {
350 "Glissando test", testGliss, "Demonstrate a glissando function",
351 "Swell on aqmplitude", testSwell, "Make an amplitude swell",
352 "Frequency envelope", testFrequencyEnv, "Play a note with a frequency envelope",
353 "AR sine", testARSin, "Play an AR (attack/release) amplitude envelope",
354 // "AR sine 2", testARSin2, "",
355 "AM/FM envelopes", testAMFMEnvs, "Test AM and FM envelopes",
356 "ADSR 2", testADSR2, "Play an ADSR (attack/decay/sustain/release)",
357 "ADSR FM", testADSR_FM, "Dual-envelope FM example",
358 "Rand Freq envelope", testRandFreqEnv, "Play a random-walk frequency envelope",
359 "50 Rand F/A envs", test50RandFreqEnv, "Test 50 random frequency envelope players",
360 // "Envelope scaling", testEnvScale, "",
361 "Fancy FM", testFancy_FM, "Play a fancy FM note",
362 "Complex envelope", testComplexEnvelope, "Play a note with a complex amplitude envelope",
363 "Many random SOS", testManyRandSOS, "Layer many SumOfSines instruments with envelopes",
364 NULL, NULL, NULL
365 };
366
367 #endif