CSL  6.0
Test_Effects.cpp
Go to the documentation of this file.
1 //
2 // Test_Effects.cpp -- C main functions for the basic CSL effect and filter 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 // Examples to add
9 // chords
10 // Microphone input
11 // JUCE MIDI
12 
13 #ifndef USE_JUCE
14 #define USE_TEST_MAIN // use the main() function in test_support.h
15 #include "Test_Support.cpp" // include all of CSL core and the test support functions
16 #else
17 #include "Test_Support.h"
18 #endif
19 
20 #include "RingBuffer.h" /// Utility circular buffer
21 #include "Clipper.h"
22 #include "FIR.h"
23 #include "InOut.h"
24 #include <unistd.h>
25 
26 using namespace csl; // this is the namespace, dummy!
27 
28 /////////////////////// Here are the actual unit tests ////////////////////
29 
30 /// Clip some sound
31 
32 void testClipper() {
33  Osc vox(110); // We need some sound, so . . . let's get a sine.
34 // ADSR vol(3.0, 0.3, 2.0, 0.2, 0.5); // The amplitude envelope.
35 // vox.setScale(vol); // We set the envelope to affect the sine.
36  Clipper clipIt(vox, -0.3, 0.3); // To use clipper, just specify a min and max value.
37  logMsg("playing clipped sin...");
38  runTest(clipIt);
39  logMsg("done.\n");
40 }
41 
42 /// Test the FIR filter - LPF @ 300 Hz on pink noise
43 
44 void testFIR() {
45  // HPF test
46 // double resp[] = { 0.000001, 1 }; // amplitudes in the 2 freq bands (i.e., hi-pass)
47 // double freq[] = { 0, 800, 1200, 22050 }; // corner freqs of the pass, transition and stop bands
48 // double weight[] = { 5, 10 }; // weights for error (ripple) in the 2 bands
49 // FilterSpecification fs(33, 2, freq, resp, weight); // 33 taps, 2 bands
50  // LPF test
51 // double resp[] = { 1, 0 }; // amplitudes in the 2 freq bands (i.e., lo-pass)
52 // double freq[] = { 0, 800, 1200, 22050 }; // corner freqs of the pass, transition and stop bands
53 // double weight[] = { 5, 50 }; // weights for error (ripple) in the 2 bands
54 // FilterSpecification fs(40, 2, freq, resp, weight); // 40 taps, 3 bands
55  // BPF test
56  double resp[] = { 0., 1., 0. }; // amplitudes in the 3 freq bands (i.e., band-pass)
57  double freq[] = { 0., 200., 250., 500., 600., 44100. }; // corner freqs of the pass and stop bands
58  double weight[] = { 10., 2., 10. }; // weights for error (ripple) in the 3 bands
59  FilterSpecification fs(70, 3, freq, resp, weight); // 70 taps (70-step IR), 3 bands
60 
61 // double resp[] = { 0, 1, 0, 1, 0 }; // amplitudes in the 5 freq bands (i.e., band-pass)
62 // double freq[] = { 0, 200, 250, 500, 600, 1000, 1200, 2000, 2400, 22050 }; // corner freqs of the pass and stop bands
63 // double weight[] = { 10, 5, 10, 5, 10 }; // weights for error (ripple) in the 3 bands
64 // FilterSpecification fs(200, 5, freq, resp, weight); // 200 taps (64-step IR), 5 bands
65 
66  PinkNoise noise; // the sound source
67  FIR vox(noise, fs); // create the filter
68  vox.print_taps(); // print the filter taps
69 
70 // Butter butter1(noise, BW_HIGH_PASS, 800.0);
71 // Butter vox(butter1, BW_LOW_PASS, 800.0);
72 
73  MulOp mul(vox, 10); // scale it back up
74  logMsg("playing FIR filtered noise...");
75  runTest(mul);
76  logMsg("FIR done.");
77 }
78 
79 /// Filter tests
80 
81 void testFilters() {
82  float dur = 2.0f; // seconds to play each test for
83  // Butterworth high pass filter
84  WhiteNoise white1(0.1);
85  Butter butter(white1, BW_HIGH_PASS, 4000.0, 333.3); // corresponds to Q of 3
86  logMsg("playing Butterworth high-passed white noise...");
87 // butter.dump();
88  runTest(butter, dur);
89  logMsg("done.");
90 
91  // Butterworth band pass filter
92  WhiteNoise white2;
93  Butter butter1(white2, BW_BAND_PASS, 1000.0f, 100.0f);
94 // butter1.dump();
95  logMsg("playing Butterworth band-passed white noise...");
96 // butter1.dump();
97  runTest(butter1, dur);
98  logMsg("done.");
99 //
100  // Butterworth low pass filter
101  WhiteNoise white3;
102  Butter butter2(white3, BW_LOW_PASS, 250.0f, 100.0f);
103  logMsg("playing Butterworth low-passed white noise...");
104 // butter2.dump();
105  runTest(butter2, dur);
106  logMsg("done.");
107 //
108  // Butterworth band-stop filter
109  WhiteNoise white4(0.1);
110  Butter butter3(white4, BW_BAND_STOP, 3000.0f, 2500.0f);
111  logMsg("playing Butterworth band-rejected white noise...");
112 // butter3.dump();
113  runTest(butter3, dur);
114  logMsg("done.");
115 
116 // if (true) return;
117  // Notch filter
118  WhiteNoise white5(0.3);
119  Notch notch(white5, 500.0f, 0.99995f);
120  logMsg("playing Notch filtered white noise...");
121 // notch.dump();
122  runTest(notch, dur);
123  logMsg("done.");
124 
125  // Formant filter
126  WhiteNoise white6(0.3f);
127  Formant formant(white6, 100.0f, 0.5f);
128  logMsg("playing Formant filtered white noise...");
129 // formant.dump();
130  runTest(formant, dur);
131  logMsg("done.");
132 
133  // Allpass filter
134  Square osc(400.0f, 0.2f);
135  Allpass allpass(osc, 0.9995f);
136  logMsg("playing All-passed square wave...");
137  runTest(allpass, dur);
138  logMsg("done.");
139 
140  // a hand-built band pass filter
141  float bcoeffs[3] = {0.05f, 0.0f, -0.0496f};
142  float acoeffs[2] = {-1.843f, 0.9f};
143  WhiteNoise white0;
144  Filter filter(white0, bcoeffs ,acoeffs, 3, 2);
145  logMsg("playing BP filtered white noise...");
146  runTest(filter, dur);
147  logMsg("done.");
148 
149  // Moog filter
150 // WhiteNoise white8;
151 // Moog moog(white8, 1000.0f, 0.9f);
152 // logMsg("playing Moog filtered white noise...");
153 // runTest(moog, dur);
154 // logMsg("done.");
155 
156 }
157 
158 // Biquad (UnitGenerator & in, FilterType type, float freq, float Q, float dB)
159 // peak gain (dB) is used only for the peak and shelf types)
160 
161 void testBiquads() {
162  float dur = 2.0f; // seconds to play each test for
163  // Biquad high pass filter
164  WhiteNoise white1(0.1); // type, freq, Q, dB
165  Biquad biquad(white1, BW_HIGH_PASS, 4000.0, 1.0); // corresponds to Q of 3
166  logMsg("playing biquad high-passed white noise...");
167  runTest(biquad, dur);
168  // Biquad band pass filter
169  WhiteNoise white2;
170  Biquad biquad1(white2, BW_BAND_PASS, 1000.0f, 2.0f);
171  logMsg("playing biquad band-passed white noise...");
172  runTest(biquad1, dur);
173  // Biquad low pass filter
174  WhiteNoise white3;
175  Biquad biquad2(white3, BW_LOW_PASS, 250.0f, 1.0f);
176  logMsg("playing biquad low-passed white noise (Q = 1)...");
177  runTest(biquad2, dur);
178  // Biquad low pass filter
179  WhiteNoise white3b;
180  Biquad biquad2b(white3b, BW_LOW_PASS, 250.0f, 4.0f);
181  logMsg("playing biquad low-passed white noise (Q = 4)...");
182  runTest(biquad2b, dur);
183  // Biquad low pass filter
184  WhiteNoise white3c;
185  Biquad biquad2c(white3c, BW_LOW_PASS, 250.0f, 12.0f);
186  logMsg("playing biquad low-passed white noise (Q = 12)...");
187  runTest(biquad2c, dur);
188  // Biquad band-stop filter
189  WhiteNoise white4(0.1);
190  Biquad biquad3(white4, BW_BAND_STOP, 1000.0f, 0.5f);
191  logMsg("playing biquad band-rejected white noise...");
192  runTest(biquad3, dur);
193  // Biquad peak filter
194  WhiteNoise white4b(0.1); // type, freq, Q, dB
195  Biquad biquad3b(white4b, PEAKING, 2000.0f, 4.0f, 6.0f);
196  logMsg("playing biquad peaked white noise...");
197  runTest(biquad3b, dur);
198  // Biquad peak filter
199  WhiteNoise white4c(0.1);
200  Biquad biquad3c(white4c, PEAKING, 500.0f, 12.0f, 6.0f);
201  logMsg("playing biquad peaked white noise2...");
202  runTest(biquad3b, dur);
203  // Biquad low-shelf filter
204  WhiteNoise white5(0.1);
205  Biquad biquad4(white5, BW_LOW_SHELF, 1000.0f, 2.0f, 12.0f);
206  logMsg("playing biquad low shelf white noise...");
207  runTest(biquad4, dur);
208  // Biquad low-shelf filter
209  WhiteNoise white6(0.1);
210  Biquad biquad5(white6, BW_LOW_SHELF, 200.0f, 2.0f, -12.0f);
211  logMsg("playing biquad low shelf white noise...");
212  runTest(biquad5, dur);
213  // Biquad hi shelf filter
214  WhiteNoise white7(0.1);
215  Biquad biquad6(white7, BW_HIGH_SHELF, 3000.0f, 2.0f, 12.0f);
216  logMsg("playing biquad hi shelf white noise...");
217  runTest(biquad6, dur);
218  // Biquad hi shelf filter
219  WhiteNoise white8(0.1);
220  Biquad biquad7(white8, BW_HIGH_SHELF, 3000.0f, 2.0f, -12.0f);
221  logMsg("playing biquad hi shelf white noise...");
222  runTest(biquad7, dur);
223  logMsg("done.");
224 }
225 
226 /// Test dynamic BP filter
227 
229  float dur = 6.0f; // seconds to play each test for
230  WhiteNoise white(1.0); // noise
231  RandEnvelope center(3, 1000, 2000, 600); // center/bw freq random walk
232  RandEnvelope bw(3, 100, 100, 40); // (frq, amp, offset)
233  Butter butter(white, BW_BAND_PASS, center, bw); // Butterworth BP filter
234  logMsg("playing dynamic Butterworth band-passed white noise...");
235 // butter.dump();
236 // center.trigger();
237 // bw.trigger();
238  runTest(butter, dur);
239  logMsg("done.");
240 }
241 
242 /// Test dynamic BP filter on a sound file
243 
245  float dur = 6.0f; // seconds to play each test for
246  RandEnvelope center(4, 1400, 1800, 600); // center/bw freq random walk
247  RandEnvelope bw(5, 60, 160, 40); // (frq, amp, offset, step)
248  SoundFile sfile(CGestalt::dataFolder() + "sns.aiff"); // open a speak'n'spell file
249  Butter butter(sfile, BW_BAND_PASS, center, bw); // Butterworth BP filter
250  logMsg("playing filtered snd file...");
251  sfile.trigger();
252  runTest(butter, dur);
253  logMsg("done.");
254 }
255 
256 /// Pan and mix many sines
257 
259  int num = 20; // # of layers
260  float scale = 3.0f / (float) num; // ampl scale
261  Mixer mix(2); // stereo mixer
262  for (int i = 0; i < num; i++) { // loop to add a panning, LFO-controlled osc to the mix
263  // (frq, amp, offset, step)
264  RandEnvelope * center = new RandEnvelope(3, 1800, fRandM(2000, 4000), 200);
265  RandEnvelope * bw = new RandEnvelope(3, 200, 400, 40);
266  WhiteNoise * white = new WhiteNoise(1.0); // noise
267  Butter * butter = new Butter(*white, BW_BAND_PASS, *center, *bw);
268  MulOp * mul = new MulOp(*butter, scale);
269  Osc * lfo = new Osc(fRandM(0.3, 0.6), 1, 0, fRandM(0, CSL_PI)); // panning LFO with rand phase
270  Panner * pan = new Panner(*mul, *lfo);
271  mix.addInput(*pan);
272  }
273  logMsg("playing mix of %d Butterworth band-passed white noise layers...", num);
274 // srand(getpid()); // seed the rand generator -- UNIX SPECIFIC CODE HERE
275  runTest(mix, 8.0f);
276  logMsg("done.\n");
277  mix.deleteInputs(); // clean up
278 }
279 
280 /// Play noise bursts into reverb
281 
282 void testReverb() {
283  ADSR mChiffEnv(1, 0.01, 0.01, 0.0, 1.5); // attack-chiff envelope
284  WhiteNoise mChiff; // attack-chiff noise source
285  Butter mChFilter(mChiff, BW_BAND_PASS, 2000.0f, 500.0f); // and filter
286  mChiffEnv.setScale(10); // scale chiff envelope
287  mChFilter.setScale(mChiffEnv); // apply chiff envelope
288  Freeverb mReverb(mChFilter); // stereo reverb
289  mReverb.setRoomSize(0.95); // longer reverb
290 
291  mChiffEnv.trigger();
292  logMsg("playing Reverb test\n");
293  theIO->setRoot(mReverb); // make some sound
294  for (unsigned i = 0; i < 4; i++) {
295  mChiffEnv.trigger();
296  sleepSec(4);
297  }
298  sleepSec(6);
299  theIO->clearRoot();
300  logMsg("done.\n");
301 }
302 
303 /// Play noise bursts into reverb
304 
306  ADSR mEnv(1, 0.005, 0.01, 0.0, 1.5); // attack-chiff envelope
307  WhiteNoise mChiff; // attack-chiff noise source
308  float ctrFrq = fRandB(3000, 1000); // filter center freq
309  Butter mFilter(mChiff, BW_BAND_PASS, ctrFrq, 500.0f); // BP filter
310  mEnv.setScale(10); // scale chiff envelope
311  mFilter.setScale(mEnv); // apply chiff envelope
312 
313  Panner mPanner(mFilter, 0.0); // stereo panner
314  Stereoverb mReverb(mPanner); // stereo reverb
315  mReverb.setRoomSize(0.988); // long reverb time
316 
317  theIO->setRoot(mReverb); // start sound output
318 #ifndef CSL_WINDOWS
319  srand(getpid()); // seed the rand generator -- UNIX SPECIFIC CODE HERE
320 #endif
321  float nap = 1.0f; // sleep time between noise bursts
322  logMsg("playing Stereoverb test\n");
323  for (unsigned i = 0; i < 10; i++) { // play a loop of notes
324  mPanner.setPosition(fRand1()); // select a random stereo position
325  mEnv.trigger(); // trigger the burst envelope
326  sleepSec(nap); // sleep a few seconds
327  nap *= 1.25f; // slow down
328  mFilter.setFrequency(fRandB(2000, 1000)); // pick a new frequency, 2k +- 1k
329  }
330  sleepSec(2); // sleep at the end to let it die out
331  theIO->clearRoot();
332  logMsg("done.\n");
333 }
334 
335 /// Play noise bursts into multi-tap delay line
336 
337 void testMultiTap() {
338  ADSR mChiffEnv(1, 0.01, 0.01, 0.0, 1.5); // attack-chiff envelope
339  WhiteNoise mChiff; // attack-chiff noise source
340  Butter mChFilter(mChiff, BW_BAND_PASS, 2000.0f, 500.0f); // and filter
341  mChiffEnv.setScale(10); // scale chiff envelope
342  mChFilter.setScale(mChiffEnv); // apply chiff envelope
343 
344  RingBuffer rbuf(mChFilter, 1, 22050); // mono, 1.2 sec.
345  rbuf.mTap.setOffset(2000);
346  RingBufferTap tap1(& rbuf, 4000);
347  RingBufferTap tap2(& rbuf, 8000);
348  RingBufferTap tap3(& rbuf, 12000);
349  RingBufferTap tap4(& rbuf, 16000);
350  RingBufferTap tap5(& rbuf, 20000);
351 
352  Mixer mix(2); // create a stereo mixer
353  mix.addInput(rbuf); // add the taps to the mixer
354  mix.addInput(tap1);
355  mix.addInput(tap2);
356  mix.addInput(tap3);
357  mix.addInput(tap4);
358  mix.addInput(tap5);
359 
360  mChiffEnv.trigger();
361  logMsg("");
362  logMsg("playing multi-tap delay test\n");
363  theIO->setRoot(mix); // make some sound
364  for (unsigned i = 0; i < 4; i++) {
365  mChiffEnv.trigger();
366  sleepSec(1);
367  }
368 // sleepSec(3);
369  theIO->clearRoot();
370  logMsg("done.\n");
371 }
372 
373 /// Test a block resizer by running a random gliss with a small block size
374 
376  float dur = 6.0f; // seconds to play each test for
377  Osc vox; // declare an oscillator
378  AR a_env(6, 1, 1); // dur, att, rel
379  RandEnvelope f_env(3, 80, 200, 40); // freq env = random walk
380  vox.setFrequency(f_env); // set the carrier's frequency
381  vox.setScale(a_env); // multiply index envelope by mod freq
382  a_env.trigger();
383  BlockResizer blocker(vox, 300); // small buffer, not a divisor of CSL's block size
384  logMsg("playing random gliss in a block up-sizer...");
385  runTest(blocker, dur); // run test
386  logMsg("done.");
387 }
388 
389 /// Test a block resizer by running a random gliss with a huge block size
390 
392  float dur = 6.0f; // seconds to play each test for
393  Osc vox; // declare an oscillator
394  AR a_env(6, 1, 1); // dur, att, rel
395  RandEnvelope f_env(3, 80, 200, 40); // freq env = random walk
396  vox.setFrequency(f_env); // set the carrier's frequency
397  vox.setScale(a_env); // multiply index envelope by mod freq
398  a_env.trigger();
399  BlockResizer blocker(vox, 1100); // large buffer, not a multiple of CSL's block size
400  logMsg("playing random gliss in a block down-sizer...");
401  runTest(blocker, dur); // run test
402  logMsg("done.");
403 }
404 
405 /// Test a Split/Join with a cross-over filter pair LPF to left, HPF to the right
406 
408  float dur = 6.0f; // seconds to play each test for
409  SumOfSines sos1(16, 0.5); // create a cmoplex sum-of-sines
410  sos1.createCache(); // make the cached wavetable
411  AR a_env(6, 1, 1); // dur, att, rel
412  RandEnvelope f_env(3, 180, 300, 40); // freq env = random walk
413  sos1.setFrequency(f_env); // set the carrier's frequency
414  sos1.setScale(a_env); // multiply index envelope by mod freq
415  a_env.trigger(); // start the envelope
416  Panner pan(sos1, 0); // stereo panner, center
417 
418  Splitter split(pan); // stereo-to-mono splitter
419  Butter lpf(split, BW_LOW_PASS, 500.0, 333.3); // lo-pass with Q of 3
420  Butter hpf(split, BW_HIGH_PASS, 500.0, 333.3); // hi-pass with Q of 3
421  Joiner join(lpf, hpf); // mono-to-stereo joiner
422 
423  logMsg("playing splitter/joiner/mixer-based crossover filter...");
424  runTest(join, dur); // run test
425  logMsg("done.");
426 }
427 
428 /// Test a Split/Join with a cross-over filter pair LPF to left, HPF to the right
429 /// mixer added in just for show
430 
432  float dur = 6.0f; // seconds to play each test for
433  SumOfSines sos1(16, 0.5); // create a cmoplex sum-of-sines
434  sos1.createCache(); // make the cached wavetable
435  AR a_env(6, 1, 1); // dur, att, rel
436  RandEnvelope f_env(3, 180, 300, 40); // freq env = random walk
437  sos1.setFrequency(f_env); // set the carrier's frequency
438  sos1.setScale(a_env); // multiply index envelope by mod freq
439  a_env.trigger(); // start the envelope
440  Panner pan(sos1, 0); // stereo panner, center
441  Mixer mix1(2); // stereo mixer, fixed
442  mix1.addInput(pan);
443 
444  Splitter split(mix1); // stereo-to-mono splitter
445  Butter lpf(split, BW_LOW_PASS, 500.0, 333.3); // lo-pass with Q of 3
446  Butter hpf(split, BW_HIGH_PASS, 500.0, 333.3); // hi-pass with Q of 3
447  Joiner join(lpf, hpf); // mono-to-stereo joiner
448  Mixer mix2(2); // stereo mixer, fixed
449  mix2.addInput(join);
450 
451  logMsg("playing splitter/joiner/mixer-based crossover filter...");
452  runTest(mix2, dur); // run test
453  logMsg("done.");
454 }
455 
456 /// Test a fan-out + mixer using UnitGenerator's built-in fan-out
457 
458 void testFanMix1() {
459  float dur = 6.0f; // seconds to play each test for
460  Osc vox; // declare an oscillator
461  AR a_env(6, 1, 1); // dur, att, rel
462  RandEnvelope f_env(3, 80, 200, 40); // freq env = random walk
463  vox.setFrequency(f_env); // set the carrier's frequency
464  a_env.setScale(0.5); // multiply index envelope by mod freq
465  vox.setScale(a_env); // multiply index envelope by mod freq
466  a_env.trigger(); // start the envelope
467  Panner pan(vox, fRand1()); // stereo panner
468 
469  Mixer mix(2); // stereo mixer, fixed
470  mix.addInput(pan); // add panner twice
471  mix.addInput(pan);
472 
473  logMsg("playing fan-out + mixer 1...");
474  runTest(mix, dur); // run test
475  logMsg("done.");
476 }
477 
478 /// Test a real fan-out + mixer
479 
480 void testFanMix2() {
481  float dur = 6.0f; // seconds to play each test for
482  Osc vox; // declare an oscillator
483  AR a_env(6, 1, 1); // dur, att, rel
484  RandEnvelope f_env(3, 80, 200, 40); // freq env = random walk
485  vox.setFrequency(f_env); // set the carrier's frequency
486  a_env.setScale(0.5); // multiply index envelope by mod freq
487  vox.setScale(a_env); // multiply index envelope by mod freq
488  a_env.trigger(); // start the envelope
489  Panner pan(vox, fRand1()); // stereo panner
490 
491  FanOut fan(pan, 2); // send the panner to 2 mixer ins
492  Mixer mix(2); // stereo mixer, fixed
493  mix.addInput(fan); // add fan-out twice
494  mix.addInput(fan);
495 
496  logMsg("playing fan-out + mixer 2...");
497  runTest(mix, dur); // run test
498  logMsg("done.");
499 }
500 
501 /// Function to create and answer a RandFreqEnv UGen patch
502 /// this is in test envelopes
503 
505 
506 /// Mix a few sources, adding/dropping graphs
507 
509  float duration = 4.0f; // seg dur
510  float pauset = 0.5f; // pause dur
511  float scale = 8.0f; // ampl scale
512  Mixer mix(2); // stereo mixer
513 
514  UGenVector insts;
515 
516  for (unsigned i = 0; i < 4; i++) { // loop to add 4 srcs to the mix
517  UnitGenerator * pan = createRandFreqEnvPatch(duration);
518  mix.addInput(*pan);
519  mix.scaleInput(*pan, scale);
520  insts.push_back(pan);
521  }
522  logMsg("playing mix of 4 sweep layers...");
523 // srand(getpid()); // seed the rand generator -- UNIX SPECIFIC CODE HERE
524  runTest(mix, duration);
525  sleepSec(pauset); // wait some
526 
527  UGenVector * ins = mix.getInputs();
528  for (unsigned i = 0; i < 2; i++) // remove 2 inputs
529  mix.removeInput(insts[i]);
530  logMsg("removed 2");
531  runTest(mix, duration);
532  sleepSec(pauset); // wait some
533 
534  for (unsigned i = 0; i < 4; i++) { // add 4 more
535  UnitGenerator * pan = createRandFreqEnvPatch(duration);
536  mix.addInput(*pan);
537  mix.scaleInput(*pan, scale);
538  }
539  logMsg("added 4");
540  runTest(mix, duration);
541  sleepSec(pauset); // wait some
542 
543  ins = mix.getInputs();
544  for (unsigned i = 2; i < 5; i++) // remove 3
545  mix.removeInput((*ins)[i]);
546  logMsg("removed 3");
547  runTest(mix, duration);
548  sleepSec(pauset); // wait some
549 
550  for (unsigned i = 0; i < 2; i++) { // add 2 more
551  mix.addInput(insts[i]);
552  mix.scaleInput(*insts[i], scale);
553  }
554  logMsg("added 2");
555  runTest(mix, duration);
556  sleepSec(pauset); // wait some
557 
558  ins = mix.getInputs();
559  for (unsigned i = 0; i < 6; i++) // remove all but one
560  mix.removeInput((*ins)[i]);
561  logMsg("removed all but one");
562  runTest(mix, duration);
563 
564  logMsg("done.\n");
565  mix.deleteInputs(); // clean up
566 }
567 
568 // Simple sample-average filter class - an example of a custom UnitGenerator definition
569 // This implements nextBuffer() with its own DSP routine: a scaled past-sample averager (lo-pass filter)
570 
571 class SAFliter : public Effect { // It's an Effect/UnitGenerator
572 public: // created with an input UGen &scale coeff
573  SAFliter(UnitGenerator & in, float coeff = 0.5f) : Effect(in), mCoeff(coeff), mStore(0) { };
574  ~SAFliter() { };
575  // nextBuffer() gets input and operates on it
576  void nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
577  unsigned numFrames = outputBuffer.mNumFrames; // get buffer length
578  csl::SampleBuffer out = outputBuffer.buffer(outBufNum); // get ptr to output channel
579 
580  Effect::pullInput(numFrames); // get my input buffer
581  csl::SampleBuffer inPtr = mInputPtr; // get a pointer to the input samples
582 
583  float val;
584  for (unsigned i = 0; i < numFrames; i++) { // here's the filter loop
585  val = *inPtr++ * mCoeff; // get next input sample, scale
586  *out++ = val + mStore; // put current output in the buffer and increment
587  mStore = val; // store val
588  }
589  }
590 protected: // class' data members
591  float mCoeff, mStore; // scale coeff & past value
592 }; // end of class SAFliter
593 
594 // test it
595 
596 void testSAFilter() {
597  SoundFile sfile(CGestalt::dataFolder() + "sns.aiff"); // open a speak'n'spell file
598 
599  SAFliter averager(sfile); // s-a filter
600  logMsg("playing filtered snd file...");
601  runTest(averager, 5.0);
602  logMsg("done.");
603 }
604 
605 //////// RUN_TESTS Function ////////
606 
607 #ifndef USE_JUCE
608 
609 void runTests() {
610 // testClipper(); // Simple clipper tests
611 // testFIR(); // Noise filtering test
612 // testFilters();
613 // testDynamicFilters();
614 // testReverb();
615  testStereoverb();
616 // testMultiTap();
617 }
618 
619 #else
620 
621 // test list for Juce GUI
622 
624  "Clipper", testClipper, "Demonstrate the signal clipper",
625  "FIR filter", testFIR, "Play an FIR band-pass filter",
626  "All filters", testFilters, "Test different filter types",
627  "Biquad filters", testBiquads, "Test biquad filter types",
628  "Filtered snd file", testDynamicVoice, "Dynamic BPF on a voice track",
629  "Dynamic filter", testDynamicFilters, "Play a dynamic BP filter on noise",
630  "Many dynamic filters", testNDynamicFilters, "Many dynamic filtered-noise instruments",
631  "Reverb", testReverb, "Show mono reverb on impulses",
632  "Stereo-verb", testStereoverb, "Listen to the stereo reverb",
633  "Multi-tap delay", testMultiTap, "Play a multi-tap delay line",
634  "Split/Join filter", testSplitJoin1, "Play a splitter/joiner cross-over filter",
635  "Split/Join/Mix filter", testSplitJoin2, "Play a splitter/joiner/mixer cross-over filter",
636  "FanOut + Mixer 1", testFanMix1, "Play a sound through fan-out + mixer",
637  "FanOut + Mixer 2", testFanMix2, "Play a sound through fan-out + mixer",
638  "Dynamic Mixer", testDynamicMixer, "Mix adding/dropping sources",
639  "Block up-sizer", testBlockUpsizer, "Test the block resizer on up-sizing",
640  "Block down-sizer", testBlockDownsizer, "Test the block resizer on down-sizing",
641  "Sample-avg filter", testSAFilter, "Demo in-line sample-average-filter class",
642  NULL, NULL, NULL
643 };
644 
645 #endif
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
Definition: CSL_Types.h:194
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
void testFanMix1()
Test a fan-out + mixer using UnitGenerator's built-in fan-out.
void pullInput(Buffer &outputBuffer)
Definition: CSL_Core.cpp:1122
void testFIR()
Test the FIR filter - LPF @ 300 Hz on pink noise.
RingBuffer is the storage + a default reader.
Definition: RingBuffer.h:56
IO * theIO
void setOffset(int offset)
Definition: RingBuffer.cpp:27
void testFilters()
Filter tests.
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
forward declaration
Definition: FIR.h:25
Effect – mix-in for classes that have unit generators as inputs (like filters).
Definition: CSL_Core.h:466
virtual void trigger()
reset internal time to restart envelope
Definition: Envelope.cpp:284
Regularizes the amount of data called for. This is useful for time-frequency transformations that onl...
Definition: BlockResizer.h:24
UnitGenerator * createRandFreqEnvPatch(float dur)
Function to create and answer a RandFreqEnv UGen patch this is in test envelopes. ...
#define PEAKING
Definition: Filters.h:57
void testSplitJoin2()
Test a Split/Join with a cross-over filter pair LPF to left, HPF to the right mixer added in just for...
testStruct effTestList[]
UGenVector * getInputs(void)
Definition: Mixer.h:29
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
really compute the next buffer given an offset base channel; this is called by nextBuffer, possibly multiple times
#define BW_LOW_SHELF
Definition: Filters.h:55
void setRoomSize(float size)
Setting the room size makes longer tails. The value has a range from 0 to 1.
Definition: Freeverb.cpp:143
#define BW_HIGH_SHELF
Definition: Filters.h:56
RingBufferTap mTap
internal tap so a RingBuffer can also be a a UnitGenerator
Definition: RingBuffer.h:67
float mStore
void testDynamicFilters()
Test dynamic BP filter.
Filter: the canonical-form n-pole/m-zero filter class.
Definition: Filters.h:99
void print_taps()
Definition: FIR.cpp:165
White noise – equal power per frequency.
Definition: Noise.h:45
void removeInput(UnitGenerator &inp)
Definition: Mixer.cpp:69
Notch Filter with poles at +-z and complex conjugate zeros at +-omega.
Definition: Filters.h:208
void testSAFilter()
struct used for the JUCE pop-up menu of tests (see the test files)
Definition: CSL_Types.h:265
#define BW_LOW_PASS
Definition: Filters.h:51
void testBlockDownsizer()
Test a block resizer by running a random gliss with a huge block size.
Square oscillator class (non-band-limited)
Definition: Oscillator.h:136
#define CSL_PI
Definition: CSL_Types.h:334
Allpass Filter with a pole and a zero at equal frequency and straddling the unit circle. Allows all freqs to pass through but messes with phases.
Definition: Filters.h:225
void testMultiTap()
Play noise bursts into multi-tap delay line.
void testBlockUpsizer()
Test a block resizer by running a random gliss with a small block size.
void testDynamicVoice()
Test dynamic BP filter on a sound file.
Examples.
Definition: FIR.h:74
float fRandM(float minV, float maxV)
min - max (min/max)
Definition: CGestalt.cpp:426
#define BW_BAND_PASS
Definition: Filters.h:53
General-purpose Biquad IIR (2nd order recursive) filter. This is simplified and optimized, but doesn't support dynamic or scalable controls. It uses inst vars rather than arrays for the coefficients. NB: peak gain (dB) is used only for the peak and shelf types)
Definition: Filters.h:161
float fRandB(float base, float range)
b +- r (base)
Definition: CGestalt.cpp:438
void setPosition(UnitGenerator &pan)
Operations.
Definition: Mixer.cpp:279
void testStereoverb()
Play noise bursts into reverb.
#define Osc
Definition: CSL_Types.h:169
void testClipper()
Clip some sound.
void setRoomSize(float size)
Definition: Freeverb.cpp:235
CSL port of the public domain Freeverb reverberator.
Definition: Freeverb.h:23
ADSR = 4-segment attack/decay/sustain/release envelope class.
Definition: Envelope.h:153
Clipper class.
Definition: Clipper.h:25
bool sleepSec(float dur)
Definition: CGestalt.cpp:379
std::vector< UnitGenerator * > UGenVector
Definition: CSL_Types.h:241
#define BW_HIGH_PASS
Definition: Filters.h:52
Splitter class – a de-multiplexer for multi-channel signals.
Definition: CSL_Core.h:633
void testNDynamicFilters()
Pan and mix many sines.
void testReverb()
Play noise bursts into reverb.
void runTest(UnitGenerator &vox, double dur)
MulOp – A BinaryOp that multiplies two UnitGenerators or fixed constants together, sample-by-sample.
Definition: BinaryOp.h:104
void scaleInput(UnitGenerator &inp, float val)
set the scale of an input
Definition: Mixer.cpp:102
void setFrequency(UnitGenerator &frequency)
set the receiver's frequency to a UGen or a float
Definition: Filters.cpp:27
Formant Filter with zeros at +-z and complex conjugate poles at +-omega. setupCoeffs() looks at the m...
Definition: Filters.h:190
RingBufferTap is a reader that loops over a buffer.
Definition: RingBuffer.h:21
RandEnvelope envelope class – makes random control signals using a single line segment.
Definition: Envelope.h:247
Butterworth IIR (2nd order recursive) filter.
Definition: Filters.h:137
void setFrequency(UnitGenerator &frequency)
Setter accessors.
Definition: CSL_Core.cpp:981
void setRoot(UnitGenerator &root)
set/clear my graph root generator
Definition: CSL_Core.cpp:1405
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
Mixer – The n-input m-channel mixer class.
Definition: Mixer.h:21
void testSplitJoin1()
Test a Split/Join with a cross-over filter pair LPF to left, HPF to the right.
void runTests()
void clearRoot()
Definition: CSL_Core.cpp:1410
Joiner class – a multiplexer for multi-channel signals.
Definition: CSL_Core.h:648
AR = 3-segment attack/release envelope class.
Definition: Envelope.h:199
The CSL mono-to-stereo L/R panner class.
Definition: Mixer.h:66
#define BW_BAND_STOP
Definition: Filters.h:54
void testFanMix2()
Test a real fan-out + mixer.
forward declaration
Definition: CSL_Core.h:241
void testBiquads()
void addInput(UnitGenerator &inp)
Definition: Mixer.cpp:43
void testDynamicMixer()
Mix a few sources, adding/dropping graphs.
float fRand1(void)
-1 - 1 (one)
Definition: CGestalt.cpp:420
SAFliter(UnitGenerator &in, float coeff=0.5f)
void setScale(UnitGenerator &scale)
set the receiver's scale member to a UGen or a float
Definition: CSL_Core.cpp:1039
A fan-out generator for DSP graphs with loops.
Definition: CSL_Core.h:615
void deleteInputs()
Definition: Mixer.cpp:114
Pink noise – equal power per octave.
Definition: Noise.h:66
Base class of CSL exceptions (written upper-case). Has a string message.
static std::string dataFolder()
the default directory for test data
Definition: CGestalt.cpp:71