Skip to content

Accessing external protocols

There are many protocols supported by designer, and expressions are one method to access that data in a way which can enhance interactivity and creativity.

It is quite common to use the data sources described here to control layers.

OSC

OSC is a common, versatile method for transmitting data within production environments. Designer interacts with OSC via OSC devices. OSC devices build a series of addresses which can be referenced by expressions.

OSC works in terms of addresses and data values. One or more data values are stored at each address, in an array.

For example an external tool may send an OSC value to address /container/parameter and the value may be 5.0 - meaning, the value at /container/parameter is the floating point number 5.0.

In order to access the value at that OSC address, the user must translate that address into expression-compatible syntax, as well as identifying the lookup as a request to find something from the OSC devices.

There are several expressions which would find the data in the example above:

  • osc:.container.parameterName - The leading . character represents the leading / in the address. While this is not necessary, it can be convenient to remember that / characters are replaced by .s in OSC expressions.
  • osc:container.parameterName - The leading . character is omitted in this example.
  • oscdevice_1:container.parameterName - In this case, the specific device (“oscdevice 1”) is specified - if the user has multiple OSC devices set up, this helps disambiguate which OSC device specifically the user wants to gather the value from. Note that only OSC devices whos name begins with “osc” can be supported using this scheme.

OSC value arrays

Expressions also support more than one OSC argument per address. This allows the user to use things like XY touchpad to control colour X and colour Y values.

This uses array indexing syntax, e.g. osc:my.address[0] - this returns the first value sent to the address in a single message. Note this does not refer to values sent one after the other, the values need to be grouped together in a single OSC message to be addressable in this way.

In order to refer to both elements in an example scenario with a touchpad, the user would need to create two expressions:

  • osc:my.touchpad.xy[0] - refers to the X component
  • osc:my.touchpad.xy[1] - refers to the Y component

Missing OSC addresses

Before an OSC value has ever been sent to designer on a specific OSC address, an expression which looks up that address will evaluate to 0.0. That is, the expression osc:this.was.never.sent will evaluate to 0.0. This is convenient in a number of circumstantes, but sometimes finer-grained control is needed. For example in the case of string or text parameters, or where 0 is not the desired default value.

To achieve this, the same osc: syntax above can be changed to valid_osc: (or valid_oscdevice_1:) to check whether the OSC address has data associated with it.

For example: valid_osc:my.address will return 0.0 if the local instance of designer has never received a value for that address, and 1.0 if it has.

DMX

DMX512-derived network protocols are well supported by designer. Designer interacts with DMX protocols using DMX Devices and assocating them with the internal universe map held within designer. Expressions use internal designer universe numbers, which start from 1.

It is useful to access DMX data from one of these internal universes using a variety of expressions. All addresses in expressions are 1-based (i.e. universe 1 is the first universe, and channels range from 1 to 512.) This is in opposition to other indexing within expressions, which are 0 based, so needs to be kept in mind.

The given universe and channel placeholders in the syntax demonstrations below are always integer literals (no variables.)

  • dmx:universe.channel - Read 8 bit dmx value.
    • For example: dmx:1.28 reads a single byte (0-255) from universe 1, channel 28.
  • dmx16:universe.channel - Read 16bit dmx value (2 channels are used.)
    • For example: dmx16:1.28 reads two bytes (0-65,535) from universe 1, channel 28 and universe 1, channel 29.
    • 16 bit data is read as coarse data in the first channel, and fine in the second. This is often referred to as “big endian”.

As with all name lookups, it is possible to continue to extend the expression with functions and operators to compute the desired result. e.g. dmx:1.28 / 255 returns the same value scaled down to lie between 0 and 1.

When the expression has been accepted the layer property will turn green.

MIDI

MIDI is often used as a control interface for some shows. It is possible to use MIDI devices as a source of data for expressions. All MIDI expressions are based on CC (Control Change) MIDI messages,

mididevice:name.c[0] - Get float value from mididevice control 0 (the first control in the device.)

For example, you have a MIDI device named bcf2000, which has a total of 32 controls. You want to read the third control value and multiply it by the animated value coming from the timeline.

The correct expression to use would be:

self * mididevice:bcf2000.c[2]

Note that the control values are the damped values provided by the midi device.

Audio Expressions

Using the Audio analyser device, it is possible to include audio-reactive elements within expressions. Once the audio analyser is set up to analyse an audio line, the audio line is available to provide frequency analysis to expressions.

audioline:name.c[lower..upper] - Get the max damped level from a selection of frequency ranges, inclusive of the lower value, and exclusive of the upper.

For example, a project contains an audio analyser set up with the line_left audio line selected. The lowest 10 (out of 127) frequency buckets are queried for the maximum damped value using the following expression. This would check for bass frequencies.

audioline:line_left.c[0..10]

What does the expression mean?

The diagram below is broken up into sections with a letter underneath. A description of each section is located below the diagram.

Audio analyser expression

A: 255 = Multiplies the result by 255 (audioline frequency responses are in the range of 0.0 to 1.0)

B: audioline = identifies the following text as an audio expression

C: line_left = which audio line to use

D: .c[0..10]= the frequency range to analyse

How do I choose which frequencies to analyse?

The audio spectrum has 127 steps across the frequency range.

Audio spectrum

The audio analyser builds 127 frequency buckets across the full frequency range of the line in.

Any frequency from 0 to 127 or a range of frequencies can be analysed using part D of the expression described above. For example,

  • To analyse just the bass frequencies select a range similar to [0..10].
  • To analyse just the high frequencies select a range similar to [100..127].

It is recommended to experiment with the range based on a range of recordings of expected live inputs to ensure the result is robust.