Not being able to play the drums and also not having much experience programming them, I need a high-level way of creating rhythms. So let's use Sonic Pi to make the machine take care of the hard part.
The Basic Idea
Here is what we are going to do: Let's randomly chop up the first bar of the Amen Break and assemble it into new patterns.
We are going to use 8 slices - one for each cymbal hit.
First Chops
So here is the code to create the 8 slices outlined above.
slices = 8 # number of slices
slice = 0 # try slices 0 to 7
start = slice * 1.0/slices
sample :loop_amen, start: start, finish: start + 1.0/slices
Trying this you will get a nice kick for slice 0 and 1 - and a double kick for slice 5. The nice snare hits are - as expected - slice 2 and 6.
Randomized Chops
As a next step let's assemble a whole bar from 8 randomly selected slices.
With use_sample_bpm one beat is defined as the length of one of our slices. So we just can do sleep 1 to wait for the next beat.
Whatever the random generator comes up with - we need to hear it again to make it feel like actual music. Repetition legitimizes. To make the bar repeat, we wrap it into a live loop and reset the random seed at the beginning of each bar. Thus the random generator will come up with the same numbers each time.
slices = 8
use_sample_bpm :loop_amen, finish: 1.0/slices
live_loop :drummer do
use_random_seed 0
slices.times do
start = (rrand_i 0, slices - 1) * 1.0/slices
sample :loop_amen, start: start, finish: start + 1.0/slices
sleep 1
end
end
Composing with Seeds
This is a steady beat you can already play along with. But let's go one step further and compose beats by picking random seeds. Each bar gets's a number representing what is played. Here a simple 8-bar loop based on seed 21 that throws in a break on bar 4 and 8.
As you will have noticed, we also added a way to set the tempo of the drummer.
Picking the good bars
Trying out random numbers is fun, but I am especially interested in bars starting with a kick. These are slice 0 and 1. Let's list the first few of these:
slices = 8
(0..100).each do |seed|
use_random_seed seed
start = (rrand_i 0, slices - 1)
if start == 0.0 || start == 1.0
puts seed
end
end
So apparently I should try the seeds 3, 4, 8, 15, 21 …
More Things to Try
To wrap things up, here are a few ideas, what to explore when playing with this code:
Try 2, 4 and 16 slices.
Try a different :loop_*, not just the Amen Break.
Come up with a generative way to pick random seeds.
Write scripts to search for seeds producing bars with specific properties you are interested in.
Add rests.
Maybe even try crossfading chunks.
Meta
This blog has been very quiet, but at 38C3 I stumbled into a Sonic Pi workshop. This is where I pieced together the idea above and was reminded how much fun this is. More stuff has been in the pipeline for ages and will hopefully see the light of day soon.
Live coding music with Sonic Pi and toying around with hardware mini synths such as Pocket Operators are both fun - but a very different kind of fun. But there should be a way to bring both together, right?
If you are reading this, chances are that you own more than one Pocket Operator. In this case you will be aware, that you can daisy chain these using a clock signal generated by the first PO in the chain. So wouldn't it be handy to generate such a clock signal using Sonic Pi?
The Click
Using a click to synchronize synthesizer units is basically done since the dawn of time - way before digital interconnection with MIDI. Even though this tutorial is exclusively talking about Pocket Operators, this will also work with a wide variety of other hardware providing a clock in.
Each PO has six sync modes, that provide a different configuration of the two input and output channels. For testing let’s use SY5 , that accepts mono/sync as input and also provides both as outputs. The clock input and output is always on the left stereo channel.
The Sync mode can be selected by repeatedly pressing chord + bpm.
To access SY2-SY5 a cable needs to be plugged into the input jack on the left side.
flowchart LR
CS:::hidden-- clock -->L
AS:::hidden-- mono -->R
subgraph Pocket Operator
L:::left~~~L2[L]:::left
R:::right~~~R2[R]:::right
end
L2-- clock -->L3:::hidden
R2-- mono -->R3:::hidden
classDef hidden display: none;
classDef left fill:#fff,stroke:#000,color:#000;
classDef right fill:#ff0000,stroke:#000,color:#fff;
So how does this clock signal look like? The first thing we can do is plugging in a pair of headphones an listen to this sound not meant for human ears.
There it is: A pulse on each eighth note. This is interesting considering the fact that the PO provides sixteenth note resolution. When turning up the swing parameter of the sequencer you can even hear the clock starting to shuffle a bit.
Set the swing by pressing bpm and turning the A knob.
The clock ticks sounds like some very short pulse with steep flanks. So let’s record the signal to learn more about the shape of a click. Any recording program will do. To separate the two stereo channels coming out of the mini headphone jack, you can use a stereo splitter cable that provides two mono headphone jacks. The left channel is the white one.
So there are the peeks we are looking for:
The flanks are as steep as it gets and the wave does not go below 0. So we are looking at a very primitive, unipolar digital protocol.
Making our own clock
So it’s time to fire up Sonic Pi to get our hands dirty. We are going to need some sharp click noise on each eighth note. A first, naïve try could look like this:
live_loop :clock do
sample :drum_snare_hard, amp: 3
sleep 0.5
end
Sonic Pi counts in quarter notes. So playing a loud snare sound each half quarter note should do what we want — if the snare sample is able to trigger a clock tick. Let's connect the Computer and the PO to find out.
flowchart LR
subgraph Computer
L00[L]:::hidden~~~L0[L]:::left
R00[R]:::hidden~~~R0[R]:::right
end
L0-- clock -->L
subgraph Pocket Operator
L:::left~~~L2[L]:::left
R:::right~~~R2[R]:::right
end
classDef hidden display: none;
classDef left fill:#fff,stroke:#000,color:#000;
classDef right fill:#ff0000,stroke:#000,color:#fff;
So how does it perform? Our little snare clock is indeed able to make the Pocket Operator play the next two sixteenth notes of its pattern, but it doesn’t do this reliably. Cranking up the volume of the computer seems to help getting fewer dropped ticks, but we still don’t get a full measure without an issue.
So we now have to do some serious engineering™️ and try out a bunch of other built-in samples. Since we are using a live_loop, cycling through samples is pretty convenient.
As it turns out,:bd_808 , the 808 kick, triggers perfectly. Somewhat surprising, but once more the 808 proves to be the superior drum machine.
So here is the updated code to generate a synthesize clock signal:
use_bpm 80
live_loop :clock do
sample :bd_808, amp: 3
sleep 0.5
end
If it doesn’t work in your setup, make sure, that the output volume of your audio interface is high enough, but not clipping. Actually listening to the clock signal can help to figure out what might be wrong.
Playing together
To wrap things up, let’s finally add a simple drum pattern generated by Sonic Pi. The PO will beep and burp perfectly in sync with this beat.
use_bpm 80
# Eighth note clock pulse on left channel
live_loop :clock do
sample :bd_808, amp: 3, pan: -1
sleep 0.5
end
# Some drum pattern on right channel
drums = [
:drum_bass_hard, nil,
:drum_snare_hard, nil,
:drum_bass_hard, :drum_bass_hard,
:drum_snare_hard, nil,
].ring
live_loop :drums do
sync :clock
sample drums.tick, pan: 1
end
As you will notice, the :clock loop is fully panned to the left side and the :drums loop to the right. And since the drum loop is synced to the clock loop, we do not need to sleep.
To join the two audio sources, some kind of mixer needs to be added to the setup.
flowchart LR
subgraph Computer
L00[L]:::hidden~~~L0[L]:::left
R00[R]:::hidden~~~R0[R]:::right
end
subgraph Pocket Operator
L:::left~~~L2[L]:::left
R:::right~~~R2[R]:::right
end
subgraph Mixer
1~~~L4[L]:::left
2~~~R4[R]:::right
end
L0-- clock -->L
R2-- mono -->1
R0-- mono -->2
classDef hidden display: none;
classDef left fill:#fff,stroke:#000,color:#000;
classDef right fill:#ff0000,stroke:#000,color:#fff;
Aaaand it’s done. That wasn’t that hard. We are now able to run Sonic Pi and one or more Pocket Operators in sync. Time to jam — until we take this to the next level next time.
This is a revised version of an article posted on Medium in 2021.