I thought I’d put a note on here referencing one of my early questions about how best to schedule chord changes within a piece. The idea is to have a controlling loop that sets up the ‘current chord’ and broadcasts it to other loops that do something with it (sequences, arpeggio, bass notes etc.) Now I understand the model a bit better, I’m worked out some coding patterns. I can see there might be lots of ways to do this, so if there’s a better one out there I’d be interested to see it. I need to use this a lot with my music, so it’s important to get a nice, robust way of doing it, and doesn’t rely on e.g. the order of the loops.
Original attempts are in here, where I didn’t quite get it Help with understanding cues/syncs
The key thing is that all the events (sets, gets and plays) have to be neatly placed in time. In this example, the ‘contoller’ loop uses a couple of sleeps to place the ‘set’ in the middle of the bar. So when the cue is issued, the ‘playchord’ loop can safely ‘get’ the current chord on beat 1. During that bar, the controller loop sets up the next chord ready for the ‘playchord’ to pick up next bar. And round it goes. The first bar is silent which represents the count-in, as Sam describes it.
EDIT: I should say that these snippets are in 4/4 so 1 beat = a 1/4 note (crotchet)
use_bpm 60 chord1 = [:C4, :Eb4,:G4] chord2 = [:F4, :A4, :C5] seq = [chord1, chord2].ring live_loop "controller" do #Set the chord in the middle of the bar sleep 2 set :currentchord, seq.tick sleep 2 #Cue the bar on the beat 1 of the 'next bar'. #Also play the bass note of the chord, down an octave. cue "bar" play seq.look-12, amp: 0.5 end live_loop "playchord", sync: "/cue/bar" do #On beat 1, pick up the current chord, that was set #on the previous bar's beat 3 c = get[:currentchord] #Play the chord 4.times do play_chord c, amp: 0.5 sleep 1 end end
An alternative way of doing the same thing, which I prefer now is using time_warp to place the ‘set’ at a specific beat in the bar…
live_loop "controller" do #Set the chord on beat 3 time_warp 3 do set :currentchord, seq.tick end sleep 4 cue "bar" end
That opens the door to more complex patterns, for instance if there’s a loop with a phrase that’s longer than a bar, but you want it to pick up the chord change as it goes. Or more than one chord per bar - same kind of thing.
In this example, the ‘playchord’ loop is two bars long, and is playing fast 32nd notes. The ‘contoller’ loop sets up the new chord just a 64th note before the new bar starts. As long as the spacing is set right (and it might vary from piece to piece) then the loops will always get the right chord when they need it.
I’ve put in a hihat ticking away on 8th notes so it’s easier to hear what’s going on.
live_loop "controller" do #Set the chord just 1/64 note before the end of the bar. time_warp 4 - 4.0/64 do puts "setting chord to " + seq.tick.to_s set :currentchord, seq.look end sleep 4 puts "cueing the bar" cue "bar" play seq.look-12, amp: 0.5 end live_loop "hihat", sync: "/cue/bar" do #hihat 8th notes sample :drum_cymbal_closed, amp: 0.1 sleep 4.0/8 end live_loop "playchord", sync: "/cue/bar" do #Two bars worth of 32nd note chords #Play the chord throughout the bar, and pick #up the chord change as you go. 64.times do c = get[:currentchord] play_chord c, amp: 0.1, sustain: 1.0/16, release: 0.0 sleep 4.0/32 end end