From 90f8157b9d4e37714f5eab217796847318e98d90 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 26 Aug 2020 10:11:14 +0200 Subject: [PATCH] Added README.md from upstream. Added MIDI channel support. --- OSC2Midi.cpp | 57 ++++++++++++++++++++++++--------------------- OSC2Midi.h | 3 ++- OSC2MidiGateway.ino | 14 ++++++----- README.md | 52 +++++++++++++++++++++++++++++++++++++++++ debug.h | 22 ++++++++--------- 5 files changed, 104 insertions(+), 44 deletions(-) diff --git a/OSC2Midi.cpp b/OSC2Midi.cpp index 9263630..645b0ac 100644 --- a/OSC2Midi.cpp +++ b/OSC2Midi.cpp @@ -3,40 +3,45 @@ #include /* - * TODO: this will return rather unpredictable numbers when - * given strings with numbers > 255. - */ + TODO: this will return rather unpredictable numbers when + given strings with numbers > 255. +*/ uint8_t getCC(const char *str, int index) { - const char *offset = str; + const char *offset = str; - // skip the first / - if (strncmp(str, "/", strlen("/")) == 0) - { - offset++; - } - - if (index == -1) - { - return atoi(offset); - } + // skip the first / + if (strncmp(str, "/", strlen("/")) == 0) + { + offset++; + } - while (index > 0) - { - const char *new_offset = strstr(offset, "/"); - if (new_offset) { - offset = new_offset + 1; - } else { - return 0; - } + if (index == -1) + { + return atoi(offset); + } - index--; + while (index > 0) + { + const char *new_offset = strstr(offset, "/"); + if (new_offset) { + offset = new_offset + 1; + } else { + return 0; } - return atoi(offset); + index--; + } + + return atoi(offset); } uint8_t getCC(const char *str) { - return getCC(str, -1); -} \ No newline at end of file + return getCC(str, 1); +} + +uint8_t getMIDIChannel(const char *str) +{ + return getCC(str, -1); +} diff --git a/OSC2Midi.h b/OSC2Midi.h index a91b2c7..247b545 100644 --- a/OSC2Midi.h +++ b/OSC2Midi.h @@ -5,5 +5,6 @@ uint8_t getCC(const char *str, int index); uint8_t getCC(const char *str); +uint8_t getMIDIChannel(const char *str); -#endif \ No newline at end of file +#endif diff --git a/OSC2MidiGateway.ino b/OSC2MidiGateway.ino index 9f3712a..c7d2b54 100644 --- a/OSC2MidiGateway.ino +++ b/OSC2MidiGateway.ino @@ -48,8 +48,10 @@ void setup() { void OSCToMidiCC(OSCMessage &msg, int offset) { char address[100] = { 0 }; uint8_t cc, value; + uint8_t midichannel; msg.getAddress(address, offset, sizeof(address)); + midichannel = getMIDIChannel(address); if (msg.size() == 1 && msg.isFloat(0)) { // Single or multi control with sending one value @@ -57,20 +59,20 @@ void OSCToMidiCC(OSCMessage &msg, int offset) { value = round(msg.getFloat(0)); value = value > 127 ? 127 : value; DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); - MIDI.sendControlChange(cc, value, 1); + MIDI.sendControlChange(cc, value, midichannel); } else if (msg.size() == 2 && msg.isFloat(0) && msg.isFloat(1)) { // XY pad, two values - cc = getCC(address, 0); + cc = getCC(address, 1); value = round(msg.getFloat(0)); value = value > 127 ? 127 : value; DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); - MIDI.sendControlChange(cc, value, 1); + MIDI.sendControlChange(cc, value, midichannel); - cc = getCC(address, 1); + cc = getCC(address, 2); value = round(msg.getFloat(1)); value = value > 127 ? 127 : value; DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); - MIDI.sendControlChange(cc, value, 1); + MIDI.sendControlChange(cc, value, midichannel); } else { DEBUG_MSG("Cannot handle: %s\n", address); } @@ -78,7 +80,7 @@ void OSCToMidiCC(OSCMessage &msg, int offset) { void MidiCCToOSC(uint8_t channel, uint8_t number, uint8_t value) { char buffer[1024]; - snprintf(buffer, sizeof(buffer), "/midi/cc/%u", number); + snprintf(buffer, sizeof(buffer), "/midi/cc/%u/%u", channel, number); OSCMessage msg = OSCMessage(buffer); msg.add(value * 1.0); diff --git a/README.md b/README.md index fdd640c..a2376ca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,54 @@ # OSC2MidiGateway +(Fork of https://github.com/tadas-s/OSC2Midi with extensions) + +ESP8266 based OSC <-> Midi wireless bridge. + +It is mostly meant to be used with [TouchOSC][1] but it will work with +any [OSC message source][2]. + +## Library dependencies + +Project uses: + * https://github.com/FortySevenEffects/arduino_midi_library/ + * https://github.com/CNMAT/OSC + +## Hardware + +Based on a generic ESP8266-01 board using both GPIO pins as MIDI-I/O. + +## OSC message formats + +All messages are expected to have payload of 1 or 2 floats with range +from 0 to 127. + +### /midi/cc/channel/{cc} + 1 float + +Will send control change message for `{cc}` number. + +### /midi/cc/channel/{ccA}/{ccB}/.../{index} + 1 float + +Will send control change message for CC specified by `{index}`. For +example: + + * /midi/cc/1/10/12/15/1 -> CC to 10 on channel 1 + * /midi/cc/1/10/12/15/3 -> CC to 15 on channel 1 + +This is meant to be used with TouchOSC groups of faders. For example, +my [MicroKORG][6] preset includes a fader group of 4 to control +amp ADSR: `/midi/cc/1/73/75/70/72` + +### /midi/cc/channel/{ccA}/{ccB} + 2 floats + +This sends two control change messages to `{ccA}` and `{ccB}`. This is +meant to be used with TouchOSC XY pads. + +[1]: http://hexler.net/software/touchosc +[2]: https://en.wikipedia.org/wiki/Open_Sound_Control +[3]: https://www.arduino.cc/en/Tutorial/Midi +[4]: http://libremusicproduction.com/tutorials/arduino-and-midi-in +[5]: https://www.arduino.cc/en/Reference/SoftwareSerial +[6]: http://www.korg.com/us/products/synthesizers/microkorg/ +[7]: https://www.microchip.com/wwwproducts/en/en027785 +[8]: https://github.com/tadas-s/esp8266-autoreset + diff --git a/debug.h b/debug.h index c0c290e..8d4ec80 100644 --- a/debug.h +++ b/debug.h @@ -7,20 +7,20 @@ #define DEBUG_MSG(...) Serial1.printf( __VA_ARGS__ ) #define DEBUG_OSC_MESSAGE(msg) \ - do { \ - char address[100]; \ - msg.getAddress(address, 0, sizeof(address)); \ - Serial1.printf("osc message: [%d] %s ", msg.size(), address); \ - for (int i = 0; i < msg.size(); i++) { \ - if (msg.isFloat(i)) { Serial1.printf("f:%f\t", msg.getFloat(i)); } \ - if (msg.isInt(i)) { Serial1.printf("i:%d\t", msg.getInt(i)); } \ - } \ - Serial1.printf("\n"); \ - } while(0); + do { \ + char address[100]; \ + msg.getAddress(address, 0, sizeof(address)); \ + Serial1.printf("osc message: [%d] %s ", msg.size(), address); \ + for (int i = 0; i < msg.size(); i++) { \ + if (msg.isFloat(i)) { Serial1.printf("f:%f\t", msg.getFloat(i)); } \ + if (msg.isInt(i)) { Serial1.printf("i:%d\t", msg.getInt(i)); } \ + } \ + Serial1.printf("\n"); \ + } while(0); #else #define DEBUG_MSG(...) #define DEBUG_OSC_MESSAGE(...) #endif -#endif \ No newline at end of file +#endif