OpenSoundControl.org: /pages /contents /spec/1.0 /spec/1.1 /implementations /publications /about
(contents of this file: links to each section)
Probably by Matt Wright, circa 2012. Courtesy of Karl Yerkes.
function [message args] = parse_message(bytes)
% Parse a single OSC message whose arguments are all floats,
% returning a matlab string for the address and a vector of floats
% for the arguments
message = ''; args = [];
firstnull = find(bytes==0,1);
if isempty(firstnull)
disp(['Invalid OSC message (no null character = no string = no address)']);
return
end
% zero vs one origin indicing meets OSC's possible extra null characters
% to bring all strings up to a multiple of 4-byte length
lastnullafteraddress = firstnull + 3 - mod(firstnull-1, 4);
for i=firstnull:lastnullafteraddress
if bytes(i) ~= 0
disp(['Invalid OSC message (improper string termination)'])
return
end
end
message = char(bytes(1:firstnull-1)');
% Got the message, now throw away those bytes
bytes = bytes(lastnullafteraddress+1:end);
firstnull = find(bytes==0,1);
if isempty(firstnull)
disp(['Invalid OSC message (missing type tag string?)']);
return
end
% zero vs one origin indicing meets OSC's possible extra null characters
% to bring all strings up to a multiple of 4-byte length
lastnullaftertypetags = firstnull + 3 - mod(firstnull-1, 4);
for i=firstnull:lastnullaftertypetags
if bytes(i) ~= 0
disp(['Invalid OSC message (typetag has improper string termination)'])
return
end
end
typetags = char(bytes(1:firstnull-1));
argbytes = bytes(lastnullaftertypetags+1:end);
if typetags(1) ~= ','
disp(['Invalid OSC message (type tag string needs leading comma)']);
return
end
if ~all(typetags(2:end) == 'f')
disp(['Sorry; I only handle floating point arguments, not ' typetags]);
return
end
% Chop into groups of 4 bytes
for i = 1:4:length(argbytes)
% big->little endian and interpret bytes as 32-bit float
f = typecast(uint8(argbytes(i+3:-1:i)),'single');
args = [args f];
end
end
And here is the UDP listener it goes with, (probably) written by Karl Yerkes around 2012.
function udp_listen(handler, port, timeout, address)
% function udp_listen(handler, port, timeout, address)
%
% udp_listen accepts 4 arguments:
%
% handler - a function that accepts a column vector of bytes and returns nothing
% port - the port on which to listen
% timeout - the number of seconds to wait before giving up on a single read
% address - the ipv4 address on which to listen
%
% try these examples:
%
% udp_listen(@(bytes) disp(bytes'), 12345, 0.01, '127.0.0.1')
% udp_listen(@(bytes) disp(char(bytes')), 12345, 0.01, '127.0.0.1')
%
% open a udp socket and listen
%
udp_object = udp(address, ...
'LocalPort', port, ...
'Timeout', timeout, ...
'Terminator', '', ...
'InputBufferSize', 65536);
fopen(udp_object);
% ensure that the udp socket gets destroyed when this function is done
%
localObject = onCleanup(@() delete(udp_object));
% loop forever (until ctrl-c, matlab shutdown, crash, or earthquake)
%
while true
try
data, count, error_message, from_address, from_port] = fread(udp_object);
[
% uncomment for debugging
disp(['got ', int2str(count), ' bytes from ', from_address, ':', int2str(from_port)])
if isempty(data)
disp(['still listening...']);
else
handler(data);
end
catch me
% hide errors/exceptions when we break this infinite loop with ctrl-c
% we should actually check if this is exception is ctrl-c related (TBD)
%
disp(['Exception caught ', me])
return
end
end
end
This page of OpenSoundControl website updated Tue May 4 12:44:27 PDT 2021 by matt (license: CC BY).