Sonic Pi: Basics

I've been looking for a way to combine my programming skills with my musical background for a few years now. It wasn't until I started looking into the Raspberry Pi a few months ago that I found Sonic Pi, which is basically an IDE that lets you write code, specifically Ruby, to program sounds and create music. Very cool.

It's so cool that it comes pre-installed with the Raspbian operating system. So when I set up my Raspberry Pi, there it was. It's also available for other operating systems; I've been toying around with it on my MacBook.

I won't dig into the IDE's GUI since it's pretty self explanatory, but I do want to write about the basics of composing in Sonic Pi: writing notes, chords, and melodies, controlling the volume ("amplitude") and direction ("panning") of the sound output, and selecting basic sounds ("synths").

Playing Individual Notes

Sonic Pi makes it easy to play individual notes. You simply use the keyword play followed by a number. For example:

play 60

The number that follows the play keyword corresponds to the note that you want it to play. In this case, 60 is a C Natural. Specifically, it's probably the closest that Sonic Pi has to a Middle C.

Each individual number represents a musical half step. So if 60 is C Natural, then 61 represents C#:

play 61

D Natural is represented by 62:

play 62

And so on. You can also do microtones using decimals:

play 60.235

Different speakers and computers are capable of different things, but on my system the highest audible value is around 131. Honestly, this tone is kind of piercing and painful. On the opposite end of things, the lowest audible value is around 7, which is just a faint bassy blip. I have no idea what notes those are supposed to represent. I should also note, these were found just experimenting with the default beep synth. Different synths may have different audible ranges.

Playing Chords

Now that we know how to play individual notes, playing chords is just a matter of combining those individual notes and playing them together. For example, here is a pretty standard C Major chord:

play 60
play 64
play 67
play 72

And here is a C Minor (Natural) chord:

play 60
play 63
play 67
play 72

sleep and Melodies

By using the sleep keyword and a number, you can put space between notes; in this way you can produce a melody. Here is the C Major chord, broken up into a little arpeggio melody:

play 60
sleep 1
play 64
sleep 1
play 67
sleep 1
play 72

The number that follows the sleep keyword corresponds to a portion of the beat. If the tempo in the IDE is set to 60 beats per minute (60 bpm), then sleep 1 is a one beat or one second of space, sleep 0.5 is a half-beat or a half-second of space and 0.25 is a quarter-beat or a quarter-second of space:

play 60
sleep 1
play 64
sleep 0.5
play 67
sleep 0.25
play 72

We can also use sleep to put space between chords:

play 60
play 64
play 67
play 72

sleep 2.28

play 60
play 63
play 67
play 72

Volume (Amplitude)

You can control the volume, or amplitude of a note using the amp keyword, like so:

play 60, amp: 1

In Sonic Pi, an optional keyword like amp is referred to as an opt. You generally separate opts from the play directive (and other opts) with a comma, and they typically use a semicolon between the opt keyword and its value.

amp's default value is 1, so play 60 is the same as play 60, amp: 1.

amp: 0 represents silence:

play 60, amp: 0 ## No sound

You can go above 1 with values like amp: 2 or amp: 100, but Sonic Pi uses compression, and these greater values will likely clip and sound harsh. It's advised that you stick between 0 and 1, and use decimal values to achieve different volumes for different notes. Here is an example:

play 60
sleep 0.2
play 63
sleep 0.2
play 67, amp: 0.7

sleep 2

play 59, amp: 0.9
sleep 0.09
play 65, amp: 0.8
play 67, amp: 0.5

sleep 2

play 58
sleep 0.3
play 62, amp: 0.6
sleep 0.07
play 65, amp: 0.6

sleep 2

play 56
sleep 0.2
play 62,  amp: 0.7
sleep 0.1
play 65, amp: 0.7

Direction (Panning)

Another opt that's available is :pan, which controls the panning of a sound, or the directional output of a sound in stereo. Basically, this opt determines if the sound comes out of the left speaker, the right speaker, dead center, or somewhere in between.

pan: -1 represents a sound that is panned fully to the left, so it only comes out of the left speaker:

play 60, pan: -1

pan: 1 represents a sound that is panned fully to the right:

play 60, pan: 1

pan: 0 represents a sound that is panned in the center, so equally between left and right. This is the default value for the pan opt:

play 60, pan: 0

play 60, pan: 0 is the same as play 60.

Since the full range for this opt is between -1 and 1, values greater than 1 or less than -1 will throw an error. However, you can use decimals to fine tune where in the panning spectrum you want the sound to come out:

