Initial author: Emanuel Rumpf
OSC (open sound control) is a protocol for exchange of arbitrary (media) data over TCP/IP or UDP/IP between a server and client application.
Currently there is no consensus how to represent and address MIDI data over OSC.
This document is a draft / brainstrom for transmission of MIDI data in a standardized way using the OSC protocol.
The point: You could implement a transmitter, being sure that each receiver following this spec would be able to play back the received midi data without further configuration.
Everyone is welcome to improve / implement this.
/ ApplicationName / ApplicationSection / midi (keyword) / channel (keyword) / ch-nr. / midi-msg-type / midi-msg-name (see midi-actions)
Strings not-required default to “none”
example (using python, liblo):
target = liblo.Address( 1234 ) # play a C note (60) at channel 0 with velocity (loudness) of 112 liblo.send( target, "/osc_receiver01/none/midi/channel/#0/note_on/none", 60, 112 ) # change expression-controller on channel 0 to 117 (dec) liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/expression", 117 )
If access by number is possible (e.g. controller names, channels), the related number can be used
by prefixing with # for decimal values or by #0x for hex values.
example:
# send a controller_change event for expression (value 11) liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/expression", 117 ) # value # alternatives with numbers: liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/#11", 117 ) liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/#0x0B", 117 )
MIDI distinguishes fine and coarse control.
If not specified, coarse is default.
Coarse and fine can be combined. (2 bytes coarse, followed by 2 bytes fine).
# fine / coarse liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/expression_coarse", 117 ) liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/expression_fine", 18 ) # combined: liblo.send( target, "/osc_receiver01/none/midi/channel/#0/controller_change/expression_combi", (117 << 16) & (18) )
All values are transmitted as integer 32 bit unsigned values (allowing a higher precision than MIDI for the future)
(midi messages usually consist of 1 to 3 values (bytes) )
(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
# integer values, first is count of elements (incl. length value) ! blob = [0, 8, 15, 16, 23, 42] # set length blob[0] = len( blob ) # send liblo.send( target, "/osc_receiver01/none/midi/channel/#0/sysex/none", blob )
TODO