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) 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?