CSL 5.2

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

- File List
- File Members

Test_Control.cpp
Go to the documentation of this file.
1 //
2 // Test_Control.cpp -- MIDI and OSC control IO tests
3 //
4 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
5 //
6
7 #ifdef USE_JUCE
8 #include "Test_Support.h"
9 #else
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 #endif
13
14 #ifdef USE_JMIDI // new way with JUCE midi
15
16 #include "MIDIIOJ.h"
17
18 #include <iostream>
19
20 using namespace csl;
21
22 extern AudioDeviceManager * gAudioDeviceManager; // global JUCE audio device mgr
23
24 // dump io names
25
26 void IO_test() {
27 MIDIIO::dumpDevices();
28 }
29
30 // echo 10 events of input
31
32 //#define DEFAULT_MIDI_IN MidiInput::getDefaultDeviceIndex()
33 //#define DEFAULT_MIDI_IN MidiOutput::getDefaultDeviceIndex()
34
35 // Run the IO_test, then edit these
36
37 void input_test() {
38 logMsg("MIDI test");
39 logMsg("Default MIDI in = %d", MidiInput::getDefaultDeviceIndex());
40 logMsg("Default MIDI out = %d", MidiOutput::getDefaultDeviceIndex());
41 MIDIIn in;
42 in.open(DEFAULT_MIDI_IN);
43 in.start();
44
45 try {
46 int cnt = 0;
47 while (cnt++ < 10) { // loop to read 10 events
48 while ( ! in.poll()) // poll and wait
49 sleepSec(0.1);
50 in.dumpMessage(); // dump received msg
51 in.clear(); // clear input
52 }
53 } catch (CException ex) {
54 logMsg(kLogError, "CSL MIDI Error %s...", ex.what());
55 }
56 in.stop();
57 in.close();
58 }
59
60 // play simple notes
61
62 void play_test() {
63 MIDIIn in;
64 in.open(DEFAULT_MIDI_IN);
65 in.start();
66
67 SumOfSines osc(kFrequency, 6, 0.4, 0.3, 0.2, 0.08, 0.05, 0.02); // create an osc + env patch
68 ADSR env(1.0, 0.05, 0.1, 0.7, 0.6);
69 osc.setScale(env);
70 osc.setFrequency(1017.0f);
71 Freeverb rev(osc); // stereo reverb
72 rev.setRoomSize(0.92); // longer reverb
73
74 theIO->setRoot(rev);
75 logMsg("testing MIDIIn playback");
76
77 while(1) { // here's the poll/play loop
78 if(in.poll()) {
79 if(in.mMsg.isNoteOn()) {
80 logMsg("MIDI note %d vel. %d", in.mMsg.getNote(), in.mMsg.getVelocity());
81 osc.setFrequency(in.mMsg.getFrequency());
82 env.scaleValues(in.mMsg.getVelocityFloat() / 2.0f );
83 env.trigger();
84 }
85 if(in.mMsg.isNoteOff()) {
86 env.release();
87 }
88 in.clear(); // clear input
89 } else {
90 sleepSec(0.1); // sleep 100 msec
91 }
92 }
93 in.stop();
94 in.close();
95 }
96
97 // generate MIDI output
98
99 void output_test() {
100
101 }
102
103 //////////////////////////////////////////////////////////////////////////////
104
105 // make a MIDI listener class -- implement update() and filter on midi command
106
107 class MIDIListener : public Observer {
108 public:
109 // update message prints to the log
110 void update(void * arg) {
111 CMIDIMessage * msg = (CMIDIMessage *) arg;
112 logMsg("MIDI msg %d k %d v %d", msg->message, msg->getNote(), msg->getVelocity());
113 mIn->clear();
114 }
115 // constructor
116 MIDIListener(MIDIIn * in) : mIn(in) { };
117 // data member for the input
118 MIDIIn * mIn;
119
120 };
121
122 /// Create a MIDI in and attach a filtering listener to it
123
124 void testListener() {
125 MIDIIn in;
126 in.open(DEFAULT_MIDI_IN);
127 MIDIListener lst(&in); // create a listener
128 // lst.mPeriod = 0.25;
129 lst.mKey = kNoteOn; // filter noteOn events
130 in.attachObserver(&lst); // attach observer to input
131 logMsg("Start MIDI listener");
132 in.start();
133
134 sleepSec(10);
135
136 logMsg("done.");
137 in.stop();
138 in.close();
139 }
140
141 // MIDI file player uses instrument library
142
143 #include <AdditiveInstrument.h>
144 #include <BasicFMInstrument.h>
145
146 void testMIDIFile() {
147 InstrumentLibrary lib; // create the instrument library map
148 Mixer mix(2); // Create the main stereo output mixer
149 // Now add 16 instruments
150 logMsg("Setting up instrument library");
151 for (unsigned i = 0; i < 16; i++) {
152 FMInstrument * in = new FMInstrument;
153 lib[i].push_back(in); // map of inst vectors
154 mix.addInput(in); // add to mix
155 }
156 // for (unsigned i = 0; i < lib.size(); i++) {
157 // logMsg("IL %d: %d", i, lib[i].size());
158 // }
159 Stereoverb rev(mix); // stereo reverb
160 rev.setRoomSize(0.8); // medium-length reverb
161
162 logMsg("Load MIDI score");
163 MIDIPlayer pla(CGestalt::dataFolder(), "pravol12c.mid", &lib);
164
165 logMsg("Start MIDI player");
166 theIO->setRoot(rev); // plug the reverb in as the IO client
167 theIO->open(); // open the IO
168 theIO->start(); // start the io
169
170 pla.start(-1); // play all tracks real-time
171
172 sleepSec(2); // let the reverb die out
173
174 theIO->clearRoot(); // shut down
175 pla.stop();
176 logMsg("done.");
177 theIO->stop();
178 theIO->close();
179 mix.deleteInputs();
180 }
181
182 //////////////////////////////////////////////////////////////////////////////
183
184 #ifdef USE_LOSC // liblo for OSC
185
186 #include "lo/lo.h" // liblo header has to be in your path (/usr/local/include)
187 #include "OSC_support.h"
188
189 // Server only (run client in a separate shell)
190
191 void testOSCServer() {
192 InstrumentVector lib;
193 logMsg("Setting up instrument library");
194 Mixer mix(2); // Create the main stereo output mixer
195 // Now add 16 instruments
196 for (unsigned i = 0; i < 16; i++) {
197 AdditiveInstrument * in = new AdditiveInstrument;
198 lib.push_back(in);
199 mix.addInput(*in);
200 }
201 Stereoverb rev(mix); // stereo reverb
202 rev.setRoomSize(0.8); // medium-length reverb
203 theIO->setRoot(rev); // plug the mixer in as the IO client
204 theIO->open(); // open the IO
205 theIO->start(); // start the IO
206
207 char pNam[CSL_WORD_LEN]; // string for port number
208 sprintf(pNam, "%d", CGestalt::outPort());
209
210 initOSC(pNam); // Set up OSC address space root
211
212 setupOSCInstrLibrary(lib); // add the instrument library OSC
213
214 mainOSCLoop(NULL); // Run the OSC loop function (it exits on the quit command)
215 logMsg("OSC server waiting for input\n");
216
217 sleepSec(2); // let the reverb dieout
218 theIO->clearRoot(); // shut down
219 theIO->stop();
220 theIO->close();
221 mix.deleteInputs();
222 }
223
224 // set up an OSC client/server with an instrument library
225
226 void testOSCClientServer() {
227 InstrumentVector lib;
228 logMsg("Setting up instrument library");
229 Mixer mix(2); // Create the main stereo output mixer
230 // Now add 16 instruments
231 for (unsigned i = 0; i < 16; i++) {
232 AdditiveInstrument * in = new AdditiveInstrument;
233 lib.push_back(in);
234 mix.addInput(*in);
235 }
236 Stereoverb rev(mix); // stereo reverb
237 rev.setRoomSize(0.8); // medium-length reverb
238 theIO->setRoot(rev); // plug the mixer in as the IO client
239 theIO->open(); // open the IO
240 theIO->start(); // start the IO
241
242 char pNam[CSL_WORD_LEN]; // string for port number
243 sprintf(pNam, "%d", CGestalt::outPort());
244
245 initOSC(pNam); // Set up OSC address space root
246 setupOSCInstrLibrary(lib); // add the instrument library OSC
247
248 // make a thread for the OSC server
249 CThread * osc = CThread::MakeThread();
250 // Run the OSC loop function (it exits on the quit command)
251 osc->createThread(mainOSCLoop, NULL);
252 sleepSec(0.5); /// wait for it to start
253
254 // now we're the OSC client
255 // set up a port to write to the server thread
256 lo_address ad = lo_address_new(NULL, pNam);
257 logMsg("Sending OSC note cmds");
258 // if (lo_send(ad, "/i1/p", "") == -1) { // send a test note command
259 // logMsg(kLogError, "OSC error1 %d: %s\n", lo_address_errno(ad), lo_address_errstr(ad));
260 // goto done;
261 // }
262 // sleepSec(0.5);
263 for (unsigned i = 0; i < 64; i++) { // note loop
264 sprintf(pNam, "/i%d/pn", (i % 16)+1); // OSC cmd: /iX/pn, "ffff", dur ampl freq pos
265 float dur = fRandM(0.15f, 1.5f);
266 float ampl = fRandM(0.2, 0.8);
267 float freq = fRandM(60, 500);
268 float pos = fRand1();
269 if (lo_send(ad, pNam, "ffff", dur, ampl, freq, pos) == -1) {
270 logMsg(kLogError, "OSC error2 %d: %s\n", lo_address_errno(ad), lo_address_errstr(ad));
271 }
272 sleepSec(fRandM(0.06, 0.3)); // sleep a bit
273 }
274 done:
275 sleepSec(2); // let the reverb dieout
276 logMsg("Sending OSC quit");
277 if (lo_send(ad, "/q", NULL) == -1) {
278 logMsg(kLogError, "OSC error3 %d: %s\n", lo_address_errno(ad), lo_address_errstr(ad));
279 }
280 theIO->clearRoot(); // shut down
281 theIO->stop();
282 theIO->close();
283 mix.deleteInputs();
284 }
285
286 #endif // USE_LOSC
287
288 // test list for Juce GUI
289
290 testStruct ctrlTestList[] = {
291 "Dump ports", IO_test, "Dump list of MIDI ports to stdout",
292 "Dump input", input_test, "Dump MIDI input from default device",
293 "MIDI notes", play_test, "Play MIDI notes (reads MIDI kbd)",
294 "MIDI output", output_test, "Test sending MIDI output",
295 "MIDI listener", testListener, "Start the MIDI listener object",
296 "MIDI file player", testMIDIFile, "Play a MIDI file on an instrument library",
297 #ifdef USE_LOSC // liblo for OSC
298 "OSC client/server", testOSCClientServer, "OSC client/server on a library",
299 "OSC server", testOSCServer, "Start OSC server on a library",
300 #endif
301 NULL, NULL, NULL
302 };
303
304 #endif