a2r-osc

An OSC implementation for node.js and the browser

Addicted2Random OSC

A2R OSC is an Open Sound Control implementation for Node.js and the browser. It implements the OSC 1.1 specification and supports compressed address strings (smc2011)

This project was created as part of the Addicted2Random project.

sock = udp.createSocket "udp4"(data, rinfo) ->
  try
    message = osc.fromBuffer(data)
    doSomethingUseful message(err, reply)->
      if err
        res = new osc.Message("/error"message.addresserr.message)
      else
        res = new osc.Message("/reply"message.addressreply)
 
      buffer = res.toBuffer()
      sock.send(buffer0buffer.lengthoutportrinfo.address)
  catch error
    console.log "error parsing data"
    console.log error.stack
 
sock.bind 5000

The following types are supported by A2R-OSC:

  • i: 32Bit integer, given floats will be rounded
  • f: 32Bit float, the default assumption for JavaScript numbers
  • s: An ASCII string, the default assumption for JavaScript strings
  • b: A blob, must be either an ArrayBuffer or a Node Buffer
  • d: A 64Bit double, represented as a JavaScript number
  • c: An ASCII character, packed as 32Bit integer, represented as a string with a length of 1
  • r: RGB color, packed as 32Bit integer, represented as JavaScript number
  • t: A NTP timetag, packed as 64Bit NTP timetag, represented as JavaScript date
  • T: A boolean true
  • F: A boolean false
  • N: A null
  • I: An Impulse or bang, represented as osc.Impulse (a singleton marker object)

Represents an OSC message.

  • address: The OSC address string
  • typetag: The OSC type tag without leading ','-character
  • arguments: Array of arguments

Takes an OSC address, an optional type tag and an optional (array of) argument(s).

new osc.Message("/a2r/mima/1/xy""ii"[123456])
new osc.Message("/a2r/mima/1/metro"osc.Impulse)
new osc.Message("/a2r/mima/1/adsr"[501284])
new osc.Message("/a2r/mima/1/adsr"[{ type: "i"value: 50 }...])

This returns a copy of the message without cloning each argument.

Add a value to the arguments list. If called with two arguments, the first argument will be treated as type code.

Returns itself for chaining.

new Message("/a2r/mima")
  .add("foo")
  .add("i"45)
  .add("integer"83)

Generates and returns a Buffer on Node.js or an ArrayBuffer in the browser.

The optional dictionary is for compressed address string support (see below).

Compare this message to another message. Returns true if equal otherwise returns false.

Represents an OSC bundle.

  • timetag: The timetag either 1 for immediately or a JavaScript data object
  • elements: Array of messages

Takes a date object and an optional list of bundle elements.

new osc.Bundle(new Date[new osc.Message("/a2r/endpoint"osc.Impulse)])

This returns a copy of the bundle and a clone of each message in the elements list.

Adds a message to the elements list. Takes either an instance of osc.Message or arguments to create an instance of osc.Message (see Message constructor).

Returns the message added to the elements list.

bundle.addElement("/a2r/endpoint"osc.Impulse)

Same as Bundle::addElement but returns itself for chaining.

new osc.Bundle(new Date)
  .add("/a2r/mima/1/a"23)
  .add("/a2r/mima/2/b"78.9)

Generates and returns a Buffer on Node.js or an ArrayBuffer in the browser.

The optional dictionary is for compressed address string support (see below).

Compare this bundle to another bundle. Returns true if equal otherwise returns false.

Takes a Node.js Buffer- or an ArrayBuffer-object and returns either an osc.Message or osc.Bundle, or throws an error if the buffer isn't well-formed.

The optional dictionary is for compressed address string support (see below).

The class osc.UnpackStream implements Nodes writable stream interface, osc.PackStream implements the readable stream interface.

Both stream classes take an optional dictionary as first argument to handle compressed address strings (see below).

A TCP OSC server utilizing (node-a2r-slip)[http://github.com/beyama/node-a2r-slip].

server = net.createServer (socket)->
  # Create stream for incoming data. 
  # 
  # incoming package -> SLIP decoder -> OSC unpack stream 
  # 
  # create OSC unpack stream 
  oscUnpackStream = new osc.UnpackStream()
  # handle message event of unpack stream 
  oscUnpackStream.on("message"(message)-> doSomethingUseful(message))
  # create SLIP decoder to decode incoming data 
  slipDecoder = new slip.SlipDecoder()
  # pipe encoded data to unpack stream 
  slipDecoder.pipe(oscUnpackStream)
  # pipe socket to SLIP decoder 
  socket.pipe(slipDecoder)
 
  # Create stream for outgoing data. 
  # 
  # message -> OSC pack stream -> SLIP encoder 
  # 
  # create SLIP encoder to encode outgoing data 
  slipEncoder = new slip.SlipEncoder()
  # pipe SLIP encoded data to socket 
  slipEncoder.pipe(socket)
  # create OSC pack stream 
  oscPackStream = new osc.PackStream()
  # pipe packed data to SLIP endoder 
  oscPackStream.pipe(slipEncoder)
 
  oscPackStream.send(new osc.Message("/osc/hello"osc.Impulse))
 
server.listen(5000)

A simple dictionary class to map ids to addresses and patterns and vice versa. This is used for compressed address string support (see below).

Takes an optional id-to-address and/or id-to-pattern object.

new osc.Dictionary(1: "/asr"2: "/a2r/osc")

Add an id-to-address respectively an id-to-pattern mapping to the dictionary.

Get an address respectively a pattern by id from the dictionary.

If you like to provide your own implementation of a dictionary than you have to implement these methods.

Get an id by address respectively pattern from the dictionary.

If you like to provide your own implementation of a dictionary than you have to implement these methods.

Remove an address respectively an pattern by id or string from the dictionary.

Compressed address strings are a way to improve the efficiency of the OSC communication protocol.

Basically, both sides of a communication have to know a (sub-) set of accessible OSC endpoints of the counter side and each endpoint has to have a known unique integer id. Instead of sending a whole OSC address or pattern again and again, the sender uses the special address '/' for addresses or '/?' for patterns and the integer id of the endpoint or the id of the pattern as first argument of the message.

For example: a message with an address like "/session/instrument/adsr" (24 bytes + 4 bytes padding) will be sent with address "/" (1 byte + 3 bytes padding) and the integer id (4 bytes) as first argument.

A2R-OSC can handle this internally by providing a dictionary (see above) to its 'toBuffer' and 'fromBuffer' methods or to the constructors of the both stream classes.

If you find what looks like a bug:

Check the GitHub issue tracker to see if anyone else has reported an issue.

If you don't see anything, create an issue with information about how to reproduce it.

If you want to contribute an enhancement or a fix:

Fork the project on github.

Make your changes with tests.

Commit the changes without making changes to any files that aren’t related to your enhancement or fix.

Send a pull request.

Created by Alexander Jentz, Germany.

MIT License. See the included LICENSE file.