This is a piece to play along with the guitar (sorry, no live-coding here ).
The architecture is such that a central control loop is orchestrating 3 instruments. Just like a band on stage with a band leader.
I found it a bit tricky to use both sleep and sync in a live_loop and avoid race conditions. Maybe I overlooked a simpler solution here?
### Jigsaw Puzzle Blues
### Fleetwood Mac / Peter Green / Danny Kirwan / Joe Venuti and Adrian Rollini
use_debug false
load_samples [:drum_cymbal_open, :drum_cymbal_closed, :perc_snap,
:drum_heavy_kick, :drum_snare_hard]
use_bpm 100
###############
# control loop
live_loop :control, auto_cue: false, delay: 0.2 do
t = tick
case t
when 0
set :run, 1
set :s_drums, 1
set :drum_pattern, 3
when 1
set :drum_pattern, 1
set :s_piano, 1
set :s_bass, 1
when 26
set :drum_pattern, 0
when 27
set :drum_pattern, 1
when 41
set :drum_pattern, 2
set :run, 0 # send stop signal to all loops
when 42
stop
end
# sync other loops
cue :bar, t
sleep 4
end
###################
# instrument loops
# drum loop
live_loop :my_drums, auto_cue: false, sync: :s_drums do
sync :bar
drum_kit(get :drum_pattern)
stop if (get :run) == 0
end
# bass loop
my_bass_line = [] # definition see below
with_synth :fm do
use_synth_defaults attack: 0.01, sustain: 0.5, release: 0.1, divisor: 2, amp: 0.9
live_loop :my_bass, auto_cue: false, sync: :s_bass do
m = my_bass_line.tick
rep = m[:rep] ? m[:rep] : 1
rep.times do
sync :bar
my_play_pattern(m)
end
stop if (get :run) == 0
end
end
# piano loop
my_chords = [] # definition see below
with_synth :piano do
use_synth_defaults amp: 1.5, hard: 0.6, release: 1.2
live_loop :my_piano, auto_cue: false, sync: :s_piano do
m = my_chords.tick
rep = m[:rep] ? m[:rep] : 1
rep.times do
sync :bar
my_play_pattern(m)
end
stop if (get :run) == 0
end
end
##############
# definitions
define :drum_kit do |pattern|
# 3.99 beats per pattern
# ensures drum loop is always slightly ahead of cue :bar
case pattern
when 0
sleep 3.99
when 1
sample :drum_heavy_kick, amp: 2
sleep 0.5
sample :drum_cymbal_closed
sleep 0.5
sample :drum_cymbal_closed
sleep 0.5
sample :drum_cymbal_closed
sleep 0.5
sample :drum_snare_hard
sleep 0.5
sample :drum_cymbal_closed
sleep 0.5
sample :drum_cymbal_closed
sleep 0.5
sample :drum_cymbal_open, attack: 0.01, sustain: 0.1, release: 0.6, amp: 0.7
sleep 0.49
when 2
sample :drum_splash_soft, attack: 0.05, release: 4, amp: 0.6
sleep 3.99
when 3
sample :perc_snap, amp: 0.4
sleep 1
sample :perc_snap, amp: 0.4
sleep 1
sample :perc_snap, amp: 0.4
sleep 1
sample :perc_snap, amp: 0.4
sleep 0.99
end
end
define :my_play_pattern do |m|
# plays pattern m with total length slightly less than 4 beats
tick_reset(:notes)
max_t = m[:n].length - 1
m[:n].each do |n|
t = tick(:notes)
rel = m[:rel] ? m[:rel][t] : nil
sus = m[:sus] ? m[:sus][t] : nil
play n, sustain: sus, release: rel
if t == max_t
# last note/chord has been played
# ensures instrument loops are always slightly ahead of cue :bar
sleep 0.99*m[:t][t]
else
sleep m[:t][t]
end
end
end
my_chords = [
# part 1
{n: (knit chord(:D3, :m, invert: 1), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:Bb2, :dom7), 2, chord(:A2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:D3, :m, invert: 1), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:Bb2, :dom7), 2, chord(:A2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:D3, :m, invert: 1), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:Bb2, :dom7), 2, chord(:A2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:D3, :m, invert: 1), 4), t: [1, 1, 1, 1]},
{n: [chord(:Eb3, :M), chord(:E3, :M)], t: [2, 2], rel: [2, 2]},
# part 2 (t=7)
{n: (knit chord(:A2, :M, invert: 1), 4), t: [1, 1, 1, 1], rep: 3},
{n: (knit chord(:A2, :M, invert: 1), 3), t: [1, 0.5, 2.5], rel: [1, 0.5, 2.5]},
# part 3 (t=9)
{n: (knit chord(:D3, '9'), 4), t: [1, 1, 1, 1], rep: 2},
{n: (knit chord(:A2, :M, invert: 1), 4), t: [1, 1, 1, 1], rep: 2},
{n: (knit chord(:E3, '9'), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:F3, '9'), 1, chord(:E3, '9'), 2), t: [2, 1, 1], rel: [2, 1.2, 1.2]},
{n: [chord(:A2, :M), chord(:A2, :dom7, invert: 2), chord(:D3, :M) ,chord(:D3, :m, invert: 2)], t: [1, 1, 1, 1]},
{n: [chord(:A3, :M), chord(:B3, :M)], t: [2, 2], rel: [2, 2]},
# part 4 (t=15)
{n: (knit chord(:E3, :M, invert: 1), 4), t: [1, 1, 1, 1], rep: 3},
{n: (knit chord(:E3, :M, invert: 1), 3), t: [1, 0.5, 2.5], rel: [1, 0.5, 2.5]},
# part 5 (t=17)
{n: (knit chord(:A2, :M, invert: 1), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:Bb2, :dim7, num_octaves: 2), 2), t: [2, 2], rel: [2, 2]},
{n: (knit chord(:E3, :M, invert: 1), 4), t: [1, 1, 1, 1], rep: 2},
{n: (knit chord(:B2, '9', invert: 2), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:C3, '9', invert: 2), 2, chord(:B2, '9', invert: 2), 2), t: [1, 1, 1, 1]},
{n: [chord(:E3, :M), chord(:E3, :dom7), chord(:A3, :M) ,chord(:A3, :m)], t: [1, 1, 1, 1]},
{n: (knit chord(:E3, :M), 2, chord(:Fs3, :M), 2), t: [1, 1, 1, 1]},
# part 6 (t=24)
{n: (knit chord(:B2, :m, invert: 2), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:G2, :dom7), 2, chord(:Fs2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:B2, :m, invert: 2), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:G2, :dom7), 2, chord(:Fs2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:B2, :m, invert: 2), 4), t: [1, 1, 1, 1]},
{n: (knit chord(:G2, :dom7), 2, chord(:Fs2, :dom7), 2), t: [1, 1, 1, 1]},
{n: (knit chord(:B2, :m, invert: 2), 4), t: [1, 1, 1, 1]},
{n: [chord(:G2, :dom7), chord(:Fs2, :dom7)], t: [2, 2], rel: [2, 2]},
{n: [chord(:B2, :m, invert: 2)], t: [4], rel: [4]},
]
my_bass_line = [
{n: [:D3, :D3, :D3, :D3], t: [1, 1, 1, 1]},
{n: [:Bb2, :Bb2, :A2, :A2], t: [1, 1, 1, 1]},
{n: [:D3, :D3, :D3, :D3], t: [1, 1, 1, 1]},
{n: [:Bb2, :Bb2, :A2, :A2], t: [1, 1, 1, 1]},
{n: [:D3, :D3, :D3, :D3], t: [1, 1, 1, 1]},
{n: [:Bb2, :Bb2, :A2, :A2], t: [1, 1, 1, 1]},
{n: [:D3, :D3, :D3, :D3], t: [1, 1, 1, 1]},
{n: [:Eb3, :E3], t: [2, 2], sus: [1.5, 1.5], rel: [0.5, 0.5]},
#
{n: [:A2, :Fs2, :E2, :E2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:A2, :Fs2, :E2, :Fs2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:A2, :B2, :C3, :Db3], t: [1, 1, 1, 1]},
{n: [:D3, :Eb3, :A3], t: [1, 0.5, 2.5], sus: [nil, 0.3, nil], rel: [1, 0.2, 2.5]},
#
{n: [:D3, :D3, :D3, :D3], t: [1, 1, 1, 1], rep: 2},
{n: [:A2, :Fs2, :E2, :E2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:A2, :Fs2, :E2, :A2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E2, :E2, :E2, :E2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:F2, :F2, :E2, :E2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:A2, :Db3, :D3, :Eb3], t: [1, 1, 1, 1]},
{n: [:E3, :B2], t: [2, 2], sus: [1.5, 1.5], rel: [0.5, 0.5]},
#
{n: [:E3, :Db3, :B2, :Db3], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E3, :Db3, :B2, :Db3], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E2, :Gb2, :G2, :Ab2], t: [1, 1, 1, 1]},
{n: [:A2, :Bb2, :E3], t: [1, 0.5, 2.5], sus: [nil, 0.3, nil], rel: [1, 0.2, 2.5]},
#
{n: [:A2, :Fs2, :E2, :E2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:Ab2, :Ab2, :Bb2, :B2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E3, :Db3, :B2, :Db3], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E3, :Db3, :B2, :Db3], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:B2, :B2, :B2, :B2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:C3, :C3, :B2, :B2], t: [1.5, 0.5, 1.5, 0.5], sus: [nil, 0.2, nil, 0.2], rel: [1, 0.05, 1, 0.05]},
{n: [:E2, :Ab2, :A2, :Bb2], t: [1, 1, 1, 1]},
{n: [:B2, :r, :Gb2], t: [1, 1.5, 1.5], rel: [1, 1.5, 1.5]},
#
{n: [:B2, :B2, :B2, :B2], t: [1, 1, 1, 1]},
{n: [:G2, :G2, :Gb2, :Gb2], t: [1, 1, 1, 1]},
{n: [:B2, :B2, :B2, :B2], t: [1, 1, 1, 1]},
{n: [:G2, :G2, :Gb2, :Gb2], t: [1, 1, 1, 1]},
{n: [:B2, :B2, :B2, :B2], t: [1, 1, 1, 1]},
{n: [:G2, :G2, :Gb2, :Gb2], t: [1, 1, 1, 1]},
{n: [:B2, :B2, :B2, :B2], t: [1, 1, 1, 1]},
{n: [:G2, :Gb2], t: [2, 2], sus: [1.5, 1.5], rel: [0.5, 0.5]},
{n: [:B2], t: [4], sus: [2], rel: [1.5]},
]