Three Sonic Pi computers play different parts together

A piece by Sameul Scheidt called Galliard Battaglia is here arranged for three computers each hosting Sonic PI. The two main trumpet parts are each played on a separate machine and the third plays the remaining two accompanying Parts. One machine acts conductor sending OSC cues to the other two to start them playing. Suitable delays are included to allow for different audio latencies in the separate machines. I first used this technique on a network of BBC computers over 30 years ago, playing a movement of a Brandenburg Concerto with parts allocated to different machines, using a hacked version of the the program TMS (The Music System). It gives me a buzz to do it again here, albeit with a more modest piece.

PROBABLY BEST TO WATCH THE VIDEO FIRST

I coded the piece for Sonic Pi 2.5 in April 2015, but have now updated it (mainly changes in sample selection) to run on Sonic Pi 3.0.1 I’ve run it on Mac and Rpi 3. Basically each computer has the same program, but unwanted parts are commented out if not being played by a machine. In the case of the Mac the data for the unplayed parts are also removed, as the file is too long to run from a Sonic Pi buffer on a Mac, where it requires use of run_file eg
run_file "path-to-file"
A simple osc message is sent from the “conductor” machine to each of the other two to start them running. As the machines have different audio latency, two small time delays are incorporated so that they all sound together. Sync is ONLY at the start of the pice, but I don;t detect any significant drift apart of the separate machines during the duration of the piece.

The complete file with all 4 parts which plays on a single machine is here

The extra bits I used on each machines are as follow:
On the pitopCEED with pitiopPULSE speaker, which had the greatest latency I added
use_osc "ip.address.of.conductor.machine",4559
at the start of the program, and
sync "/osc/go"
just after the line set_bpm(165)

The same lines were added to the second Pi (running with a pisound card)
The conducting machine, a MacBookPro had the following code added just after the line
set_bpm(165)

use_osc "localhost",4559
osc_send "192.168.1.238",4559,"/go" #start RPi with greatest audio latency
sleep 0.21 #delay: adjust for audio sync
osc_send "192.168.1.234",4559,"/go" #start Pi with PiSound card
sleep 0.07
osc "/go" #start this machine
sync "/osc/go"

Also, so that it would run on a Mac, I deleted the parts data for n3 n4 and d3 d4 from this machine so that the shortened code ran OK.
Finally for each of the three machines I commended out the play section for unwanted parts in the section at the end of the program where these are played. For example for the Mac which played the second part only:

with_fx :reverb,room: 0.6,mix: 0.4 do #add some reverb
  with_fx :level do |amp| #amp controlled by settings in plct function
    in_thread do
      plct(amp,a,as,ad,s,1)
    end
    ##| in_thread do
    ##|   plarray(path,i[0][0],i[0][1],n1,d1,0,0.7,0,-0.8) #trumpet I
    ##| end
    #     in_thread do
    plarray(path,i[0][0],i[0][1],n2,d2,0,0.7,0,0.8) #trumpet II
  end
  #     in_thread do
  #       plarray(i[path,1][0],i[1][1],n3,d3,0,0.2,0,0) #trombone I
  #     end
  #     plarray(path,i[2][0],i[2][1],n4,d4,0,0.2,0,0) #trombone II
  #   end
end

Finally apologies to @samaaron I have updated the program, but only partially. It still makes use of global variables, reflecting the state of the early SP 2.5 for which it was written. It also uses techniques pertaining to that time, when I was less versed in coding, and when SP was less developed. One of these days I may revise it properly :grinning:

A video of the machines playing is here

2 Likes