Live-coding online with Sonic Pi: code music and perform over the internet with a Raspberry Pi

By Russell Barnes. Posted

Originally created as an interactive and fun instructional tool for teaching both programming and music, Sonic Pi is also a very powerful tool for creating sophisticated live-coding online performances as well as algorithmic compositions, all by writing code.

This tutorial was written by Chris Bush and Daria Tsaregorodtseva. It first appeared in The MagPi #61.

Sonic Pi is perfect for people who love to code and love to create music, even if they can’t play an instrument. Best of all, Sonic Pi is included in Raspbian, making it easy to get started with coding your own musical creations on your Raspberry Pi. Wouldn’t it be great if you could share those creations over the internet? In this project, we’ll show you how using live-coding.

Live-coding online: Sharing Sonic Pi compositions

For this project, we will assume that you are at least somewhat familiar with the Sonic Pi GUI and its coding language, and you have at least tried some simple code or played with the many examples included with Sonic Pi. If not, check out the Essentials book, Code Music with Sonic Pi, for some excellent beginners tutorials.

Our goal for this project is to give you a way to go beyond playing your Sonic Pi compositions for whoever happens to be in the room with you. We’ll show how you can share your Sonic Pi coding creations with your friends, family, and fans over the internet, so they can listen to your musical masterpieces virtually anywhere in the world.

To do that, we have created a couple of simple Python programs that can interface with Sonic Pi, and communicate with each other over the internet, using a lightweight IoT messaging protocol called MQTT.

MQTT is a publish/subscribe messaging transport protocol (in case you are wondering, MQTT originally stood for MQ Telemetry Transport, but is no longer officially an acronym). It was designed to be very lightweight, simple and easy to implement and is most commonly used for communication in machine-to-machine and Internet of Things applications.

The main aspect in the publish/subscribe pattern is the decoupling of publisher and receiver, where the publisher and subscriber don’t know about the existence of one another, don’t have to run at the same time, and are not halted during publishing or receiving. A third component, a broker, is known by both parties: this filters and distributes all incoming messages by subject/topic.

For this project, we have created two Python programs that use the Eclipse Paho MQTT Python client library to implement an MQTT publisher and subscriber. The programs use the public Eclipse IoT MQTT broker at iot.eclipse.org to exchange messages.

The publisher program, sp-mqtt-publisher.py, is used to read a file that contains Sonic Pi code, and publish it to the Eclipse IoT MQTT broker. The subscriber program, sp-mqtt-subscriber.py, is then used to retrieve the Sonic Pi code from the broker and send it to Sonic Pi for playback.

 Save the composition from the Sonic Pi buffer to a file, so the Python publisher program can read it and publish it to the MQTT broker

Getting started with live-coding online

To get started, first download the two included Python programs, sp-mqtt-publisher.py and sp-mqtt-subscriber.py, and save them on your Raspberry Pi.

Next, you will need to install the Python MQTT client library from the Eclipse Paho project. This is easy with the Python package manager, called pip, which is included with Raspbian Jessie. Open a Terminal window on your Raspberry Pi and enter the following command:

sudo pip install paho-mqtt

Finally, you will need a way to send Sonic Pi code directly to the Sonic Pi synth server, rather than typing it into the Sonic Pi GUI. Currently, there is no built-in capability to play your compositions on Sonic Pi from the command line – although that is apparently planned for Sonic Pi 3. Consequently, we are using sonic-pi-cli, written by Nick Johnstone. This provides a very simple command-line interface, written in Ruby, for interacting with Sonic Pi. Luckily, Ruby also comes as part of the Raspbian Jessie distribution, and sonic-pi-cli should work just fine with it. From the Terminal window, enter the following command:

sudo gem install sonic-pi-cli

This will install a Ruby script, called sonic_pi, in the /usr/local/bin directory on your Raspberry Pi, where it can easily be called from the Python code.

 The saved file will be published to the MQTT broker

Try out live-coding

Once you have these components installed, it’s time to try everything out. First, let’s make sure that the sonic_pi Ruby program is working. Start by opening Sonic Pi. Once the Sonic Pi GUI is running, open a Terminal window and enter the following command:

