CSL  5.2
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() {
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;
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;
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++) {
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++) {
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