Extensive OSC tutorial


Hi, I’ve seen that a lot of in_thread members are using OSC controls extensively in their everyday practice with Sonic Pi. However, the in-built tutorial is only covering the basic aspect of OSC messaging, both for input and output.

I’m starting a project which requires to make an intensive usage of OSC messaging: using Sonic Pi as the language for my live-coding performance, and Max/Msp as the support for audio-synthesis. I’m running into various problems when trying to send multiple messages in a very short amount of time (enveloppe trigger, filter cutoff, resonance, various controls, etc…)

I would like to start this topic to gather everything you’ve learned so far about OSC messaging in Sonic Pi, and what you will recommand for others to do in order to use this functionality with efficiency. For instance, how to properly send melodic or harmonic information, how to create good osc controls, etc…

This topic could be used in the future as a basis for a larger article or something else, covering this aspect of working with Sonic Pi.

Thanks, have a good day.


Hi there, I’d love to hear more about the specific issues you’re facing using OSC.


I have used OSC messaging extensively with Sonic Pi in a wide range of projects involving messages both to and from SP and to a range of interfaces from python scripts processing sketches TouchOSC and a brief play with Ableton live connection kit.
I think it best if you kick off with details of the problems you are finding.


I will post a more detailled example tomorrow, but here is a little snippet:

live_loop :sine do
  note =(ring 50, 54, 57, 59).tick(:note)
  sine(note, 2)
  sine_adsr(2000, 100, 1, 10)

Sine and sine_adsr are two functions defined in another buffer. The first one is sending three OSC messages : 1) note 2) note-on 3) note-off. The second one is sending four messages : 1) attack 2) decay 3) sustain 4) release.

The functions are :

define :sine do |note, len|
  use_osc "localhost", 5000
  osc "/trig 1"
  osc "/note " + note.to_s
  sleep len
  osc "/trig 0"

define :sine_adsr do |a, d, s, r|
  osc "/env_a " + a.to_s
  osc "/env_d " + d.to_s
  osc "/env_s " + s.to_s
  osc "/env_r " + r.to_s

These messages are received by the Max/Msp patch, but some packages are missing. A few of them are not received at all, some are late or desynchronized to the beat.

I think it’s mostly my fault, which is the reason why I was asking for advices to send OSC properly and efficiently. Here is a snippet of the journal when running the code:

{run: 79, time: 350.0, thread: :live_loop_sine}

├─ OSC -> localhost, 5000, /trig 0, []

├─ OSC -> localhost, 5000, /env_a 2000, []

├─ OSC -> localhost, 5000, /env_d 100, []

├─ OSC -> localhost, 5000, /env_s 1, []

├─ OSC -> localhost, 5000, /env_r 10, []

├─ OSC -> localhost, 5000, /trig 1, []

└─ OSC -> localhost, 5000, /note 59, []

Maybe a good workaround would be simply to rewrite everything using MIDI messages. :thinking:


Do you really mean to send what is essentially data as part of the OSC address?

eg osc "/env_a " + a.to_s
when a is 2000 is sending no data to address
"/env_a 2000"

or are you meaning to send
osc "/env_a",a.to_s
and then extract the data value sent (2000)?

It depends on how your max/msp patch is set up of course.
It seems a bit inefficient to have a separate osc address for every single data value.

Also, can your max/msp patch be set up to receive ALL the adsr data in one call. eg
osc "/adsr",a,d,s,r


In my patch, I’m using an external object from the CNMAT library that allows to route OSC messages using this particular format: /something datafollowing.

I was thinking that sending a bunch of them was okay. I will try to group all OSC informations concerning one synthesizer or sound device in one message, and format it later in Max.

My initial idea for separating the different messages was to keep the syntax as light as possible on the Sonic Pi side.


I’ve been working a bit on this project and now everything is fine. You were right @robin.newman. I’ve reworked my OSC messages to send every information in one message per synth:

define :simpleosc do |note, vel, a, d, s, r, cutoff, resonance, q, mix|
  use_osc "localhost", 5000
  osc note.to_s + " " + vel.to_s + " " +  a.to_s + " " + d.to_s + " " + s.to_s + " " + r.to_s + " " + cutoff.to_s + " " + resonance.to_s + " " + q.to_s + " " + mix.to_s

I’ve been able to synchronize my Max synthesizers with Sonic_Pi, and I’ve been playing for a while routing the audio back to Sonic Pi to mess the sound with the default effects.

Thanks for the suggestion.


Glad you got it going. I’d be interest in full details of the project on the max side once you have it finished.