Clapping-Rhythms-With-Arpeggio-Accompaniment

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