Open Sound Control (OSC) is a communication protocol for collaborative control of audio engines and their clients. The Hz MusicAPI can be used to send and receive/perform OSC events.
Hz is can operate as both OSC client and OSC server.
You can write lua scripts that act as OSC clients, awaiting OSC activity on one or more network ports and converting it to musical events.
Here's a simple JavaScript example script that logs OSC events as they arrive.
let oin = new OSCIn();
let err = await oin.Connect(); // listen on default port (22000)
if(!err)
{
console.info("oin connected");
for(let i=0;i<30;i++)
{
let msg = await oin.Recv();
console.info(`${i} OSC msg: ` + JSON.stringify(msg));
}
console.info("oin done after 30 messages");
oin.Disconnect();
}
else
console.warn("Problem listening on default OSC port.");
And here's a Lua example client:
-- Express interest in OSC messages on a particular port
-- When not specified, we use the default OSC server port (22000, overridable via CLI)
-- Otherwise, a server in created on demand and may be shared by multiple coroutines.
local OSC = App.OSC
local oscIn = OSC.Recv:new({port: 8000})
local oscMsg = {}
oscIn:addMsgFilter("/foo/bar") -- express interest in a subset of messages
while(oscIn:recv(oscMsg))
{
Log.info(Inspect(osgMsg))
-- An OSC packet is a lua table comprising:
-- - three named fields:
-- - addr (string) eg "/foo/notes"
-- - types (string) eg "iffs" (int, float, float, s)
-- - origin (string) (host)
-- - 1-indexed array values whose length and types are given by types
}
You can also write lua scripts to control other OSC servers via hz.
local go = function(loopcount, dur, host)
local cfg = {host = host, port = 10000} --- cfg: {port, transport}
local oscOut = App.OSC.Send:new(cfg)
local id = ""..oscOut.id
for i=1,loopcount do
oscOut:start("/foo/note")
oscOut:add(i)
oscOut:add(.33 * i)
oscOut:add("id")
oscOut:send()
Log.notice(string.format("OSC.%d send1 %d/%d", id, i, loopcount))
App.audio.wait(dur) -- <---- wait/yield
end
end
App.audio.start() -- here we ust audio for its wait capability
EventHub:on("audio:running", function()
local dur = App.audio.dur.seconds(.5)
local loopcount = 10
App.performCoroutine(go, "send1", loopcount, dur, "localhost")
App.performCoroutine(go, "send1", loopcount, dur, "10.10.10.1")
App.performCoroutine(go, "send1", loopcount, dur, "192.168.1.113")
end)
Remote controlling Hz can be accomplished with OSC by
command-line arguments to Hz-itself. We reserve the /_ctrl
namespace which to implement the simple on-the-fly controls,
osc:add, osc:del, osc:clear and osc:quit
.
% hz --osc:help
osc options:
--osc:recv:${port}
sets default listening port)
--osc:send:${port}[:${host}]
sets default sending port)
--osc:add:${filename}
sends a filename to target hz
--osc:del:${coId}
deletes a coroutine in target hz
--osc:clear
clears all coroutines in target hz
--osc:quit
requests quit in target hz
* send host defaults to localhost
* port defaults to 22000
Perform one or more script files in a running hz. Note that we currently send the file name (and current directory), not the file contents to the active hz (server).
% hz --osc:add:one.lua --osc:add:two.lua