Hello, I’m new here and I want to share with you this implementation I made to handle drums inside a Sonic Pi track, in order to understand if this can be a good solution
I liked the idea I found around the web (mostly here and here) to map the beats inside an array, to emulate somehow the common grids used by real drum machines and simplify the creation of beats.
I also wanted to have something that gives the possibility to manage in easy way the evolution of the beats during the track, so I used sync messages to register the measures number in order to create conditions inside the loop based on it.
Here an example of a beat that has a fill every forth measure:
use_bpm 120
# pattern: is an array of 1s and 0s. 1 = beat played, 0 = no beat
# drum_sample: the sample you want to play
define :play_drum_pattern do |pattern, drum_sample|
# Every time this function is called a new thread is created.
# The name of the thread is the tick number, in order to be always new
# (I come up with this solution after some issues with timing)
in_thread(name: tick.to_s) do
pattern.each do |p|
if p == 1 then
sample drum_sample
end
sleep 0.25
end
# at the end, the thread is stopped to free the resources (don't know if necessary anyway)
stop
end
end
live_loop :drums do
# loop synced with :measure
# :measures carries the current measure of the loop, so we can use it to control the behaviour
measure = (sync :measure)[0]
puts measure
if (measure % 4 != 0) then
# pattern played for every measure but the last
kick = [1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0]
snare = [0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0]
play_drum_pattern(kick, :drum_heavy_kick)
play_drum_pattern(snare, :drum_snare_soft)
else
# pattern played for the last measure (the fill)
kick = [1,0,0,1, 0,0,0,1, 1,0,1,0, 0,0,0,0]
snare = [0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0]
open_hat = [0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0]
play_drum_pattern(kick, :drum_heavy_kick)
play_drum_pattern(snare, :drum_snare_soft)
play_drum_pattern(open_hat, :drum_cymbal_open)
end
end
measure = 1;
live_loop :conductor do
cue :beat
# every 4 bars, a :measure message is sent (notifying the beginning of a new measure)
if (tick % 4 == 0) then
cue :measure, measure
measure += 1
end
sleep 1
end
What do you think?