Hi all, this is my first postable SP patch. As I’ve seen others do, using the Tabla sample set seems like an obvious target. Firstly… this will not be authentic Tabla music! It’s more an exercise in the high level control.
I wanted to play with the idea of the ebb and flow in music. Something I’ve heard in live Indian music performances… moving from time of calm to periods of frenetic activity.
I hope to use the core building blocks in other creations over time.
Comments on coding, ideas and improvements welcome.
Thanks,
Frank.
# Tabla Improv
#
# Tabla and melodic line, that play from defined patterns and with a changing feel.
#
# Frank Taylor <spi ! lieder.me.uk
# [<pattern>, <freq>] The higher the freq the more likely it is to be chosen.
#
# Order the patterns in increasing spiciness.
pf = [[[1], 2],
[[2, 2], 3],
[[2, 4, 4], 4],
[[4, 4, 2], 4],
[[4, 2, 4], 4],
[[4, 4, 4, 4], 4],
[[8, 8, 8, 8, 4, 4], 3],
[[16, 16, 8, 8, 16, 16, 8, 8, 4], 3],
[[16, 16, 16, 16, 16, 16, 16, 16, 4, 16, 16, 16, 16], 3],
[[3, 3, 3], 1],
[[3, 3, 6, 6], 1],
[[6, 6, 3, 6, 6], 1],
[[5, 5, 5, 5, 5], 0]]
patterns = []
pf.each do |p, n|
n.times do
patterns << p
end
end
# Return a biased rand between 0..1.
# s - start of the focussed section
# e - end of the focussed section
# f - probability to take from the focussed section
#
# E.g. biased_rand(0.5, 0.1, 1.0) -> 0.4...0.6
# biased_rand(0.5, 0.5, 0.5) -> 0..1, but 50% of the time it will choose a number between 0.4..0.6
#
define :biased_rand do |s, e, f|
if rand > f
return rand
else
return rand(e - s) + s
end
end
# Similar to biased_rand, but chooses elements from a list based on focussed section.
# Focus is still specified in 0..1 - fraction of the list.
#
define :biased_choose do |s, e, f, l|
br = biased_rand(s, e, f)
s = l.length
l[s * br]
end
define :choose_pattern do |f, l|
(s, e, f) = f
biased_choose(s, e, f, l)
end
feeling_calm = [0.0, 0.25, 1.0]
feeling_mid = [0.0, 0.5, 0.8]
feeling_hot = [0.5, 1.0, 0.5]
feeling_blistering = [0.5, 1.0, 1.0]
# [<feeling>, <freq>]
feeling_prefs = [[feeling_calm, 2],
[feeling_mid, 3],
[feeling_hot, 2],
[feeling_blistering, 1]]
feelings = []
feeling_prefs.each do |p, n|
n.times do
feelings << p
end
end
notes = scale :c2, :indian, num_octaves: 3
note = :c2
feeling = feeling_calm
live_loop :changer do
sleep 32
s = [:c2, :f2, :g2].choose
notes = scale s, [:hindu, :indian, :dorian].choose, num_octaves: 3
feeling = feelings.choose
puts "Feeling: ", feeling, "New scale: ", s
end
live_loop :tabla do
p = choose_pattern(feeling, patterns)
ts = 0.0
p.each do |f|
puts "Pattern: ", p, feeling
l = 1.0/f
s = (sample_names :tabla).choose
sample s
ts = ts + l
sleep l
end
ds = (1-ts)
puts "Delay sleep: ", ds
sleep ds
end
live_loop :melody do
slow = 2.0
with_synth :pluck do
p = choose_pattern(feeling, patterns)
tl = 0.0
p.each do |f|
interval = [0, 0, 0, 1, 1, 1, -1, -1, -1, 2, -2, 3, -3, 4, -4].choose
note = note + interval
l = slow / f
tl = tl + l
puts "Melody: ", p, interval, note, l, notes[note], feeling
play notes[note], sustain: l, amp: 0.75
sleep l
end
ds = (slow - tl)
sleep ds
end
end