CSL  6.0
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(3, 40, 5000); // freq line (dur val1, val2)
31  LineSegment swell(3, 0.000001, 0.5); // 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); // play vox for 3 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(true);
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.buffer(0));
266  oscBuff.mAreBuffersAllocated = true;
267  oscBuff.mNumAlloc = fi.duration();
268  Osc wav(oscBuff);
269 // Osc wav;
270  wav.setFrequency(440.0); // set freq
271  wav.setScale(0.25); // set ampl
272  logMsg("playing wavetable from file...");
273  runTest(wav); // call the test function that runs this for a few seconds
274  logMsg("done.");
275 }
276 
277 /// Test loading the SHARC samples
278 
279 #ifndef CSL_WINDOWS
280 
281 #include <SHARC.h>
282 
283 void test_SHARC() {
284  SHARCLibrary::loadDefault(); // load the SHARC library
285  SHARCLibrary * lib = SHARCLibrary::library();
286  lib->dump();
287  SHARCInstrument * inst = lib->instrument_named("bassoon");
288  SHARCSpectrum * spect = inst->_spectra[4]; // get a spectrum and make a SumOfSines
289  SumOfSines sos(* spect);
290  sos.setFrequency(110);
291  ADSR adsr(2, 0.04, 0.1, 0.6, 1.0); // make an ADSR
292  sos.setScale(adsr);
293  logMsg("playing SHARC sum of sines...");
294  adsr.trigger();
295  runTest(sos, 2);
296  logMsg("done.\n");
297 }
298 
299 /// test vector SHARC - load 3 spectra into SOS oscillators and cross-fade
300 
301 void test_SHARC2() {
302  float dur = 6.0f;
303  SHARCLibrary::loadDefault();
304  SHARCLibrary * lib = SHARCLibrary::library();
305  // 3 spectra from the SHARC library
306  SHARCSpectrum * spect1 = lib->spectrum("oboe", 60);
307  SHARCSpectrum * spect2 = lib->spectrum("tuba", 40);
308  SHARCSpectrum * spect3 = lib->spectrum("viola_vibrato", 60);
309  SumOfSines sos1(*spect1); // create 3 SOS oscs
310  SumOfSines sos2(*spect2);
311  SumOfSines sos3(*spect3);
312  sos1.setFrequency(110); // set freqs
313  sos2.setFrequency(220);
314  sos3.setFrequency(110);
315  // 3 envelopes
316  LineSegment env1(dur, 1, 0.0001); // fade out
317  sos1.setScale(env1);
318  Triangle env2(dur); // triangle
319  sos2.setScale(env2);
320  LineSegment env3(dur, 0.0001, 1); // fade in
321  sos3.setScale(env3);
322  Mixer mix(1); // mix 'em
323  mix.addInput(sos1);
324  mix.addInput(sos2);
325  mix.addInput(sos3);
326  Freeverb revb(mix); // mono reverb
327  revb.setRoomSize(0.985); // longer reverb
328  Panner pan(revb); // stereo panner
329  logMsg("playing SHARC vector synth (oboe, tuba, viola)...");
330  env1.trigger(); // trigger envelopes
331  env2.trigger();
332  env3.trigger();
333  runTest(pan, dur); // run test fcn
334  logMsg("done.\n");
335 }
336 #endif
337 
338 //////// RUN_TESTS Function ////////
339 
340 #ifndef USE_JUCE
341 
342 void runTests() {
343  testSimpleSines(); // Simple sine demo tests
344 // testBasicWaves(); // Basic waveform tests
345 // testScaledSin(); // Ways of simple scaling
346 // testWavetableInterpolation(); // test truncating and interpolating wavetable osc
347 // testAMFMSin(); // Examples of AM and FM
348 // dumpAMFMSin(); // Examples of AM and FM
349 // testSumOfSinesCached(); // Sum Of Sines tests
350 // testSumOfSinesNonCached(); // Sum Of Sines tests
351 // testWaveTableFromFile(); // load a wavetable from a sound file
352 // testSweep();
353 }
354 
355 #else
356 
357 // test list for Juce GUI
358 
360  "Sweep/swell test", testSweep, "Test a sine with swept freq and volume swell",
361  "Simple sines", testSimpleSines, "Test some simple sine oscilators",
362  "Standard waveforms", testBasicWaves, "Demonstrate the standard wave forms",
363  "Scaled sine", testScaledSin, "Play a scaled-quiet sine wave",
364  "Wavetable interpolation", testWavetableInterpolation, "Show truncated/interpolated wave tables",
365  "AM/FM sines", testAMFMSin, "Play an AM and FM sine wave",
366  "Dump AM/FM sines", dumpAMFMSin, "Dump the graph of the AM/FM sine",
367  "SumOfSines cached", testSumOfSinesCached, "Play a sum-of-sines additive oscillator",
368  "SumOfSines non-cached", testSumOfSinesNonCached, "Play an uncached inharmonic sum-of-sines",
369  "SumOfSines build", testSumOfSinesSteps, "Build up a harmonic series on a sum-of-sines",
370  "SumOfSines 1/f", testSumOfSines1F, "Play a 1/f spectrum sum-of-sines",
371  "Wavetable from file", testWaveTableFromFile, "Play a wave table from a sound file",
372 #ifndef CSL_WINDOWS
373  "SHARC SOS", test_SHARC, "Load/print the SHARC timbre database, play example",
374  "Vector SHARC", test_SHARC2, "Show vector cross-fade of SHARC spectra",
375 #endif
376  NULL, NULL, NULL
377 };
378 
379 #endif
SimpleSine – The simplest CSL sine oscillator class.
Definition: SimpleSines.h:21
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
#define kFrequency
Enum for SumOfSines description formats.
Definition: Oscillator.h:181
SineAsPhased – A sine oscillator that uses the Phased mix-in class, meaning that we inherit mFrequen...
Definition: SimpleSines.h:42
#define kFreqAmpPhase
Definition: Oscillator.h:183
void dump()
Prints instance info.
Definition: BinaryOp.cpp:54
virtual void setBuffer(unsigned bufNum, SampleBuffer sPtr)
Definition: CSL_Core.h:158
bool sleepMsec(float dur)
Definition: CGestalt.cpp:372
bool mAreBuffersAllocated
are the buffers allocated?
Definition: CSL_Core.h:120
void dumpAMFMSin()
use the dumpTest call to dump the whole graph
void dumpTest(UnitGenerator &vox)
#define kLinear
Definition: Oscillator.h:54
virtual void trigger()
reset internal time to restart envelope
Definition: Envelope.cpp:284
void testScaledSin()
Scaled sine wave – 3 methods: with a MulOp and using the Sine's scale input.
Sawtooth oscillator class (non-band-limited)
Definition: Oscillator.h:126
SHARCSpectrum ** _spectra
Definition: SHARC.h:105
void test_SHARC()
Test loading the SHARC samples.
void testSimpleSines()
Simplest sine wave tests using the tutorial example classes.
void setRoomSize(float size)
Setting the room size makes longer tails. The value has a range from 0 to 1.
Definition: Freeverb.cpp:143
void testBasicWaves()
Test/demonstrate the basic waveform oscillators.
void dump()
pretty-print the receiver
virtual void dump()
pretty-print the receiver
Definition: CSL_Core.cpp:693
void trigger()
Definition: Envelope.h:68
SHARC library class.
Definition: SHARC.h:130
StaticVariable – he static external variable (plug) class. This is a kind of variable that holds ont...
Definition: Variable.h:50
struct used for the JUCE pop-up menu of tests (see the test files)
Definition: CSL_Types.h:265
void testWaveTableFromFile()
Load an oscillator's wave table from a file – a single cycle of the vowel "oo" from the word "moon"...
SHARCInstrument * instrument_named(const char *name)
Definition: SHARC.cpp:283
SineAsScaled – A sine oscillator that also has scale and offset as dynamic controls (from Scalable) ...
Definition: SimpleSines.h:60
Square oscillator class (non-band-limited)
Definition: Oscillator.h:136
A linearly interpolated segment – this has start and end values, and a duration (in seconds)...
Definition: Envelope.h:45
void testSweep()
Apply a glissando and swell to a sine oscillator with LineSegments.
static SHARCSpectrum * spectrum(const char *instr, char *note)
Definition: SHARC.cpp:358
void test_SHARC2()
test vector SHARC - load 3 spectra into SOS oscillators and cross-fade
#define Osc
Definition: CSL_Types.h:169
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
void addPartial(Partial *pt)
given a SHARC spectrum
Definition: Oscillator.cpp:486
SHARC instrument class.
Definition: SHARC.h:100
void dump()
pretty-print the receiver
#define TABLE_SIZE
Test truncating and interpolating wavetable osc with a small wavetable (these should sound different ...
void runTest(UnitGenerator &vox, double dur)
void testWavetableInterpolation()
void testAMFMSin()
AM and FM using the dynamic scale and frequency inputs.
#define CSL_TWOPI
Definition: CSL_Types.h:336
MulOp – A BinaryOp that multiplies two UnitGenerators or fixed constants together, sample-by-sample.
Definition: BinaryOp.h:104
void testSumOfSinesNonCached()
Now test an uncached inharmonic series constructor format 3 = list of (freq/amp/phase) for (not-neces...
Sine – oscillator class (this computes the sine fcn on the fly)
Definition: Oscillator.h:108
Triangle envelope class – equal attack/release times.
Definition: Envelope.h:227
void setFrequency(UnitGenerator &frequency)
Setter accessors.
Definition: CSL_Core.cpp:981
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
testStruct oscTestList[]
The CSL mono-to-stereo L/R panner class.
Definition: Mixer.h:66
void testSumOfSinesCached()
Play a sum of sines waveform – cached harmonic overtone series.
void testSumOfSines1F()
Play a sum of sines waveform – 1/f + noise.
void addInput(UnitGenerator &inp)
Definition: Mixer.cpp:43
void runTests()
void setScale(UnitGenerator &scale)
set the receiver's scale member to a UGen or a float
Definition: CSL_Core.cpp:1039
void testSumOfSinesSteps()
SHARC spectrum class.
Definition: SHARC.h:76
void dump()
print the receiver for debugging
Definition: Oscillator.cpp:563