/ Topics / Open Sound Control

Hz System Overview
Authoring Musical Notes, Soundscaping
Audio IO, MIDI IO
Open Sound Control
Asset-based, Nonlinear Workflow


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.

OSC client

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
}

OSC Server

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 Control

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

Known issues

See also:

OSC Home

rtosc, rtosc guide

losc

home .. topics .. interface .. reference .. examples .. tipjar