CSL  5.2
Test_Oscillators.cpp
Go to the documentation of this file.
1 //
2 // Test_Oscillators.cpp -- C main functions for the basic CSL oscillator source 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 #ifdef USE_JUCE
10  #include "Test_Support.h"
11 #else
12  #define USE_TEST_MAIN // use the main() function in test_support.h
13  #include "Test_Support.cpp" // include all of CSL core and the test support functions
14 #endif
15 
16 #ifdef USE_JSND
17  #include "SoundFileJ.h"
18 #else
19  #include "SoundFileL.h"
20 #endif
21 
22 #include "SimpleSines.h"
23 
24 /////////////////////// Here are the actual unit tests ////////////////////
25 
26 /// Apply a glissando and swell to a sine oscillator with LineSegments
27 
28 void testSweep() {
29  Osc vox; // wave-table oscillator
30  LineSegment gliss(5, 40, 1000); // freq line (dur val1, val2)
31  LineSegment swell(5, 0.000001, 0.8); // ampl line
32  vox.setFrequency(gliss); // apply freq function
33  vox.setScale(swell); // apply ampl function
34 // vox.dump();
35  logMsg("playing swept sin with line segment...");
36  runTest(vox, 5); // play vox for 5 seconds
37  logMsg("done.\n");
38 }
39 
40 /// Simplest sine wave tests using the tutorial example classes
41 
43  float freq = 220.0; // choose a frequency in Hz
44  SimpleSine sineOsc(freq); // create a simple sine oscillator
45  sineOsc.dump();
46  logMsg("playing simple sin...");
47  runTest(sineOsc); // call the test function that runs this for a few seconds
48  logMsg("sin done.");
49  SineAsPhased sineOsc2(freq); // create a sine-as-phased oscillator
50  sineOsc2.dump();
51  logMsg("playing sin-as-phased...");
52  runTest(sineOsc2); // call the test function that runs this for a few seconds
53  logMsg("sin done.");
54  SineAsScaled sineOsc3(freq, 0, 0.2, 0); // sine-as-scaled constructor args: freq, phase, scale, offset
55  sineOsc3.dump();
56  logMsg("playing sin-as-scaled...");
57  runTest(sineOsc3); // call the test function that runs this for a few seconds
58  logMsg("sin done.");
59 }
60 
61 /// Test/demonstrate the basic waveform oscillators
62 
64  float freq = 220.0; // choose a frequency in Hz
65  float ampl = 0.4; // choose an amplitude scale
66 
67  Sine sine(freq, ampl); // create a computed sine oscillator
68  logMsg("playing computed sin...");
69 // sine.dump();
70  runTest(sine); // call the test function that runs this for a few seconds
71 // dumpTest(sine); // or just dump the graph
72  logMsg("done.\n");
73  sleepMsec(250);
74 
75  Osc wav(freq, ampl, 0.0, 0.0); // create a wave-table sine oscillator
76  logMsg("playing wavetable sin...");
77  runTest(wav); // call the test function that runs this for a few seconds
78  logMsg("done.\n");
79  sleepMsec(250);
80 
81  Sawtooth saw(freq, ampl); // create a sawtooth oscillator
82  logMsg("playing sawtooth...");
83  runTest(saw); // call the test function that runs this for a few seconds
84  logMsg("done.\n");
85  sleepMsec(250);
86 
87  Square square(freq, ampl); // create a square oscillator
88  logMsg("playing square...");
89  runTest(square); // call the test function that runs this for a few seconds
90  logMsg("done.\n");
91  sleepMsec(250);
92 
93 // Impulse impulse(freq, ampl); // create an impulse oscillator
94 // logMsg("playing impulse...");
95 // runTest(impulse); // call the test function that runs this for a few seconds
96 // logMsg("done.");
97 }
98 
99 /// Scaled sine wave -- 3 methods: with a MulOp and using the Sine's scale input
100 
102  Osc osc(220);
103  osc.setScale(0.4); // simplest: scale the sine directly
104  logMsg("playing quiet sin1 (setScale)...");
105  runTest(osc);
106  logMsg("quiet sin done.");
107  sleepMsec(250);
108 
109  Osc sineOsc2(220);
110  MulOp mul(sineOsc2, 0.4); // using a MulOp with a constant
111  logMsg("playing quiet sin2 (MulOp)...");
112  mul.dump();
113  runTest(mul);
114  logMsg("quiet sin done.");
115  sleepMsec(250);
116 
117  Osc sineOsc3(220);
118  StaticVariable var(0.4); // using a MulOp with a StaticVariable
119  MulOp mul2(sineOsc3, var);
120  logMsg("playing quiet sin3 (StaticVar)...");
121  runTest(mul2);
122  logMsg("quiet sin done.");
123 }
124 
125 /// Test truncating and interpolating wavetable osc with a small wavetable
126 /// (these should sound different because of the truncation error in the first tone)
127 
128 #define TABLE_SIZE 128
129 
131  float sineTable[TABLE_SIZE];
132  float * ptr = & sineTable[0];
133  float incr = CSL_TWOPI / TABLE_SIZE;
134  float accum = 0;
135  for (unsigned i = 0; i < TABLE_SIZE; i++) {
136  *ptr++ = sin(accum);
137  accum += incr;
138  }
139  Buffer oscBuff(1, TABLE_SIZE);
140  oscBuff.setBuffer(0, sineTable);
141  oscBuff.mAreBuffersAllocated = true;
142  Osc wav(oscBuff);
143  wav.setScale(0.4);
144  logMsg("playing truncating wavetable...");
145  runTest(wav); // call the test function that runs this
146  logMsg("done.\n");
147  sleepMsec(250);
148  wav.setInterpolate(kLinear); // set the oscillator's interpolation policy
149  logMsg("playing interpolating wavetable...");
150  runTest(wav); // re-play test
151  logMsg("done.\n");
152 }
153 
154 /// AM and FM using the dynamic scale and frequency inputs
155 
156 void testAMFMSin() {
157  Osc osc(220); // carrier to be AM'ed
158  Osc AMmod(6, 0.3, 0.4); // AM osc: freq, scale, offset
159 // mod.setScale(0.2); // another way to scale the AM osc
160 // mod.setOffset(0.8); // or to offset the AM osc
161  osc.setScale(AMmod); // amplitude modulate the sine
162  logMsg("Simple AM/FM sin Examples");
163  osc.dump();
164  logMsg("playing AM sin...");
165  runTest(osc);
166  logMsg("AM sin done.\n");
167 
168  Osc osc2; // carrier to be FM'ed
169  Osc FMmod(4, 40, 220); // FM osc: freq, scale, offset
170  osc2.setFrequency(FMmod); // FM using setFrequency()
171  osc2.setScale(0.5); // scale the osc (quieter)
172  osc2.dump();
173  logMsg("playing FM sin...");
174  runTest(osc2);
175  logMsg("FM sin done.\n");
176 }
177 
178 /// use the dumpTest call to dump the whole graph
179 
180 void dumpAMFMSin() {
181  Osc osc;
182  Osc AMmod(6, 0.2, 0.8); // AM osc: freq, scale, offset
183  Osc FMmod(110, 10, 110); // FM osc: freq, scale, offset
184  osc.setScale(AMmod); // amplitude modulate the sine
185  osc.setFrequency(FMmod); // FM using setFrequency()
186  logMsg("Dumping AM/FM sin...");
187  osc.dump();
188  dumpTest(osc);
189  logMsg("Playing AM/FM sin...");
190  runTest(osc);
191  logMsg("AM/FM sin done.\n");
192 }
193 
194 /// Play a sum of sines waveform -- cached harmonic overtone series
195 
197  // constructor format kFrequency = list of amplitudes for first n overtones
198  SumOfSines sos1(kFrequency, 5, 0.4, 0.2, 0.1, 0.05, 0.02);
199  sos1.setFrequency(220);
200  sos1.setScale(0.2); // make it quiet
201  logMsg("Sum of sines Examples");
202  sos1.dump();
203  logMsg("playing uncached sum of sines...");
204  runTest(sos1);
205  logMsg("sum of sines done.\n");
206  sleepMsec(250);
207 
208  sos1.createCache(); // make the cached wavetable
209  logMsg("playing cached sum of sines...");
210  runTest(sos1);
211  logMsg("sum of sines done.\n");
212 }
213 
214 /// Play a sum of sines waveform -- 1/f + noise
215 
217  // constructor format # harms, rand noise around 1/f weighting
218  SumOfSines sos1(16, 0.5);
219  sos1.setFrequency(220);
220  sos1.createCache(); // make the cached wavetable
221  sos1.setScale(0.2); // make it quiet
222  logMsg("Sum of sines 1/f");
223  runTest(sos1);
224  logMsg("sum of sines done.\n");
225 }
226 
227 // play a loop that adds upper harmonics in steps
228 
230  SumOfSines sos2(kFrequency, 3, 0.4, 0.2, 0.1);
231  sos2.setFrequency(220);
232  sos2.setScale(0.2); // make it quiet
233  logMsg("playing sum of sines loop...");
234  for (unsigned i = 3; i < 11; i++) {
235  sos2.addPartial(i*2, (0.6 / i));
236 // sos2.dump();
237  runTest(sos2, 2);
238  }
239  logMsg("sum of sines done.");
240 }
241 
242 /// Now test an uncached inharmonic series
243 /// constructor format 3 = list of (freq/amp/phase) for (not-necessarily-harmonic) overtones
244 /// Since it's a non-harmonic overtone series in this example, we can't cache a wavetable
245 
247  SumOfSines vox2(kFreqAmpPhase, 4, 1.0, 0.2, 1.0, 1.08, 0.2, 2.0,
248  1.2, 0.1, 3.0, 1.34, 0.02, 4.0);
249  vox2.setFrequency(220);
250  vox2.setScale(0.5); // make it quiet
251 
252  logMsg("playing uncached sum of sines...");
253  runTest(vox2, 5);
254  logMsg("sum of sines done.");
255 }
256 
257 /// Load an oscillator's wave table from a file -- a single cycle of the vowel "oo" from the word "moon"
258 
260  SoundFile fi(CGestalt::dataFolder() + "oo_table.aiff");
261  fi.openForRead();
262  logMsg("Loading sound file %s = %d frames @ %d Hz", fi.path().c_str(), fi.duration(), fi.playbackRate());
263 // fi.seekTo(0, kPositionStart);
264  Buffer oscBuff(1, fi.duration());
265  oscBuff.setBuffer(0, fi.mWavetable.monoBuffer(0));
266  oscBuff.mAreBuffersAllocated = true;
267  Osc wav(oscBuff);
268  logMsg("playing wavetable from file...");
269  runTest(wav); // call the test function that runs this for a few seconds
270  logMsg("done.");
271 }
272 
273 /// Test loading the SHARC samples
274 
275 #ifndef CSL_WINDOWS
276 
277 #include <SHARC.h>
278 
279 void test_SHARC() {
280  SHARCLibrary::loadDefault(); // load the SHARC library
281  SHARCLibrary * lib = SHARCLibrary::library();
282  lib->dump();
283  SHARCInstrument * inst = lib->instrument_named("bassoon");
284  SHARCSpectrum * spect = inst->_spectra[4]; // get a spectrum and make a SumOfSines
285  SumOfSines sos(* spect);
286  sos.setFrequency(110);
287  ADSR adsr(2, 0.04, 0.1, 0.6, 1.0); // make an ADSR
288  sos.setScale(adsr);
289  logMsg("playing SHARC sum of sines...");
290  adsr.trigger();
291  runTest(sos, 2);
292  logMsg("done.\n");
293 }
294 
295 /// test vector SHARC - load 3 spectra into SOS oscillators and cross-fade
296 
297 void test_SHARC2() {
298  float dur = 6.0f;
299  SHARCLibrary::loadDefault();
300  SHARCLibrary * lib = SHARCLibrary::library();
301  // 3 spectra from the SHARC library
302  SHARCSpectrum * spect1 = lib->spectrum("oboe", 60);
303  SHARCSpectrum * spect2 = lib->spectrum("tuba", 40);
304  SHARCSpectrum * spect3 = lib->spectrum("viola_vibrato", 60);
305  SumOfSines sos1(*spect1); // create 3 SOS oscs
306  SumOfSines sos2(*spect2);
307  SumOfSines sos3(*spect3);
308  sos1.setFrequency(110); // set freqs
309  sos2.setFrequency(220);
310  sos3.setFrequency(110);
311  // 3 envelopes
312  LineSegment env1(dur, 1, 0.0001); // fade out
313  sos1.setScale(env1);
314  Triangle env2(dur); // triangle
315  sos2.setScale(env2);
316  LineSegment env3(dur, 0.0001, 1); // fade in
317  sos3.setScale(env3);
318  Mixer mix(1); // mix 'em
319  mix.addInput(sos1);
320  mix.addInput(sos2);
321  mix.addInput(sos3);
322  Freeverb revb(mix); // mono reverb
323  revb.setRoomSize(0.985); // longer reverb
324  Panner pan(revb); // stereo panner
325  logMsg("playing SHARC vector synth...");
326  env1.trigger(); // trigger envelopes
327  env2.trigger();
328  env3.trigger();
329  runTest(pan, dur); // run test fcn
330  logMsg("done.\n");
331 }
332 #endif
333 
334 //////// RUN_TESTS Function ////////
335 
336 #ifndef USE_JUCE
337 
338 void runTests() {
339  testSimpleSines(); // Simple sine demo tests
340 // testBasicWaves(); // Basic waveform tests
341 // testScaledSin(); // Ways of simple scaling
342 // testWavetableInterpolation(); // test truncating and interpolating wavetable osc
343 // testAMFMSin(); // Examples of AM and FM
344 // dumpAMFMSin(); // Examples of AM and FM
345 // testSumOfSinesCached(); // Sum Of Sines tests
346 // testSumOfSinesNonCached(); // Sum Of Sines tests
347 // testWaveTableFromFile(); // load a wavetable from a sound file
348 // testSweep();
349 }
350 
351 #else
352 
353 // test list for Juce GUI
354 
355 testStruct oscTestList[] = {
356  "Sweep test", testSweep, "Test a sine with swept freq and volume swell",
357  "Simple sines", testSimpleSines, "Test some simple sine oscilators",
358  "Standard waveforms", testBasicWaves, "Demonstrate the standard wave forms",
359  "Scaled sine", testScaledSin, "Play a scaled-quiet sine wave",
360  "Wavetable interpolation", testWavetableInterpolation, "Show truncated/interpolated wave tables",
361  "AM/FM sines", testAMFMSin, "Play an AM and FM sine wave",
362  "Dump AM/FM sines", dumpAMFMSin, "Dump the graph of the AM/FM sine",
363  "SumOfSines cached", testSumOfSinesCached, "Play a sum-of-sines additive oscillator",
364  "SumOfSines non-cached", testSumOfSinesNonCached, "Play an uncached inharmonic sum-of-sines",
365  "SumOfSines build", testSumOfSinesSteps, "Build up a harmonic series on a sum-of-sines",
366  "SumOfSines 1/f", testSumOfSines1F, "Play a 1/f spectrum sum-of-sines",
367  "Wavetable from file", testWaveTableFromFile, "Play a wave table from a sound file",
368 #ifndef CSL_WINDOWS
369  "SHARC SOS", test_SHARC, "Load/print the SHARC timbre database, play example",
370  "Vector SHARC", test_SHARC2, "Show vector cross-fade of SHARC spectra",
371 #endif
372  NULL, NULL, NULL
373 };
374 
375 #endif