CSL 5.2

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

- File List
- File Members

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
42 void testSimpleSines() {
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
63 void testBasicWaves() {
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
101 void testScaledSin() {
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
130 void testWavetableInterpolation() {
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
196 void testSumOfSinesCached() {
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
216 void testSumOfSines1F() {
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
229 void testSumOfSinesSteps() {
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
246 void testSumOfSinesNonCached() {
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
259 void testWaveTableFromFile() {
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