diff --git a/OSC2Midi.cpp b/OSC2Midi.cpp index 645b0ac..167c74b 100644 --- a/OSC2Midi.cpp +++ b/OSC2Midi.cpp @@ -6,7 +6,7 @@ TODO: this will return rather unpredictable numbers when given strings with numbers > 255. */ -uint8_t getCC(const char *str, int index) +uint8_t getVar(const char *str, int index) { const char *offset = str; @@ -38,10 +38,10 @@ uint8_t getCC(const char *str, int index) uint8_t getCC(const char *str) { - return getCC(str, 1); + return getVar(str, 1); } uint8_t getMIDIChannel(const char *str) { - return getCC(str, -1); + return getVar(str, 0); } diff --git a/OSC2Midi.h b/OSC2Midi.h index 247b545..c6552cb 100644 --- a/OSC2Midi.h +++ b/OSC2Midi.h @@ -3,7 +3,7 @@ #include -uint8_t getCC(const char *str, int index); +uint8_t getVar(const char *str, int index); uint8_t getCC(const char *str); uint8_t getMIDIChannel(const char *str); diff --git a/OSC2MidiGateway.ino b/OSC2MidiGateway.ino index c7d2b54..7fcb6ec 100644 --- a/OSC2MidiGateway.ino +++ b/OSC2MidiGateway.ino @@ -1,6 +1,9 @@ +#define DEBUG 1 + #include "debug.h" #include -#include +//#include +#include #include #include #include @@ -21,96 +24,124 @@ IPAddress clientIP; IPAddress gateway(192,168,4,1); IPAddress subnet(255,255,255,0);*/ -MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI); +/* + UART RX IO TX IO CTS RTS + UART0 GPIO3 GPIO1 N/A N/A + UART1 GPIO9 GPIO10 GPIO6 GPIO11 + UART2 GPIO16 GPIO17 GPIO8 GPIO7 +*/ + +MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI); // Pins on ESP32: RX: 6, TX: 7 +//MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI2); // Pins on ESP32: RX: ?, TX: ? -void setup() { - // Midi via UART0 - Serial.begin(31250); - Serial.swap(); +void setup() +{ + Serial2.begin(31250); -#ifdef DEBUG - // Debug via UART1 TX only - Serial1.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY, 2); - Serial1.setDebugOutput(true); -#endif + Serial.begin(115200); + Serial.setDebugOutput(true); DEBUG_MSG("\nHello OSC2Midi!\n"); - WiFi.softAP("OSC2Midi", "Midi2OSCGateway"); + WiFi.softAP("OSC2Midi", "1357924680"); DEBUG_MSG("\nAP IP address: %s\n", WiFi.softAPIP().toString().c_str()); udp.begin(8000); + MIDI.begin(MIDI_CHANNEL_OMNI); MIDI.setHandleControlChange(MidiCCToOSC); + MIDI.turnThruOff(); } -void OSCToMidiCC(OSCMessage &msg, int offset) { +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); + //midichannel--; - if (msg.size() == 1 && msg.isFloat(0)) { + if (msg.size() == 1 && msg.isFloat(0)) + { // Single or multi control with sending one value cc = getCC(address); value = round(msg.getFloat(0)); value = value > 127 ? 127 : value; - DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); + DEBUG_MSG("MSG: %s\tChannel: %u\t\tCC: %u\tValue: %u\n", address, midichannel, cc, value); MIDI.sendControlChange(cc, value, midichannel); - } else if (msg.size() == 2 && msg.isFloat(0) && msg.isFloat(1)) { + } + else if (msg.size() == 2 && msg.isFloat(0) && msg.isFloat(1)) + { // XY pad, two values - cc = getCC(address, 1); + cc = getVar(address, 1); value = round(msg.getFloat(0)); value = value > 127 ? 127 : value; - DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); + DEBUG_MSG("MSG: %s\tChannel: %u\t\tCC: %u\tValue: %u\n", address, midichannel, cc, value); MIDI.sendControlChange(cc, value, midichannel); - - cc = getCC(address, 2); + cc = getVar(address, 2); value = round(msg.getFloat(1)); value = value > 127 ? 127 : value; - DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); + DEBUG_MSG("MSG: %s\tChannel: %u\t\tCC: %u\tValue: %u\n", address, midichannel, cc, value); MIDI.sendControlChange(cc, value, midichannel); - } else { + } + else + { DEBUG_MSG("Cannot handle: %s\n", address); } } -void MidiCCToOSC(uint8_t channel, uint8_t number, uint8_t value) { +void MidiCCToOSC(uint8_t channel, uint8_t number, uint8_t val) +{ char buffer[1024]; + snprintf(buffer, sizeof(buffer), "/midi/cc/%u/%u", channel, number); - OSCMessage msg = OSCMessage(buffer); - msg.add(value * 1.0); + DEBUG_MSG("MidiCCToOsc: %s %f\n", buffer, val * 1.0); - DEBUG_MSG("MidiCCToOsc: %s %f", buffer, value * 1.0); + if (clientIP) + { + OSCMessage msg = OSCMessage(buffer); + msg.add(val); - udp.beginPacket(clientIP, 8001); - msg.send(udp); - udp.endPacket(); + udp.beginPacket(clientIP, 9000); + msg.send(udp); + udp.endPacket(); + } } -void loop() { +void loop() +{ OSCMessage msg; uint8_t buffer[1024]; + uint16_t outPort; // Check if there are any OSC packets to handle size_t size = udp.parsePacket(); - if (size > 0 && size <= 1024) { + + if (size > 0 && size <= 1024) + { udp.read(buffer, size); msg.fill(buffer, size); - if (!msg.hasError()) { + if (!msg.hasError()) + { DEBUG_OSC_MESSAGE(msg); msg.route("/midi/cc", OSCToMidiCC); - } else { + //msg.route("/midi/sysex", OSCToMidiSYSEX); + //msg.route("/midi/note", OSCToMidiNote); + } + else + { DEBUG_MSG("Error parsing OSC message: %d\n", msg.getError()); } // Keep track of the client IP address for "talking back" clientIP = udp.remoteIP(); + + udp.flush(); } // Check if there are any CC messages from synth itself diff --git a/debug.h b/debug.h index 8d4ec80..7d620b5 100644 --- a/debug.h +++ b/debug.h @@ -3,21 +3,21 @@ #ifdef DEBUG -#define DEBUG_ESP_PORT Serial1 -#define DEBUG_MSG(...) Serial1.printf( __VA_ARGS__ ) +#define DEBUG_ESP_PORT Serial +#define DEBUG_MSG(...) Serial.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); \ + Serial.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)); } \ + if (msg.isFloat(i)) { Serial.printf("f:%f\t", msg.getFloat(i)); } \ + if (msg.isInt(i)) { Serial.printf("i:%d\t", msg.getInt(i)); } \ } \ - Serial1.printf("\n"); \ + Serial.printf("\n"); \ } while(0); - + #else #define DEBUG_MSG(...) #define DEBUG_OSC_MESSAGE(...) diff --git a/doc/midi_message_types.txt b/doc/midi_message_types.txt new file mode 100644 index 0000000..3ec42cf --- /dev/null +++ b/doc/midi_message_types.txt @@ -0,0 +1,90 @@ +MIDI message types + +(hex) +8 = note_off +9 = note_on +A = aftertouch (ie, key pressure) +B = controller_change +C = program_change +D = channel_pressure +E = pitch_wheel + + +** additions ** +sysex +start +stop +continue +mode +file + +control_change messages + +(dec) +0 bank_select (coarse) +1 modulation_wheel (coarse) +2 breath_controller (coarse) +4 foot_pedal (coarse) +5 portamento Time (coarse) +6 data_entry (coarse) +7 volume (coarse) +8 balance (coarse) +10 pan position (coarse) +11 expression (coarse) +12 effect_control_1 (coarse) +13 effect_control_2 (coarse) +16 general_purpose_slider_1 +17 general_purpose_slider_2 +18 general_purpose_slider_3 +19 general_purpose_slider_4 +32 bank_select (fine) +33 modulation_wheel (fine) +34 breath_controller (fine) +36 foot_pedal (fine) +37 Portamento Time (fine) +38 Data Entry (fine) +39 Volume (fine) +40 Balance (fine) +42 Pan position (fine) +43 Expression (fine) +44 Effect Control 1 (fine) +45 Effect Control 2 (fine) +64 Hold Pedal (on/off) +65 Portamento (on/off) +66 Sustenuto Pedal (on/off) +67 Soft Pedal (on/off) +68 Legato Pedal (on/off) +69 Hold 2 Pedal (on/off) +70 Sound Variation +71 Sound Timbre +72 Sound Release Time +73 Sound Attack Time +74 Sound Brightness +75 Sound Control 6 +76 Sound Control 7 +77 Sound Control 8 +78 Sound Control 9 +79 Sound Control 10 +80 General Purpose Button 1 (on/off) +81 General Purpose Button 2 (on/off) +82 General Purpose Button 3 (on/off) +83 General Purpose Button 4 (on/off) +91 Effects Level +92 Tremulo Level +93 Chorus Level +94 Celeste Level +95 Phaser Level +96 Data Button increment +97 Data Button decrement +98 Non-registered Parameter (fine) +99 Non-registered Parameter (coarse) +100 Registered Parameter (fine) +101 Registered Parameter (coarse) +120 All Sound Off +121 All Controllers Off +122 Local Keyboard (on/off) +123 All Notes Off +124 Omni Mode Off +125 Omni Mode On +126 Mono Operation +127 Poly Operation