Sonic Pi - sample slicing

By Russell Barnes. Posted

In his latest musical coding piece, Sonic Pi creator Sam Aaron shows us how to slice and dice audio samples

Way back in part three of this Sonic Pi series, we looked at how to loop, stretch, and filter one of the most famous drum breaks of all time: the Amen Break. In this tutorial, we’re going to take this one step further and learn how to slice it up, shuffle the slices, and glue it back together in a completely new order. If that sounds a bit crazy to you, don’t worry: it will all become clear and you’ll soon master a powerful new tool for your live‑coded sets.

The full article can be found in The MagPi 45 and was written by Sam Aaron

Sound as data

Before we get started, let’s just take a brief moment to understand how to work with samples. By now, you have all hopefully played with Sonic Pi’s powerful sampler. If not, there’s no time like the present! Boot up your Raspberry Pi, launch Sonic Pi from the Programming menu, type the following line into a fresh buffer, and then hit the Run button to hear a pre-recorded drum beat:

sample :loop_amen

A recording of a sound is simply represented as data: lots of numbers between -1 and 1, which represent the peaks and troughs of the sound wave (see the boxout to the right for more information). If we play those numbers back in order, we get the original sound. However, what’s to stop us from playing them back in a different order and creating a new sound?

How are samples actually recorded?

It’s actually pretty simple once you understand the basic physics of sound. When you make a sound - for example, by hitting a drum –the noise travels through the air in a similar fashion to the way the surface of a lake ripples when you throw a pebble into it. When those ripples reach your ears, your eardrum moves sympathetically and converts those movements into the sound you hear. If we wish to record and play back the sound, we therefore need a way of capturing, storing, and reproducing those ripples. One way is to use a microphone, which acts like an eardrum and moves back and forth as the sound ripples hit it. The microphone then converts its position into a tiny electric signal, which is then measured many times a second. These measurements are then represented as a series of numbers between -1 and 1.

If we were to plot a visualisation of the sound, it would be a simple graph of data with time on the x axis and microphone/speaker position as a value between -1 and 1 on the y axis. You can see an example of such a graph at the top of the image above.

Playing part of a sample

So, how do we code Sonic Pi to play a sample back in a different order? To answer this question, we need to take a look at the start: and finish: opts for sample. These let us control the start and finish positions of our playback of the numbers which represent the sound.

The values for both of these opts are represented as a number between 0 and 1, where 0 represents the start of the sample and 1 is the end.So, to play the first half of the Amen Break, we just need to specify a finish: of 0.5:

sample :loop_amen, finish: 0.5

We can add in a start: value to play an even smaller section of the sample:

sample :loop_amen, start: 0.25, finish: 0.5

For fun, you can even have the finish: opt’s value set before start:, in which case it will play the section backwards:

sample :loop_amen, start: 0.5, finish: 0.25

Reordering sample playback

Now that we know that a sample is simply a list of numbers that can be played back in any order, and also how to play a specific part of a sample, we can start having fun playing a sample back in the ‘wrong’ order.

Let’s take our Amen Break and chop it up into eight equally sized slices, and then shuffle those pieces around to create a new drum break.

Take another look at the image at the top of this page: at the top, A) represents the graph of our original sample data. Chopping it into eight slices gives us B) – notice that we’ve given each slice a different colour to help distinguish them. You can see each slice’s start and finish values at the top. Finally, C) is one possible reordering of the slices. We can then play this back to create a new beat. Take a look at the code to do this:

live_loop :beat_slicer do
  slice_idx = rand_i(8)
  slice_size = 0.125
  s = slice_idx * slice_size
  f = s + slice_size
  sample :loop_amen, start: s, finish: f
  sleep sample_duration :loop_amen, start: s, finish: f
end

Let’s analyse this piece of code to see precisely what is going on at each stage…

  1. We choose a random slice to play, which should be a random number between 0 and 7 (remember that we start counting at 0). Sonic Pi has a handy function for exactly this: randi(8). We then store this random slice index in the variable sliceidx.

  2. We define our slicesize, which is 1 divided by the number of slices (8), or 0.125. We need this to convert our sliceidx into a slice starting position, as a value between 0 and 1. For example, the slice with index 3 starts three slices into the sample: 3 * 0.125, or 0.375.

  3. We calculate the start position s by multiplying the sliceidx by the slicesize.

  4. We calculate the finish position f by adding the slice_size to the start position s.

  5. We can now play the slice by plugging in the s and f values into the start: and finish: opts for sample.

  6. Before we play the next slice, we need to know how long to sleep, which should be the duration of the sample slice.  Luckily, Sonic Pi has us covered with sampleduration, which accepts all the same opts as sample and simply returns the duration. So, by passing sampleduration to our start: and finish: opts, we can find out the duration of a single slice.

  7. We wrap all of this code in a live_loop so that we continue to pick new random slices to play.

    Bringing it all together

    Let’s combine everything we’ve seen so far into a final example which demonstrates how we can take a similar approach to combine randomly sliced beats with some bass to create the start of an interesting track. Now it’s your turn: take this code as a starting point and see if you can create something new...

    liveloop :slicedamen do
      n = 8
      s = line(0, 1, steps: n).choose
      f = s + (1.0 / n)
      sample :loopamen, beatstretch: 2, start: s, finish: f
      sleep 2.0 / n
    end

liveloop :acidbass do
  with_fx :reverb, room: 1, reps: 32, amp: 0.6 do
    tick
    n = (octs :e0, 3).look - (knit 0, 3 * 8, -4, 3 * 8).look
    co = rrand(70, 110)
    synth :beep, note: n + 36, release: 0.1, wave: 0, cutoff: co
    synth :tb303, note: n, release: 0.2, wave: 0, cutoff: co
    sleep (ring 0.125, 0.25).look
  end
end

From The MagPi store

Subscribe

Subscribe to the newsletter

Get every issue delivered directly to your inbox and keep up to date with the latest news, offers, events, and more.