OSC Output — Oscilla → Max, Pd, SuperCollider
Almost every moving or interactive object in an Oscilla score can stream its state to other software as OSC. The server sends UDP to 127.0.0.1:57120 by default — sclang's port, so SuperCollider hears it with no setup. Every address starts with /oscilla/.
This page is the receiving side. For messages into Oscilla see OSC Input; for the discrete osc() event cue see cue:osc.
Example patches
Three ready-made receivers, one panel per object type, with bangs, faders and number boxes wired to every address in the table below:
| Environment | File | Notes |
|---|---|---|
| Pure Data | oscilla-osc-in.pd | vanilla 0.47+, no externals (netreceive -u -b → oscparse) |
| Max | oscilla-osc-in.maxpat | stock objects only (udpreceive → route) |
| SuperCollider | oscilla-osc-in.scd | OSCdefs driving a Qt window; sine blip per notation note when the server is booted |
Open the demo project demo-osc-send in Oscilla, open one of the patches, press play. Sections A–F of that score drive o2p, oscCtrl and osc() triggers; section G holds rotate, scale, fade, trans, metro, synth and notation objects, all with osc:1. The same three files ship inside the demo project folder (pd/, sc/, max/).
To point them at your own score, change the uid in each route / OSCdef to the uid of your object.
Turning OSC on
- Per object — add
osc:1to the cue:rotate(dur:6, osc:1, uid:wheel).rotate,scale,fade,trans,o2p,metro,synth,audio,audioPoolandaudioImpulseare all off until you do.notation()fires on playhead-pass by default;oscCtrl(),controlXY()andosc()exist to send OSC and are always on. - Address override —
oscaddr:is the full address, sent exactly as written:rotate(dur:6, osc:1, oscaddr:/oscilla/rotate/abc)oroscaddr:/iem/source/1. In the DSL editor the field opens showing the object's default address, so you edit it in place; leave it unchanged and nothing is written. A value without a leading slash (oscaddr:rotate/abc, older scores) is placed under/oscilla/. - Mute — the OSC mute button in the top bar, with Preferences → OSC Output as the project's default. The OSC monitor overlay still shows what would be sent.
- Several machines, one stream — every client runs the same score, so every client produces the same OSC. The server forwards it from the sync leader only and discards the rest; the leader is marked ★ (and the current OSC source ♪) in the client list. If the leader's browser crashes the others elect a new one within about half a second, and while there is no leader everyone's OSC is forwarded, so the stream never stops. A muted leader hands the role to the others. You do not need to mute anyone by hand.
- Ports — the server console has an OSC ports section: the port Oscilla
listens on, and a list of destinations to send to. Add as many as the rig
needs — Pd here, Surge XT there, a lighting desk on another machine — with
+ destination. Changes apply at once, without a restart, so a running score
keeps playing and the next message goes to the new destinations. They are
remembered between runs.
--osc-in,--osc-outand--osc-out2still work and become the first entries in the list; when a startup option is in play the console shows the list read-only and says so, rather than accepting an edit the next restart would undo.
Every destination receives every message. This is not a split: each application hears the whole stream and ignores what it does not recognise. Two programs on one machine cannot share a UDP port, which is the only reason more than one destination is needed.
Rates: continuous streams (rotate, scale, fade, trans, o2p, control lanes) are throttled to one message per address every 33 ms in the browser and de-duplicated within 30 ms on the server. Discrete events (triggers, waypoint arrivals, notation notes, metro beats) are never dropped.
Address reference
f float, i int, s string. <uid> is the object's uid: (or its element id when none is given).
| Object | Address | Arguments |
|---|---|---|
rotate(osc:1) |
/oscilla/rotate/<uid> |
deg f rad f norm f (0–1) |
scale(osc:1) |
/oscilla/scale/<uid> |
sx f sy f (1 = authored size) |
fade(osc:1) |
/oscilla/fade/<uid> |
opacity f |
trans(osc:1) |
/oscilla/trans/<uid> |
total f (whole waypoint list, 0–1) legT f (current leg) x f y f idx i (waypoint being headed for, −1 = home) |
/oscilla/trans/<uid>/waypoint |
i — sent on each arrival |
|
o2p(osc:1) |
/oscilla/o2p/<uid> |
t f (path position) normX f normY f angle f worldX f worldY f sweepX f sweepY f p f |
/oscilla/o2p/<uid>/vertex |
i — sent when passing a path vertex |
|
controlXY() |
/oscilla/controlXY/<uid> (…/<handleId> with several handles) |
normX f normY f [normP f] |
oscCtrl(addr:…) |
/oscilla/control/<addr> |
v f (the lane's value, already scaled to its min:…max:) t f (position along the lane, 0–1) |
oscOut(addr:…, a: follow(…), b: follow(…)) |
/oscilla/<addr> |
one f per named parameter, in the order written — any signal, already mapped by its follow()/map(). See Sinks |
osc(addr:…) |
/oscilla/<addr> |
pitchType f pitchA f pitchB f size f env f density f [root f] [gate f] — see cue:osc |
osc(click:1, toggle:1) |
/oscilla/<addr> |
state i (0/1) |
notation() |
/oscilla/notation/<uid>/note |
i i midi f freq f cents i style s name s |
metro(osc:1) |
/oscilla/metro/<uid> |
beat i bpm f — one message per beat |
synth(osc:1) |
/oscilla/synth/<uid> |
state s (start step update stop) freq f amp f dur f (lifetime / step length / release) wave s |
audio(osc:1) |
/oscilla/audio/trigger |
file s vol f loop i |
audioPool(osc:1) |
/oscilla/audio/pool |
file s amp f pan f pitch f fadeIn f fadeOut f |
audioImpulse(osc:1) |
/oscilla/audio/impulse |
same as pool |
| audio stop | /oscilla/audio/stop |
file s (all) fadeOut f (seconds) |
Receiving
Pure Data — oscparse turns /oscilla/rotate/wheel 12 0.2 0.03 into the list oscilla rotate wheel 12 0.2 0.03; after list trim a chain of route objects peels the address off one word at a time:
[netreceive -u -b 57120]
|
[oscparse]
|
[list trim]
|
[route oscilla]
|
[route rotate scale fade trans o2p control notation metro synth audio]
| (right outlet: osc() addresses such as kick)
[route wheel]
|
[unpack f f f] -> deg, rad, norm
When the first remaining atom is a string (audio file names, synth state), route makes it the selector; put a [list append] before [unpack s f i] to turn it back into a list. Both quirks are wired up in the example patch.
Max — udpreceive decodes OSC itself, so the address is the message selector:
[udpreceive 57120]
|
[route /oscilla/rotate/wheel /oscilla/scale/pulse]
| |
[unpack f f f] [unpack f f]
Use slider with @floatoutput 1 @size 1. for 0–1 values, dial @size 360. for degrees.
SuperCollider — one OSCdef per address; strings arrive as Symbols and msg[0] is the address:
OSCdef(\wheel, { |msg| ("deg" -> msg[1]).postln }, '/oscilla/rotate/wheel');
OSCdef(\note, { |msg| Synth(\blip, [\freq, msg[3]]) }, '/oscilla/notation/tune/note');
// wildcards: every oscCtrl lane
OSCFunc({ |msg| msg.postln }, '/oscilla/control/*');
If Oscilla was started with another --osc-out port: thisProcess.openUDPPort(57122).
Surge XT
An address beginning surge/ is translated onto the second OSC destination
and sent as a Surge parameter:
oscaddr:"surge/macro/1" written on the cue
↓
/param/macro/1 0.73 sent to --osc-out2
Start the server with --osc-out2 53280 (Surge's default OSC input port, which
has to be enabled in Surge under menu → Workflow → OSC Settings). One float
between 0 and 1, which is what Surge's /param takes, so a control lane keeps
its default min:0 max:1 and the height you draw is the parameter value. This
works from any cue that carries an oscaddr: — control lanes, faders driven by
o2p, osc() events.
Parameter paths look like a/filter/1/cutoff — scene, section, index, name.
Right-click any knob in Surge and choose Copy OSC Address to get the exact one.
Macros are macro/1 … macro/8 and are the same in every patch, which makes
them the natural place to put controls you want a player to aim freely.
The prefix reaches Surge's whole OSC vocabulary, not only parameters: writing
surge/mnote sends /mnote note velocity to play a note, surge/patch/load_user
changes patch, and surge/mod/macro_1 wires a macro to a parameter. Surge's own
reference, linked from its OSC settings, lists all of it.
The /param/… translation goes to every destination, alongside the ordinary
/oscilla/… message, so the same drawn gesture can move Surge and a Pd or
SuperCollider patch at once. See the demo-surge-xt project for a score wired
up this way.
Port conflicts
sclang binds 57120 while it runs, so Pd or Max cannot open it at the same time. Either quit SuperCollider, start Oscilla with --osc-out 57122 and change the port in the patch, or keep 57120 for SuperCollider and add --osc-out2 57122 for the second application.
See also
- cue:osc — the discrete event cue and its packet format
- oscCtrl() — continuous control lanes
- controlXY() — multitouch XY pads
- OSC Input — driving Oscilla from outside
- OSC developer guide — message types inside the WebSocket
Tip: use ← → or ↑ ↓ to navigate the docs