In this month’s Sonic Pi tutorial we’re going to take a look at how you can start treating Sonic Pi like a real instrument. We therefore need to start thinking of code in a completely different way. Live coders think of code in a similar way to how violinists think of their bow. In fact, just like a violinist can apply various bowing techniques to create different sounds (long slow motions vs short fast hits) we will explore five of the basic live coding techniques that Sonic Pi enables. By the end of this article you’ll be able to start practicing for your own live coded performances.
The first tip to live coding with Sonic Pi is to start using the shortcuts. For example, instead of wasting valuable time reaching for the mouse, moving it over to the Run button and clicking, you can simply press alt
and r
at the same time which is much faster and keeps your fingers at the keyboard ready for the next edit. You can find out the shortcuts for the main buttons at the top by hovering the mouse over them. See section 10.2 of the built-in tutorial for the full list of shortcuts.
When performing, one fun thing to do is to add a bit of flair with your arm motion when hitting shortcuts. For example, it’s often good to communicate to the audience when you’re about to make a change - so embellish your movement when hitting alt-r
just like a guitarist would do when hitting a big power chord.
Now you can trigger code instantly with the keyboard, you can instantly apply this skill for our second technique which is to layer your sounds manually. Instead of ‘composing’ using lots of calls to play
, and sample
separated by calls to sleep
we will have one call to play
which we will manually trigger using alt-r
. Let’s try it. Type the following code into a fresh buffer:
synth :tb303, note: :e2 - 0, release: 12, cutoff: 90
Now, hit Run
and whilst the sound is playing, modify the code in order to drop down four notes by changing it to the following:
synth :tb303, note: :e2 - 4, release: 12, cutoff: 90
Now, hit Run
again, to hear both sounds playing at the same time. This is because Sonic Pi’s Run
button doesn’t wait for any previous code to finish, but instead starts the code running at the same time. This means you can easily layer lots of sounds manually with minor or major modifications between each trigger. For example, try changing both the note:
and the cutoff:
opts and then re-trigger.
You can also try this technique with long abstract samples. For example:
sample :ambi_lunar_land, rate: 1
Try starting the sample off, and then progressively halving the rate:
opt between hitting Run
from 1
to 0.5
to 0.25
to 0.125
and then even try some negative values such as -0.5
. Layer the sounds together and see where you can take it. Finally, try adding some FX.
When performing, working with simple lines of code in this way means that an audience new to Sonic Pi has a good chance to follow what you’re doing and relate the code that they can read to the sounds they are hearing.
When working with more rhythmic music, it can often be hard to manually trigger everything and keep good time. Instead, it is often better to use a live_loop
. This provides repetition for your code whilst also giving the ability to edit the code for the next time round the loop. They also will run at the same time as other live_loop
s which means you can layer them together both with each other and manual code triggers. Take a look at section 9.2 of the built-in tutorial for more information about working with live loops.
When performing, remember to make use of live_loop
’s sync:
opt to allow you to recover from accidental runtime mistakes which stop the live loop running due to an error. If you already have the sync:
opt pointing to another valid live_loop
, then you can quickly fix the error and re-run the code to re-start things without missing a beat.
One of Sonic Pi’s best kept secrets is that it has a main mixer through which all sound flows. This mixer has both a low pass filter and a high pass filter built-in, so you can easily perform global modifications to the sound. The main mixer’s functionality can be accessed via the fn set_mixer_control!
. For example, whilst some code is running and making sound, enter this into a spare buffer and hit Run
:
set_mixer_control! lpf: 50
After you run this code, all existing and new sounds will have a low pass filter applied to them and will therefore sound more muffled. Note that this means that the new mixer values stick until they are changed again. However, if you want, you can always reset the mixer back to its default state with reset_mixer!
. Some of the currently supported opts are: pre_amp:
, lpf:
hpf:
, and amp:
. For the full list, see the built-in docs for set_mixer_control!
.
Use the mixer’s *_slide
opts to slide one or many opts values over time. For example, to slowly slide the mixer’s low pass filter down from the current value to 30, use the following:
set_mixer_control! lpf_slide: 16, lpf: 30
You can then slide quickly back to a high value with:
set_mixer_control! lpf_slide: 1, lpf: 130
When performing, it’s often useful to keep a buffer free for working with the mixer like this.
The most important technique for live coding is practice. The most common attribute across professional musicians of all kinds is that they practice playing with their instruments - often for many hours a day. Practice is just as important for a live coder as a guitarist. Practice allows your fingers to memorise certain patterns and common edits so you can type and work with them more fluently. Practice also gives you opportunities to explore new sounds and code constructs.
When performing, you’ll find the more practice you do, the easier it will be for you to relax into the gig. Practice will also give you a wealth of experience to draw from. This can help you understand which kinds of modifications will be interesting and also work well with the current sounds.
This month, instead of giving you a final example that combines all the things discussed, let’s part by setting down a challenge. See if you can spend a week practicing one of these ideas every day. For example, one day practice manual triggers, the next do some basic live_loop
work and the following day play around with the main mixer. Then repeat. Don’t worry if things feel slow and clunky at first - just keep practicing and before you know it you’ll be live coding for a real audience.