MIDI to OSC

Hi there -
I’m not sure if this is possible - I’m having a little trouble figuring it out.
I’d like to take an incoming MIDI stream and convert it to OSC messages.
I seem to have effectively done this - as I can turn on “OSCFunc.trace(true)” and see the message… but I am unable to discretely monitor this specific message with a unique OSCdef.

Is there something I’m failing to understand?

(
MIDIClient.init;
~midiListener = MIDIIn.connectAll;

~oscAddr = NetAddr("127.0.0.1", 57120);

// Note On/Note Off
~sendNoteAsOSC = { |src, chan, num, vel|
    var val, addrStr;
    val = (vel > 0).asInteger;   // 1 = note on, 0 = note off
    addrStr = "/note/" ++ num.asString;
    ~oscAddr.sendMsg(addrStr, val); 
};

// MIDI to OSC
MIDIIn.noteOn = { |src, chan, num, vel|
    ~sendNoteAsOSC.(src, chan, num, vel);
};

MIDIIn.noteOff = { |src, chan, num, vel|
    ~sendNoteAsOSC.(src, chan, num, 0);
};

// Listener for received OSC messages (doesn't work)
OSCdef(\midiOSCReceiver, { |msg, time, addr, recvPort|
    ("Received OSC: " ++ msg).postln;
}, "/note");
)

Thanks!

~oscAddr.sendMsg("/note", num, val)

Usually it’s not a good idea to concatenate data into the OSC path. In this case, it creates the complication that you would need a separate responder for every note number. The solution, then, is, simply don’t do the unnecessary concatenation, and send a message with two data arguments.

hjh

1 Like

Thank you! I see this does seem to work now - but if my note data and on/off data are sent as an array, I get an Int8Array. Is there a way to decode that?

What exactly does the array consist of?

hjh

Well, I changed to this:

~sendNoteAsOSC = { |src, chan, num, vel|
   var val = (vel > 0).asInteger;  
	~oscAddr.sendMsg("/1", [num, val]);
};

But now it returns an array something like this:
Received OSC: [/1, Int8Array[0, 0, 0, 62, 44, 105, 0, 0, 0, 0, 0, 1]]

The “62” is likely the note number and the 1 at the end is the on/off value - but I’m not sure what the rest of the numbers are, or why they’re there.

Took a minute to realize what’s going on here.

A TL;DR might be that it’s usually better to avoid introducing complexity when it’s not needed. In this case, SC’s OSC implementation mainly carries a command path at the head, followed by a flat list of data values. It’s not impossible, but more rare, to send structured data. I’d introduce structure into an OSC message only if you really benefit from it… but here it’s just two integers. So the extra complexity is only raising questions but not offering any concrete improvements over the non-array alternative.

So why is it encoding like that?

Some SC server messages accept a secondary OSC command to run after their main work is done (many of the Buffer commands, for instance). In SC language, you write the secondary message as an array within the main message. SC encodes the sub-array as an OSC message and embeds that binary representation.

In your array, the first element is an integer. This is treated as though it’s a command path (SC server, contrary to the strict OSC spec, allows commands to be integers or strings). That’s the 0 0 0 62. Then you get type tags for the message arguments. There’s one integer argument = 1, so there’s an i (ASCII 105) and then I think 44 is a terminator. Couple 0s to pad to 32 bits, then the 0 0 0 1.

If all that seems needless for your use case – it is! And it’s easily avoided by simply not using an array here.

hjh