Experimental syncing of 4 Sonic Pi computers

I have been having a play at syncing 4 sonic pi computers together, using OSC messages to perform the sync. I find that the OSC signals enable syncing quite easily, but there can be a problem is the Sonic Pi computers are different especially if they have different audio setups (as was the case here) and they can they have quite different audio latencies. However, it is possible to sync them to the machine with the worst audio latency by employing some time warp in the other computers with smaller latency. The good thing is that latency is a fixed value and so can be compensated for.
The four computers I used were:
1 a Mac Book Pro which acted as the ā€œconductorā€ and sent out the sync signals.
2 an RPI 3 with a Pisound audio card
3 an old iMac repurposed as a LInux Machine running Ubuntu 17.04
4 an RPi 3 in a Pi-topCEED with a PiPulse audio card (HiFi Berry guts)

The code in the MacBookPro was this

set :bpm,20
set :f,0
live_loop :speed do
  b=get(:bpm)
  if b<220 and get(:f)==0
    b+=10
  else
    set :f,1
  end
  if get(:f)==1 and b>20
    b-=10
  else
    set :f,0
  end
  use_bpm b
  set :bpm,b
  sleep 0.5
end

live_loop :sendsync do
  bpm=get(:bpm)
  use_real_time
  use_bpm bpm
  osc_send "192.168.1.190",4559,"/sync",bpm
  osc_send "192.168.1.234",4559,"/sync2",bpm
  osc_send "192.168.1.238",4559,"/sync3",bpm
  sleep 0.25
end

The code in the 1st RPi was this

live_loop :n2 do
  use_real_time
  b = sync "/osc/sync2"
 #set time_warp to delay note to match  greatest latency. use rt so time not affected by bpm
  time_warp  rt(0.18) do 
    use_bpm b[0)
    play scale(:e3,:minor_pentatonic).tick,release: 0.25
  end
end

The code for the Ubuntu Sonic PI was this

live_loop :n1 do
  use_real_time
  b = sync "/osc/sync"
 #set time_warp to delay note to match  greatest latency. use rt so time not affected by bpm
  time_warp  rt(0.18) do 
    use_bpm b[0)
    play scale(:e4,:minor_pentatonic).tick,release: 0.25
  end
end

The code for the pi-topCEED (with the greatest latency) was this

live_loop :n3 do
  use_real_time
  b = sync "/osc/sync3"
  use_bpm b[0)
  play scale(:e5,:minor_pentatonic).tick,release: 0.25
end

Start the three slave machines running, then start the MBP "conductor"
You should adjust the time_warp settings so all notes play together. To set up start with the live_loop
:speed commented out in the MBP code and you can adjust the notes so they sound together.
You can then uncomment the MPB code and re-run the ā€œconductorā€ machine and the tempo of thenotes
will be speeded up and slowed down.
You should be able to extend the technique for a larger number of machines. I am investigating whether it is possible to send a ā€œbroadcastā€ OSC message which would only need one sync, but Iā€™m not sure if this is possible yet.

A video of the program in action is shown here:

3 Likes

This is glorious, and very useful example code.

Did you get anywhere with broadcast message sending? Iā€™m hoping to use Sonic Pi to control a network of individual musical robots, but at the moment Iā€™m struggling to get broadcast OSC messages to work. Right now I suspect the issue is with my (python-osc based) target. I can get things working with specific IP addresses, but not with broadcast. However, before I faff about trying to fix that itā€™d be good to know if Sonic Pi can send broadcast messages anyway!

I havenā€™t pursued broadcast messages further yet, but I suspect it will be quite involved.

I was afraid of that. Iā€™ve just managed to get broadcast listening working from a Python script (no idea how - the only change I recall making in the last hour was to restart my Mac. Huh.); I have broadcast sending working from Python; and I have broadcast listening working on a Wemos D1 mini (Arduino/wifi) controller.

However, osc_send <broadcast ip>, <port>, <message> doesnā€™t appear to send anything from Sonic Pi. Gnats. I guess I could write a little Python script which bounces messages back out to broadcast; thatā€™s not tidy, but it is a workaround in my case.

Thanks for the speedy reply, appreciated!

I have spent this afternoon looking at this. Sonic Pi osc code would need altering to allow use of broadcast. However I have written a broadcast helper in which SP sends an osc message to a script with parameters and the script then sends the same parameters in a broadcast which any SP computer on the same local network can pick up. If the original sending SP computer then responds to this too the it can be used to sync machines together. Seems to work ok. When I have tested further I will publish it.

Excellent. Iā€™ll take someone elseā€™s code over my own any day, there are invariably fewer bugs!

I think I have the other components of my system working (or at least proof-of-concept, but thatā€™s the same, right?), so the individual-host-to-broadcast bridge is the missing piece. Very happy to, err, ā€˜testā€™ code for you. :slight_smile:

Iā€™m updating this topic because I try to achieve something similar. @robin.newman, how would you proceed to synchronize eight computers, each one being controlled by an active player? Do I always need to use a computer as a slave for incoming messages?

Does this thread help?

I donā€™t think so. In your dispositive, you are using one computer as a master to control every other computers running Sonic-Pi. What I would like to do is much more an improvisational setup. I need every computer to be referring to the same clock so that everytime someone launch a sound, itā€™s syncing with some kind of master-clock and never drifts away from the general ensemble tempo.

You can use this broadcast technique to send sync messages to several machines to start the doing something at the same time. These could be sent at different times as they play or used to sync metronome loops on each computer.
EDIT you can also send information for changes in tempo if required.

Iā€™ll try to test it as soon as I can. Indeed, this may be everything I need for this improvisational piece. Thanks Robin!

Hey @robin.newman
Iā€™m trying something similar here, but failing currently.
I have two mac books on my local network.
I know the local IP addresses of the two macs (letā€™s say 192.168.1.1, 192.168.1.2)

Iā€™m trying to send from mac 1 with osc_send "192.168.1.2", 4560, "/sync" in a live_loop. This works.
But the other end is not receiving anything. I suspect the OSC port is not open on the receiving mac.
Do you know how I can open that port, maybe only restricted to the OSC protocol ?

Just tested sending from one mac to another and back again here and it works fine. What version of SP are you using? Do you see anything in the cues log of the receiving mac? Have you switched on the Send/Receive remote OSC in the IO Prefs on the two macs?

Silly me, I had experimented with OSC before, but only locally, and completely forgot about that aspect when doing this over the network ! Thanks :wink:

1 Like