sonicpi "sample :loopbreakbeat"

You should hear the breakbeat sample loop that is included with Sonic Pi.

With that working, now it’s time to try a simple live-coding performance over the internet, using the two Python programs provided. With Sonic Pi open, copy one of the code examples included with Sonic Pi into a buffer. Then, using the Save button, save the buffer to a file. In the screenshot, we have chosen the tron-bikes example because, well – who doesn't like the sound of Tron light cycles?

Once the buffer is saved to a file, run the sp-mqtt-publisher.py program from a Terminal window. You will need to include two command-line arguments when you run the program. The first specifies the MQTT topic name that you will publish to. Choose something that is simple and likely to be unique. The second argument is the name of the code file in which you saved the buffer from Sonic Pi. For example, you might enter the following command:

python sp-mqtt-publisher.py saulpimon tron-bike.txt

The publisher program will read the contents of the code file named on the command line, and publish it to the Eclipse IoT MQTT broker under the provided topic name. The publisher program runs an infinite loop, and every ten seconds will re-publish the code to the MQTT broker. With each iteration of the loop, it will check to see if the code file has been updated and, if so, it will re-read the file before re-publishing, so that the most recent version of the live-coding composition is published to the MQTT broker.

Now, of course, this isn’t much of a live-coding performance without listeners, right? If you have a couple of friends who want to help, you can have them install the required components as described in the ‘Getting started’ section, and run the Python subscriber program, sp-mqtt-subscriber.py, to retrieve the published code from the MQTT broker and play it using Sonic Pi on their own Raspberry Pi. Or, if you like, you can run the subscriber program yourself on the same Raspberry Pi that you used to publish the code. To run the subscriber program, first be sure you have installed the Paho MQTT client and the sonic_pi Ruby script as described above. Next, open Sonic Pi and run the Python subscriber program, being sure to specify the same topic name that was used with the publisher above as a command-line argument. For example, enter the following command:

python sp-mqtt-subscriber.py saulpimon

The subscriber program will connect to the Eclipse IoT MQTT broker and retrieve messages that are published to the topic named on the command line. When a message is received, the subscriber program then calls the sonicpi Ruby script, passing the retrieved message as data. The sonicpi Ruby script connects to Sonic Pi and sends it the code, which will then be played. Don’t worry when you don’t see the retrieved code in the Sonic Pi GUI on the Raspberry Pi on which you’re running the subscriber program. The sonic_pi Ruby script doesn’t interact with the Sonic Pi GUI at all. Instead, it connects directly to the Sonic Pi synth server to send the code.

You are now ready to start sharing your live-coding masterpieces over the internet. Simply make changes to the Sonic Pi code as you would with any other live-coding performance, and save the buffer to a file as described above. The simple Python programs and MQTT will handle the rest, for you and your faithful listeners.

import paho.mqtt.client as paho
import time, os, sys

topic = sys.argv[1]
filename = sys.argv[2]

host = "iot.eclipse.org"
client = paho.Client()
client.connect(host, 1883)

timestamp1 =  -10
while True:
    timestamp2 = os.path.getmtime(filename)
    if timestamp1 != timestamp2:
        with open(filename, 'r') as myfile:
            filedata=myfile.read()
        timestamp1 = timestamp2
    client.publish(topic, filedata)
    time.sleep(10)
import paho.mqtt.client as paho
import sys, subprocess

def on_message(client, userdata, message):
    pipe = subprocess.Popen("sonic_pi", stdin=subprocess.PIPE, shell=True)
    pipe.communicate(input=message.payload)
    print(str(message.payload.decode("UTF-8")))

def on_disconnect(client, userdata, rc):
    subprocess.call("sonic_pi stop", shell=True)

topic = sys.argv[1]
host = "iot.eclipse.org"
client = paho.Client()
client.connect(host, 1883)
client.subscribe(topic, 0)

client.on_message = on_message
client.on_disconnect = on_disconnect

print("Press Ctrl-C to stop...")
try:
    client.loop_forever()
except KeyboardInterrupt:
    client.loop_stop()
    client.disconnect()

 

From The MagPi store

Subscribe