Skip to content

Commit

Permalink
An implementation of Bjorklund's algorithm applied to rhythm.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Voorhis committed Nov 16, 2008
1 parent e1ecfe6 commit 3b7d85e
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions examples/euclid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# An implementation of Bjorklund's algorithm applied to rhythm.
# Inspired by http://ruinwesen.com/blog?id=216

require 'music'

include Music

module Euclid
module_function
def euclid(k, n)
bjorklund Array.new(k, [true]) + Array.new(n - k, [false])
end

def bjorklund(seqs)
real, rem = split_rem(seqs)
if rem.size <= 1
(real + rem).flatten
else
bjorklund(interleave(real, rem))
end
end

def split_rem(seq)
rem, real = seq.partition { |x| x == seq.last }
if rem.size == real.size
return seq, []
else
return real, rem
end
end

def interleave(list1, list2)
res = []
l1 = list1.dup
l2 = list2.dup
until l1.empty? && l2.empty?
e1 = l1.shift || []
e2 = l2.shift || []
res.push(e1 + e2)
end
res
end
end

def cresc(factor, score)
group(score,
:velocity => env { |v0, ph|
v1 = (v0 + ph * ((v0 * factor) - v0)).round # Linear interpolation
v1.clip(0..127) })
end

def kick(*args)
n(35, *args)
end

def snare(*args)
n(38, *args)
end

def rhythm(k, n)
bits = Euclid.euclid(k, n)
s(bits.map { |pulse| pulse ? kick(SN) : r(SN) }) * 2
end

def tick
(r & snare(1)) * 2
end

def score
ks = rhythm(3, 8) & rhythm(7, 8) & rhythm(5, 8) & rhythm(7, 8)
ss = tick * 4
ks | ss
end

SMFWriter.new(:tempo => 136).
track(score, :name => 'Euclidean Etude').
save('euclid')

0 comments on commit 3b7d85e

Please sign in to comment.