OSC

Basic support for Open Sound Control protocol is available via the Synth.OSC module.

Design

The basic idea is to model the type of an OSC message packet as a Julia Tuple. The following types are supported - Int32, UInt32, Int64, UInt64, Float32, Float64,String, Symbol, Char, RGBA{N0f8}, OSC.Blob, OSC.TimeTag.

While you can read an Int32 value as an Int64, while writing they're written with their respective OSC type tags. The same goes for Float32 and Float64. We don't permit casting a Float64 value in the packet to a Float32 upon reading because it might signal a loss of precision. This is debatable though since most applications use Float32. However in some special cases like latitude/longitude, the double precision makes a difference and there will be loss of precision if it is down-converted to Float32. Similarly Symbol and String can parse each others type tags but when writing they use their own tags. The unsigned types use the same type code as the signed ones and so must have the same but positive range.

The methods and type names are chosen so that they can be used comfortably with the module prefix, so OSC is not expected to be imported with using.

import Synth.OSC as OSC
msg = OSC.unpack(Tuple{Int32,Float32}, packetBytes)
println("address = ", msg.address)
println("data = ", msg.data) # Should print the tuple.

For packing OSC messages, use pack! or pack. You can use NamedTuple as well with unpack.

Methods

Synth.OSC.pack!Function
pack!(packet::Bytes, address::AbstractString, t::Union{Tuple,NamedTuple})
pack!(packet::Bytes, msg::Message)

Packs the given tuple of data to be sent to the given address into the given bytes array and returns a view into the array containing the actual bytes to be sent. This means that packet must have sufficient size to store all the information.

Use packosc if you want the packet to be allocated automatically.

source
Synth.OSC.packFunction
pack(address::AbstractString, t::Tuple)
pack(msg::Message)

Convenience function to allocate and return a constructed OSC packet with the given data. See also pack! for a non-allocating version.

source
Synth.OSC.unpackFunction
unpack(t::Type{Message{T}}, packet::Bytes) :: Message{T}
unpack(t::Type{T<:Tuple}, packet::Bytes) :: Message{T}
unpack(t::Type{T<:NamedTuple}, packet::Bytes) :: Message{T}

Give an OSC packet and a Tuple or NamedTuple type, parses the packet according to the types of the given tuple and returns an appropriate Message. It is convenient to define aliases for the types of messages you want to handle then use these aliases with unpack like below –

const FloatMsg = OSC.Message{Tuple{Float32}}
msg = unpack(FloatMsg, packetBytes)
@assert typeof(msg) <: FloatMsg
source
Synth.OSC.startFunction
start(ipaddr::IPAddr, port::Int) :: Closure

Starts a thread for receiving and processing OSC messages and returns a control procedure for it. Here is example usage -

osc = OSC.start(ip"127.0.0.1", 7000)
# Route an OSC float32 message to a Synth.Control
osc(:control, "/multisense/orientation/pitch", c, (x) -> 0.5+x/360)
# Clear a previously setup route.
osc("/multisense/orientation/pitch", nothing)
# General routing of message
b = bus()
play(b)
const Buttons = Message{@NamedTuple{btn::Int32}}
osc(r"^[/]touch[/]button", Buttons, b) do address, msg, b
    sched(b, midinote(1, msg.data.btn, 0.8, 0.5))
end
# Route a Float32 control to another destination
# Either give the IPAddr and Port explicitly or
# construct a Dest and pass it. The former can be
# more space efficient because the buffer is allocated
# to exactly meet the required packet size.
osc(c, "/orientation/pitch", ip"127.0.0.1", 7001)
d = dest(ip"127.0.0.1", 7001; buffersize = 32)
osc(c, "/orientation/pitch", d)
# Stop all OSC processing
osc(:stop)
source
Synth.OSC.destFunction
dest(ip::IPAddr, port::Integer; buffersize = 4096)

Construct an OSC destination targeting the given IP address and port. This also allocates a buffer for use when sending packets across, but the buffer can be reused for each send. Use Base.close on the Dest to close the associated socket.

source
Synth.OSC.sendFunction
send(dest::Dest, address::AbstractString, t::Union{Tuple,NamedTuple})

Sends the given tuple with the given target address as an OSC encoded packet.

source
send(dest::Dest, msg::Message)

Sends the msg as an OSC packet on the given dest.

source

Types

Synth.OSC.BlobType

Blob is a vector of unsigned bytes that can be interpreted in an application dependent manner.

source
Synth.OSC.ColourType

Colour or Color is an RGBA colour that makes up 4 bytes. The parsed colour is scaled to [0.0,1.0] range treating the colour as a fixed point value.

source
Synth.OSC.MessageType
struct Message

Encapsulates an OSC message which is a piece of typed data (.data field) associated with an address (.address field).

source