Sonic Pi Orchestra

Spurred on by recent questions on this thread, I decided to look again at getting an improved mechanism for syncing Sonic Pi computers together so that they can play in an orchestra or band together. I looked at the possibility of using broadcast OSC messages, but Sonic Pi cannot produce these without some hacking of the built in osc code which is quite finely tuned and critical to the operation of Sonic Pi, both internally and externally. Instead I hit on the idea of building a separate python script which could receive an OSC message from Sonic Pi but then resend it immediately as a broadcast OSC message which could be picked up by any other instance of Sonic Pi running on the same local network.
After playing around with this for most of yesterday I came up with a script which seems to work nicely, and today I have modified various pieces of music to make use of the system.
Basically it is best to run it on your main Sonic Pi computer and send an OSC message addressed to “/triggerBroadcast” to port 8000 (can be changed) on “localhost” with up to 6 (arbitrary choice) parameters in the message. The python script script then immediately generates another OSC message with address “/broadcast” containing the same data, which it sends to the local network broadcast address (in my case 192.168.1.255) with destination port 4559. This can them be received by any Sonic Pi computer on the local network.

I have used four different computers, a Macbook, an iMac, a Raspberry Pi3 and a very ancient old iMac converted to running Sonic Pi 3.2dev on Ubuntu. The master computer (my Macbook) sent messages to the python script for each part and the first parameter in the message consisted of the part number. Each receiving Sonic Pi has an identical live_loop which can then filter out separate parts according to this part number, and so different machines can play different parts which are all synchronised together.

This is demonstrated in the video below

In this example there are 9 separate parts to the music. I assigned parts 1 and 2 to channel 1, parts 3 and 4 to channel 2 parts 5 and 6 to channel 3 and parts 7 and 8 to channel 4, each of these channels being serviced by a live_loop on the four available computers. In addition I left the base part on channel 9, and duplicated the receiving live_loop on the fourth computer assigning it to process broadcast data on channel 9, so this computer in fact processed 3 parts all together. However by doing this I could adjust its volume for part 9 separately.

A second method of operation can be used when playing a round on several computers. In this case, each computer produces its own sounds, and the broadcast signal is merely used to synchronise the start of each tune, with one computer taking on the additional role of conductor.
by default the python script runs without the need for any input data (using defaults of localhost port 8000 for input and the network broadcast address 192.168.1.255 with port 4559 (the cue port for Sonic Pi) as output. However these can be over-ridden with arguments on startup. If the actual ip address of the host computer is used instead of localhost then other computers on the network can send a directed “/triggerBroadcast” to the script and this can in turn be broadcast to all the others. I used this to let the last computer in the round sequence (which I called the “finisher”) send a broadcast to all the other computers causing their programs to be stopped.

The script is on my gist site at

I will add later some example Sonic Pi programs illustrating in more detail how to utilise it, but basically all you need to know is shown in the example below:

On the master Sonic Pi machine, run the script in a terminal window using python3 broadcastOSC.py
From Sonic Pi on that computer communicate with it using

use_osc "localhost",8000
sp=1 #this computer "number". Others will be sp-2, sp=3 etc
bpm=120
use_bpm bpm
live_loop :testSend do
  osc "/triggerBroadcast",1,note(:c4),1,bpm,"tri",0.5
  sleep 1
  osc "/triggerBroadcast",2,note(:e4),1,bpm,"saw",0
  sleep 1
  osc "/triggerBroadcast",3,note(:g4),1,bpm,"pulse",-0.5
  sleep 1
end

live_loop :pl do
  use_real_time
  b= sync "/osc*/broadcast"
  if b[0]==1 #check if the right channel
    use_synth b[4]
    use_bpm b[3] #set bpm
    #rests come up as "nil": ignore them, i.e. play nothing
    play b[1],sustain: b[2]*0.9,release: b[2]*0.1,amp: 0.5,pan: b[5] if b[1]!="nil" #allows for rests
  end
end

Other machines just need the live_loop :pl and will have different sp values set to play parts 2 and 3.

4 Likes

Nice work! One day I’ll get around to testing a setup like this.
Who knows, maybe eventually we’ll even figure out a way to handle it internally :slight_smile: :crossed_fingers:

A new video showing a 6 machine Sonic Pi orchestra is here

1 Like

Excellent! Many thanks, Robin - I’ll test this for my own particular/peculiar circumstances later in the week.

Amazing! Thanks for all you do!

@robin.newman this looks good - could it be adapted to convert incoming OSC to MIDI? This would be lightweight alternative to my using SPi to do that. Can python send MIDI? And I mean with some robust libraries that aren’t going to disappear :slight_smile:

Ref Sonic Pi + Volca = Good

I didn’t think of sending to the broadcast address. I’m sure that’s going to be useful in some way - I’ll have to think

I haven’t used python with midi, but a quick google shows there are libraries available eg here

Thanks, yes it says “There are probably about ten different python packages out there that accomplish some part of this goal…” hmm looks like ‘linux fun’ :slight_smile: Looks like it’s the same story for Ruby.

Seem a bit overkill to use SPi just for this task, but the advantage of it not being a homebrew is strong. Makes me think that it would be great if you could run Spi without the SuperCollider tackle, it could be more like a dedicated controller. Let’s give that to Sam as an idea, I’m sure he’d love that :smile:

Now, in a ideal world, you’ll write back saying - of course you can do that with the command line switch…

One day hopefully… :slight_smile:

I can see you raising your eyes to heaven. Are these users never happy? :scream:

Other people must have seen SPi’s amazing potential as a controller - with many more possibilities than the hardware controllers out there. I’m sure I’m playing catch up, sorry