play 60, pan: -1
sleep 0.4
play 60, pan: -0.6
sleep 0.4
play 60, pan: -0.3
sleep 0.4
play 60, pan: 0
sleep 0.4
play 60, pan: 0.3
sleep 0.4
play 60, pan: 0.6
sleep 0.4
play 60, pan: 1

Different Sounds (Synths)

So far we've only been using the default synth in Sonic Pi. This synth's name is beep, but we haven't specified that anywhere. The use_synth opt allows you to specify which synth you want Sonic Pi to use to play a particular note.

Select a synth with use_synth then a colon, then the name of the synth. All notes that follow that command will use that synth until another synth is selected:

use_synth :blade
play 60
play 64
play 67
play 72

sleep 1.5

use_synth :prophet
play 60
play 63
play 67
play 72

You can also combine multiple synths at the same time:

use_synth :tb303
play 38
use_synth :dsaw
play 50
use_synth :prophet
play 57
sleep 1
use_synth :fm
play 55
use_synth :tb303
play 57

sleep 0.5
use_synth :fm
play 54
use_synth :tb303
play 62

Put It All Together

So let's take all of these basics and put them all together into something fun. Here's a bit of the Clock Town Melody from Majora's Mask, transposed into Sonic Pi:

play 69
sleep 0.5
play 81
sleep 0.2
play 80
sleep 0.2
play 78
sleep 0.2
play 76
sleep 0.2
play 78
sleep 0.6
play 74
sleep 0.6
play 76
sleep 0.5
play 71
sleep 0.2
play 76
sleep 0.2
play 74
sleep 0.2
play 71
sleep 0.2
play 74
sleep 0.4
play 76
sleep 0.2
play 73

I'm going to use amp to put some decrescendos on some of the descending runs:

play 69
sleep 0.5
play 81
sleep 0.2
play 80, amp: 0.6
sleep 0.2
play 78, amp: 0.5
sleep 0.2
play 76, amp: 0.4
sleep 0.2
play 78
sleep 0.6
play 74
sleep 0.6
play 76
sleep 0.5
play 71
sleep 0.2
play 76, amp: 0.6
sleep 0.2
play 74, amp: 0.5
sleep 0.2
play 71, amp: 0.4
sleep 0.2
play 74
sleep 0.4
play 76
sleep 0.2
play 73

Now I'll add some bass in, using the chipbass synth, set to a little bit lower amplitude, just to accent the root notes of the melody:

use_synth :chipbass
play 57, amp: 0.2

use_synth :beep
play 69
sleep 0.5
play 81
sleep 0.2
play 80, amp: 0.6
sleep 0.2
play 78, amp: 0.5
sleep 0.2
play 76, amp: 0.4
sleep 0.2

use_synth :chipbass
play 56, amp: 0.3

use_synth :beep
play 78
sleep 0.6
play 74
sleep 0.6
play 76

use_synth :chipbass
play 54, amp: 0.4

use_synth :beep
sleep 0.5
play 71
sleep 0.2
play 76, amp: 0.6
sleep 0.2
play 74, amp: 0.5
sleep 0.2
play 71, amp: 0.4
sleep 0.2
play 74

use_synth :chipbass
play 56, amp: 0.3

use_synth :beep
sleep 0.4
play 76
sleep 0.2
play 73

And just for a little bit of texture, I'll add in an ascending scale that uses the sine synth that pans from left to right as it ascends:

use_synth :chipbass
play 57, amp: 0.2

use_synth :sine
play 57, amp: 0.6, pan: -0.6

use_synth :beep
play 69
sleep 0.5
play 81
sleep 0.2
play 80, amp: 0.6
sleep 0.2
play 78, amp: 0.5
sleep 0.2
play 76, amp: 0.4
sleep 0.2

use_synth :chipbass
play 56, amp: 0.3

use_synth :sine
play 59, amp: 0.6, pan: -0.2

use_synth :beep
play 78
sleep 0.6
play 74
sleep 0.6
play 76

use_synth :chipbass
play 54, amp: 0.4

use_synth :sine
play 62, amp: 0.6, pan: 0.2

use_synth :beep
sleep 0.5
play 71
sleep 0.2
play 76, amp: 0.6
sleep 0.2
play 74, amp: 0.5
sleep 0.2
play 71, amp: 0.4
sleep 0.2
play 74

use_synth :chipbass
play 56, amp: 0.3

use_synth :sine
play 64, amp: 0.4, pan: 0.6

use_synth :beep
sleep 0.4
play 76
sleep 0.2
play 73

And there you have it. I hope you enjoyed this little Sonic Pi intro, I definitely had a lot of fun writing it and composing these examples. In the next few weeks I'll continue my exploration of Sonic Pi, so stay tuned!