Added README.md from upstream.

Added MIDI channel support.
master
Holger Wirtz 4 years ago
parent 15449c78ab
commit 90f8157b9d
  1. 57
      OSC2Midi.cpp
  2. 3
      OSC2Midi.h
  3. 14
      OSC2MidiGateway.ino
  4. 52
      README.md
  5. 22
      debug.h

@ -3,40 +3,45 @@
#include <stdlib.h> #include <stdlib.h>
/* /*
* TODO: this will return rather unpredictable numbers when TODO: this will return rather unpredictable numbers when
* given strings with numbers > 255. given strings with numbers > 255.
*/ */
uint8_t getCC(const char *str, int index) uint8_t getCC(const char *str, int index)
{ {
const char *offset = str; const char *offset = str;
// skip the first / // skip the first /
if (strncmp(str, "/", strlen("/")) == 0) if (strncmp(str, "/", strlen("/")) == 0)
{ {
offset++; offset++;
} }
if (index == -1)
{
return atoi(offset);
}
while (index > 0) if (index == -1)
{ {
const char *new_offset = strstr(offset, "/"); return atoi(offset);
if (new_offset) { }
offset = new_offset + 1;
} else {
return 0;
}
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) uint8_t getCC(const char *str)
{ {
return getCC(str, -1); return getCC(str, 1);
} }
uint8_t getMIDIChannel(const char *str)
{
return getCC(str, -1);
}

@ -5,5 +5,6 @@
uint8_t getCC(const char *str, int index); uint8_t getCC(const char *str, int index);
uint8_t getCC(const char *str); uint8_t getCC(const char *str);
uint8_t getMIDIChannel(const char *str);
#endif #endif

@ -48,8 +48,10 @@ void setup() {
void OSCToMidiCC(OSCMessage &msg, int offset) { void OSCToMidiCC(OSCMessage &msg, int offset) {
char address[100] = { 0 }; char address[100] = { 0 };
uint8_t cc, value; uint8_t cc, value;
uint8_t midichannel;
msg.getAddress(address, offset, sizeof(address)); msg.getAddress(address, offset, sizeof(address));
midichannel = getMIDIChannel(address);
if (msg.size() == 1 && msg.isFloat(0)) { if (msg.size() == 1 && msg.isFloat(0)) {
// Single or multi control with sending one value // Single or multi control with sending one value
@ -57,20 +59,20 @@ void OSCToMidiCC(OSCMessage &msg, int offset) {
value = round(msg.getFloat(0)); value = round(msg.getFloat(0));
value = value > 127 ? 127 : value; value = value > 127 ? 127 : value;
DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, 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)) { } else if (msg.size() == 2 && msg.isFloat(0) && msg.isFloat(1)) {
// XY pad, two values // XY pad, two values
cc = getCC(address, 0); cc = getCC(address, 1);
value = round(msg.getFloat(0)); value = round(msg.getFloat(0));
value = value > 127 ? 127 : value; value = value > 127 ? 127 : value;
DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, 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 = round(msg.getFloat(1));
value = value > 127 ? 127 : value; value = value > 127 ? 127 : value;
DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value); DEBUG_MSG("MSG: %s\tCC: %u\tValue: %u\n", address, cc, value);
MIDI.sendControlChange(cc, value, 1); MIDI.sendControlChange(cc, value, midichannel);
} else { } else {
DEBUG_MSG("Cannot handle: %s\n", address); 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) { void MidiCCToOSC(uint8_t channel, uint8_t number, uint8_t value) {
char buffer[1024]; 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); OSCMessage msg = OSCMessage(buffer);
msg.add(value * 1.0); msg.add(value * 1.0);

@ -1,2 +1,54 @@
# OSC2MidiGateway # 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

@ -7,20 +7,20 @@
#define DEBUG_MSG(...) Serial1.printf( __VA_ARGS__ ) #define DEBUG_MSG(...) Serial1.printf( __VA_ARGS__ )
#define DEBUG_OSC_MESSAGE(msg) \ #define DEBUG_OSC_MESSAGE(msg) \
do { \ do { \
char address[100]; \ char address[100]; \
msg.getAddress(address, 0, sizeof(address)); \ msg.getAddress(address, 0, sizeof(address)); \
Serial1.printf("osc message: [%d] %s ", msg.size(), address); \ Serial1.printf("osc message: [%d] %s ", msg.size(), address); \
for (int i = 0; i < msg.size(); i++) { \ for (int i = 0; i < msg.size(); i++) { \
if (msg.isFloat(i)) { Serial1.printf("f:%f\t", msg.getFloat(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.isInt(i)) { Serial1.printf("i:%d\t", msg.getInt(i)); } \
} \ } \
Serial1.printf("\n"); \ Serial1.printf("\n"); \
} while(0); } while(0);
#else #else
#define DEBUG_MSG(...) #define DEBUG_MSG(...)
#define DEBUG_OSC_MESSAGE(...) #define DEBUG_OSC_MESSAGE(...)
#endif #endif
#endif #endif

Loading…
Cancel
Save