I enjoyed the recent post by @perpetual_monday and have been playing around with it. It is a great bit of code to experiment with, and I ended up with the piece below, where I added note arpeggios to the rhythm, altered the tempo for each section and generally had a lot of fun.
#Steve Reich's clapping patterns with arpeggios
#coded by Robin Newman, based on program by perpetual_monday
#see https://in-thread.sonic-pi.net/t/steve-reichs-clapping-music/2940
use_debug false #remove clutter from log
define :klist do |low,high,num,rpt| #creates a knitted ring of bmp values
#low,high = random number limits, num= number of sections in list, rpt= knit repeats
outlist=[]
(num-1).times do
outlist << (knit rrand_i(low,high),rpt)
end
outlist << (knit high+10,rpt) # add final item at bpm high+10
return outlist.flatten #remove nested [ ]
end
use_random_seed 6148 #changes "random selections"
use_synth_defaults release: 0.125,amp: 0.6,mod_phase: 0.0625
clappervol=1.2
# How many times to play each pattern before clapper two shifts it by one beat
bars_per_pattern = 4
#bpm will be adjustged at random for each pattern section in range 45-55 (with last pattern at 65)
with_fx :reverb, room: 0.6,mix: 0.7 do #add some reverb
2.times do |i| #play twice with differnt note offsets but same rhythmic pattern
#select pattern for each iteration
#two different clapping rhythms. - means rest, numbers are note offsets in hex
clapping_rhythm = ['5c0-55-c-05-','047-cc-7-40-'][i].to_s #i selects which rhythm pattern to use
#select starting note offset for each pattern se tion ªdiffernt one for each of the 2 iterations
shiftpat= [[5,12,0,5,12,0,5,12,0,5,12,0,5],[0,4,7,12,7,4,0,4,7,12,7,4,0]][i]
shifts = 0 #used to shift pattern of 2nd part relative to first one.
bpmlist=klist 45,55,shiftpat.length,bars_per_pattern #setup list of bpm for each bar
puts bpmlist #print list
puts bpmlist[-1],bpmlist.length #check last value (should be 65) and length
# Cycle through the rhythm pattern:
# Once for each beat in the rhythm,
# Repeated number of times specified in `bars_per_pattern`
((1 + clapping_rhythm.length) * bars_per_pattern).times do |bars|
use_bpm bpmlist.tick #get next bpm (each value repeated "bars-per-pattern" times
# Play through one bar of the rhythm
(clapping_rhythm.length).times do |clapper_one|
use_synth (ring :mod_tri,:mod_dsaw,:mod_pulse,:mod_fm)[shifts] #vary the synth
# Use modulo operator so we can treat the string characters like a ring and wraparound
clapper_two = (clapper_one + shifts) % clapping_rhythm.length
v1=clapping_rhythm[clapper_one]
if v1 != '-' then #play clap and calculated note
n1=("0x"+v1).to_i(base=16) #note offset in hex. convert to decimal.
puts ("0x"+v1).to_i(base=16),current_bpm,bars #print diagnostic info
## in next section can uncomment four if statements to vary pattern and note interplay
sample :elec_plip,pan: -1,amp: clappervol #if bars%4==0 or bars%4==3
play shiftpat[shifts]+48+n1,release: 0.125,pan: -0.5,amp: 0.6 if bars%4>=1
end
v2=clapping_rhythm[clapper_two]
if v2 != '-' then
n2=('0x'+v2).to_i(base=16)
sample :elec_tick,pan: 1,amp: clappervol #if bars%4==0 or bars%4==3
play 12-shiftpat[shifts]+48+n2,release: 0.125,pan: 0.5,amp: 0.6 if bars%4>=1
end
sleep 0.125
end
# Check if it is time to shift the pattern
if (bars + 1) % bars_per_pattern == 0 then
shifts += 1
end
end
end #repeat 2.times
m = play [60,60+4,60+7,60+12],release: 12,amp: 1,mod_phase_offset: 0.5,mod_range: 2 #exit sound
control m, mod_phase: 1,mod_phase_slide: 10 #slow the phase rate down
end #reverb