Sonic Pi: Samples

We continue with our journey into the world of Sonic Pi today, this time looking into samples. A sample is just a prerecorded audio clip. Sonic Pi comes with lots of samples available by default. You can trigger a sample using the sample keyword followed by the name of the sample you want to play, preceded by a colon.

sample :elec_blip

Samples work just like notes in most regards. For example, you can space them out with sleep and layer them by triggering the samples at the same time. Or you can combine them with regular synth notes:

sample :elec_blip
sleep 1.2

play 67
sleep 1.2

use_synth :bass_foundation

play 64
sample :glitch_perc1
sleep 1.2

play 49

The audio output of samples can also be changed using amp and pan.

sample :elec_blip, pan: -1
sleep 1

use_synth :bass_foundation
play 62, attack: 0.4, release: 0.8
sample :elec_blip, pan: -0.3
sleep 1

use_synth :bass_highend
play 50, amp: 0.6, attack: 1, release: 0.2
sample :elec_blip, pan: 0.3
sleep 1

sample :elec_blip, pan: 1

Rate (Stretch, Squash, and Reverse)

You can change the length and pitch at which a sample is played using the rate opt:

sample :ambi_glass_rub, rate: 1

The default value for the rate opt is 1, so sample :ambi_glass_rub is the same as sample :ambi_glass_rub, rate: 1.

We can stretch a sample by using a rate value less than 1:

sample :ambi_glass_rub, rate: 0.5

rate: 0.5 doubles the length of time that the sample takes to play as well as plays it an octave lower.

Alternatively, we can squash a sample by using a rate value greater than 1:

sample :ambi_glass_rub, rate: 2

rate: 2 cuts the length of time that the sample takes to play in half as well as plays it an octave higher.

Finally, we can reverse a sample by using a negative value for the rate:

sample :ambi_glass_rub, rate: -1

Here's a fun drum sample played backward and forward at various rates:

sample :loop_amen, rate: -0.5
sleep 3.5
sample :loop_amen, rate: 0.5
sleep 3.5
sample :loop_amen, rate: -1
sleep 1.67
sample :loop_amen, rate: 1
sleep 1.67
sample :loop_amen, rate: -1.5
sleep 1.15
sample :loop_amen, rate: 1.5

Envelopes

Unsurprisingly, we can also apply the ADSR envelope opts to adjust the attack, decay, sustain, and release of our sample playback, but it works a little differently than regularly played notes.

Where you can fully extend a note using the ADSR envelope, you can only reduce the amplitude and length of a played sample. Using lengthy attack, decay, sustain, or release will not make the sample playback longer. In fact, you can never extend a sample's length using an envelope. The sample will stop playing either when the envelope has completed its four phases or the sample has finished playing, whichever comes first.

This can be a little bit confusing to figure out, so let's break it down. Here's a nice, long sample to play with:

sample :loop_3d_printer

We can fade in over 1 beat using the attack opt:

sample :loop_3d_printer, attack: 1

We can also set the amplitude that the attack phase attacks toward using the attack_level opt:

sample :loop_3d_printer, attack: 1, attack_level: 0.4

We can also adjust the decay and decay_level:

sample :loop_3d_printer, attack: 1, attack_level: 0.4, decay: 1, decay_level: 0.8

Sustain works differently though. Where for a regular synth note playback, sustain's default value is 0, for a sample, sustain's default is the calculated time it takes to play the rest of the sample. More on this in a second.

Release is also a little different in a sample than in a synth; where a synth's release default value is 1, for a sample the release default value is 0. You can hear this when you compare this:

sample :loop_3d_printer

...with this:

sample :loop_3d_printer, release: 1

So what was this about the sustain taking on a calculated duration for samples? Let's dive in there.

First, let's think about the length of the :loop_3d_printer sample we've been playing with. You can see that with:

print sample_duration :loop_3d_printer
# expected result: 7.959183673469388

We can see that :loop_3d_printer is basically 8 beats long, which is 8 seconds at 60 bpm. If we add release: 1, it fades out the sample for the last second of playback. If no other opts are present, this means the other 6.959183673469388 are the duration of the sustain.

sample :loop_3d_printer, release: 1

And further, if we use attack: 1 to fade in for one second at the beginning of the sample playback, the sustain is further reduced to 5.959183673469388.

sample :loop_3d_printer, attack: 1, release: 1

However, we can also adjust the sustain manually by giving it a value. If that value is less than the automatically calculated sustain value, it will cut the playback time down.

sample :loop_3d_printer, attack: 1, sustain: 3, release: 1

But we can also drop the sustain to 0, allowing us to get some very short, punchy samples:

sample :loop_3d_printer, attack: 1, sustain: 0, release: 1

You can use this trick effectively with drum samples. Compare this :drum_snare_hard sample with its defaults:

sample :drum_snare_hard

...to this one with sustain: 0 and release: 0.2:

sample :drum_snare_hard, sustain: 0, release: 0.2

This second one is much tighter and cleaner sounding!

Partial Samples

We can also use specific portions of a sample. We can specify a starting position with the start opt and an ending position with the finish opt. In this way we don't have to start at the beginning of the sound or finish at the end of the sound.

sample :loop_3d_printer, start: 0.3, finish: 0.4

Naturally this can be combined with rate, envelope, and other opts and techniques to give you a huge range of options for building beats and music.

External Samples

You can also use any WAV, AIFF, OGG, OGA, or FLAC files on your computer as samples by passing in a file path. If, for example, you had a file named Kasha.wav on your MacBook's desktop that you wanted to sample, you could do with the following:

sample "/Users/joey/Desktop/Kasha.wav"

All of the same opts will work for this sample!

sample "/Users/joey/Desktop/Kasha.wav", start: 0.6, finish: 0.7