Hi everyone!
I’m starting a generative EDM project, and I was looking for the simplest way to represent complex rhythms. This is what I found:
- My starting point was something I observed in @Nechoj’s work:
x---x---x---x---
, where eachx
represents a hit. - I wanted to represent amplitude information, so I replaced the
x
s with digits 0-9:8---6---8---6---
. (A similar approach can be found in @mlange’s work — see the discussion.) - My “aha” moment was when I realised that simply by factoring the length of the string into the calculation of duration, I could always represent a rhythm in its simplest form: e.g.
8686
=8---6---8---6---
. A simple calculation can determine the spacing of a pattern based on its number of characters.
At last, I have a simple way to represent arbitrary tuplets! No genre is beyond reach!
Here is a simple cross-genre demo. The most complex rhythm is in the closed hi-hats. It involves a triplet. I think the best way to understand the implementation is to take a look.
use_bpm 116
live_loop :kick do
pattern = "8----8--".ring
3.times do
pattern.length.times do
sample :bd_haus, amp: (pattern[look].to_f / 9) if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
end
tick_reset
pattern = "8".ring
pattern.length.times do
sample :bd_haus, amp: (pattern[look].to_f / 9) if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
end
live_loop :snare do
pattern = "-6-6".ring
pattern.length.times do
sample :sn_zome, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
pattern = "---16--4----6---".ring
pattern.length.times do
sample :sn_zome, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
end
live_loop :closedHiHat do
pattern = "8--6--6--2468--6--6--6--".ring
pattern.length.times do
sample :drum_cymbal_closed, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
pattern = "86668666".ring
pattern.length.times do
sample :drum_cymbal_closed, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
pattern = "8--6--6--2468--6--6--6--".ring
pattern.length.times do
sample :drum_cymbal_closed, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
pattern = "8666866-".ring
pattern.length.times do
sample :drum_cymbal_closed, amp: (pattern[look].to_f / 9), sustain: 0.2 if (pattern[tick] != "-")
sleep 4/pattern.length.to_f
end
tick_reset
end
It’s so simple that someone may have already (cough) beat me to it.
EDIT: According to @Eli, this intuitive approach may have been around for at least a decade. It was discussed in the Google Group that preceded our present forum. I hope this more recent post may save some people the trouble of having to search.
Best,
d0lfyn