CSL  6.0
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 juce::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", juce::MidiInput::getDefaultDeviceIndex());
40  logMsg("Default MIDI out = %d", juce::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
static void dumpDevices()
printing device info for all devices.
Definition: MIDIIOJ.cpp:58
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
IO * theIO
The PThreads CSL Thread class.
virtual void clear()
stop MIDI stream
Definition: MIDIIOJ.cpp:102
unsigned getVelocity()
Definition: MIDIIOJ.cpp:32
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
CSL Observer/Dependent/Monitor class – instances receive update() messages from "models" and handle ...
Definition: CGestalt.h:296
AdditiveInstrument.
MIDIIn class is-a MidiInputCallback too, and an "input-ready" flag.
Definition: MIDIIOJ.h:130
void mainOSCLoop(int port)
virtual void open()
Definition: CSL_Core.h:759
CSL_MIDIMessage mMsg
Definition: MIDIIOP.h:182
struct used for the JUCE pop-up menu of tests (see the test files)
Definition: CSL_Types.h:265
virtual void stop()
stop MIDI stream
Definition: MIDIIOJ.cpp:241
void setupOSCInstrLibrary(std::vector< Instrument * > library)
const char * what()
void dumpMessage()
print current msg
Definition: MIDIIOJ.cpp:281
FMInstrument.
virtual void start()
Definition: CSL_Core.h:761
float fRandM(float minV, float maxV)
min - max (min/max)
Definition: CGestalt.cpp:426
juce::AudioDeviceManager * gAudioDeviceManager
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
#define DEFAULT_MIDI_IN
Definition: CSL_Types.h:158
bool sleepSec(float dur)
Definition: CGestalt.cpp:379
std::vector< Instrument * > InstrumentVector
Players hold onto Instrument vectors/maps.
Definition: CSL_Types.h:251
bool poll()
poll returns a bool (really quickly)
Definition: MIDIIOJ.cpp:263
MIDI stream/file player.
Definition: MIDIIOJ.h:187
#define CSL_WORD_LEN
default short string length
Definition: CSL_Types.h:119
virtual int createThread(VoidFcnPtr *func, void *args)=0
void attachObserver(Observer *)
(possibly notify obersvers on my death)
Definition: CGestalt.cpp:502
static CThread * MakeThread()
factory method
unsigned getNote()
Definition: MIDIIOJ.cpp:31
virtual void close()
open/close start/stop methods
Definition: CSL_Core.h:760
void setRoot(UnitGenerator &root)
set/clear my graph root generator
Definition: CSL_Core.cpp:1405
Mixer – The n-input m-channel mixer class.
Definition: Mixer.h:21
CMIDIMessage class (mapped to juce::MidiMessage)
Definition: MIDIIOJ.h:46
CMIDIMessageType message
event type
Definition: MIDIIOJ.h:73
virtual void open(int deviceID)
open a device
Definition: MIDIIOJ.cpp:218
void clearRoot()
Definition: CSL_Core.cpp:1410
virtual void close()
closing MIDI stream
Definition: MIDIIOJ.cpp:95
static unsigned outPort()
the default RemoteIO output port
Definition: CGestalt.cpp:62
float fRand1(void)
-1 - 1 (one)
Definition: CGestalt.cpp:420
virtual void start()
start MIDI stream
Definition: MIDIIOJ.cpp:233
std::map< int, InstrumentVector > InstrumentLibrary
Definition: CSL_Types.h:252
int done
Definition: OSC_support.cpp:34
virtual void stop()
Definition: CSL_Core.h:762
Base class of CSL exceptions (written upper-case). Has a string message.
static std::string dataFolder()
the default directory for test data
Definition: CGestalt.cpp:71