# HG changeset patch # User Giulio Moro # Date 1457452182 0 # Node ID 97faaf985164bbb17c1ce4c281b266ff04004a9d # Parent ec9425f728bcef6a9371af5d652f4cf33db7fded Added callback for Midi channel messages diff -r ec9425f728bc -r 97faaf985164 core/Midi.cpp --- a/core/Midi.cpp Mon Feb 22 11:28:21 2016 +0000 +++ b/core/Midi.cpp Tue Mar 08 15:49:42 2016 +0000 @@ -58,6 +58,11 @@ messages[writePointer].setDataByte(elapsedDataBytes, input[n]); elapsedDataBytes++; if(elapsedDataBytes == messages[writePointer].getNumDataBytes()){ + // done with the current message + // call the callback if available + if(isCallbackEnabled() == true){ + messageReadyCallback(getNextChannelMessage()); + } waitingForStatus = true; writePointer++; if(writePointer == messages.size()){ @@ -66,6 +71,7 @@ } } } + return consumedBytes; }; @@ -104,14 +110,12 @@ } void Midi::midiInputLoop(){ - printf("Midi input loop %d\n", objAddrs[kMidiInput].size()); for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){ objAddrs[kMidiInput][n] -> readInputLoop(); } } void Midi::midiOutputLoop(){ - printf("Midi output loop %d\n", objAddrs[kMidiOutput].size()); for(unsigned int n = 0; n < objAddrs[kMidiOutput].size(); n++){ objAddrs[kMidiOutput][n] -> writeOutputLoop(); } @@ -132,6 +136,7 @@ if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around inputBytesWritePointer = 0; } + if(parserEnabled == true && ret > 0){ // if the parser is enabled and there is new data, send the data to it int input; while((input=_getInput()) >= 0){ diff -r ec9425f728bc -r 97faaf985164 include/Midi.h --- a/include/Midi.h Mon Feb 22 11:28:21 2016 +0000 +++ b/include/Midi.h Tue Mar 08 15:49:42 2016 +0000 @@ -115,6 +115,8 @@ unsigned int readPointer; unsigned int elapsedDataBytes; bool waitingForStatus; + void (*messageReadyCallback)(MidiChannelMessage); + bool callbackEnabled; public: MidiParser(){ waitingForStatus = true; @@ -122,6 +124,8 @@ messages.resize(100); // 100 is the number of messages that can be buffered writePointer = 0; readPointer = 0; + callbackEnabled = false; + messageReadyCallback = NULL; } /** @@ -133,14 +137,25 @@ * @return the number of bytes parsed */ int parse(midi_byte_t* input, unsigned int length); - int callme(){ - return readPointer; + + void setCallback(void (*newCallback)(MidiChannelMessage)){ + messageReadyCallback = newCallback; + if(newCallback != NULL){ + callbackEnabled = true; + } else { + callbackEnabled = false; + } }; + + bool isCallbackEnabled(){ + return callbackEnabled; + }; + int numAvailableMessages(){ int num = (writePointer - readPointer + messages.size() ) % messages.size(); if(num > 0){ int a = a +1; - a = callme(); + a = readPointer; } return num; } @@ -202,6 +217,12 @@ */ MidiParser* getParser(); + void setParserCallback(void (*callback)(MidiChannelMessage)){ + // if callback is not NULL, also enable the parser + enableParser(callback != NULL); //this needs to be first, as it deletes the parser(if exists) + getParser()->setCallback(callback); + } + /** * Open the specified input Midi port and start reading from it. * @param port Midi port to open diff -r ec9425f728bc -r 97faaf985164 projects/basic_midi/render.cpp --- a/projects/basic_midi/render.cpp Mon Feb 22 11:28:21 2016 +0000 +++ b/projects/basic_midi/render.cpp Tue Mar 08 15:49:42 2016 +0000 @@ -12,6 +12,22 @@ #include #include +float gFreq; +float gPhaseIncrement = 0; +bool gIsNoteOn = 0; +int gVelocity = 0; +float gSamplingPeriod = 0; + +void midiMessageCallback(MidiChannelMessage message){ + message.prettyPrint(); + if(message.getType() == kmmNoteOn){ + gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440; + gVelocity = message.getDataByte(1); + gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod; + gIsNoteOn = gVelocity > 0; + rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity); + } +} // setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. @@ -25,11 +41,13 @@ { midi.readFrom(0); midi.writeTo(0); -// midi.enableParser(true); + midi.enableParser(true); + midi.setParserCallback(midiMessageCallback); if(context->analogFrames == 0) { rt_printf("Error: this example needs the matrix enabled\n"); return false; } + gSamplingPeriod = 1/context->audioSampleRate; return true; } @@ -38,21 +56,18 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -static midi_byte_t noteOnStatus = 0x90; //on channel 1 enum {kVelocity, kNoteOn, kNoteNumber}; void render(BeagleRTContext *context, void *userData) { - static float f0; - static float phaseIncrement = 0; - static bool noteOn = 0; - static int velocity = 0; +// one way of getting the midi data is to parse them yourself +// (you should set midi.enableParser(false) above): +/* + static midi_byte_t noteOnStatus = 0x90; //on channel 1 static int noteNumber = 0; static int waitingFor = kNoteOn; static int playingNote = -1; -/* int message; - // one way of getting the midi data is to parse them yourself (you should set midi.enableParser(false) above): while ((message = midi.getInput()) >= 0){ rt_printf("%d\n", message); switch(waitingFor){ @@ -92,6 +107,7 @@ } } */ + /* int num; //alternatively, you can use the built-in parser (only processes channel messages at the moment). while((num = midi.getParser()->numAvailableMessages()) > 0){ @@ -103,28 +119,31 @@ velocity = message.getDataByte(1); phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate; noteOn = velocity > 0; - rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, velocity); + rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity); } } - + */ + // the following block toggles the LED on an Owl pedal + // and asks the pedal to return the status of the LED + // using MIDI control changes for(unsigned int n = 0; n < context->analogFrames; n++){ static int count = 0; static bool state = 0; analogWriteFrameOnce(context, n, 1, state); if(count % 40000 == 0){ state = !state; - midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status + midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status midi.writeOutput(bytes, 6); } count++; } for(unsigned int n = 0; n < context->audioFrames; n++){ - if(noteOn == 1){ + if(gIsNoteOn == 1){ static float phase = 0; - phase += phaseIncrement; + phase += gPhaseIncrement; if(phase > 2 * M_PI) phase -= 2 * M_PI; - float value = sinf(phase) * velocity/128.0f; + float value = sinf(phase) * gVelocity/128.0f; audioWriteFrame(context, n, 0, value); audioWriteFrame(context, n, 1, value); } else {