Changing keys crashes script

Okeydokey, made lots of progress. My piece is sounding pretty darn good. But I’d like to throw in some chord changes. I implemented it as below, but every time it hits a key change, scales/chords somehow start throwing negative midi numbers.
Any ideas what I’m doing wrong? Is there a better way to pass the new key into multiple live loops other than set/get?

set :playbeat , 1
set :playbass , 1
set :playkick , 1
set :playeuclid , 1
set :playchords , 1
set :playkalimba , 1
set :playsafari, 1
set :playguitar, 1
set :playtabla, 1

set :tonic ,  :e3




whole = 1.0
half = 0.5
quarter = 0.25
eighth = 0.125
sixteenth = 0.0625
dotted = 1.5
triplet = 2.0 / 3
octave = 12
maj3 = 4
min3 = 3
fifth = 7
wstep = 2
hstep = 1

bpm = 90
use_bpm bpm
secsperbeat = 60.0 / bpm

live_loop :etick do
  sleep eighth
end

live_loop :qtick do
  sleep quarter
end

live_loop :htick do
  sleep half
end
live_loop :wtick do
  sleep whole
end

live_loop :dtick do
  sleep whole * 2
end

live_loop :ftick do
  sleep whole * 4
end



##| live_loop :keychange do |thiskey|

##|   [:a4, :b4, :e4, :e4].each do
##|     sleep whole * 32
##|     set :tonic, thiskey
##|   end
##| end




live_loop :beat do
  sync :qtick
  if get[:playbeat] == 1 then
    if one_in(4)
      sample  [:arovane_beat_a, :arovane_beat_b, :arovane_beat_b, :arovane_beat_b, :arovane_beat_b, :arovane_beat_c, :arovane_beat_d, :arovane_beat_e, :arovane_beat_e].choose     , onset: pick, release: 0.25
      sleep [quarter, half, half * dotted].choose
    end
  end
end








live_loop :bass do
  sync :htick
  if get[:playbass] == 1 then
    localtonic = get[:tonic]
    
    use_synth [:blade, :bass_foundation, :pulse, :tb303, :subpulse].choose
    play scale(localtonic - (octave * 2 + maj3), :major_pentatonic, num_octaves: 1).choose \
      , amp: rrand(0.7, 1) \
      , sustain: [0, 0.125, 0.25, 0.375].choose \
      , cutoff: rrand(50, 90)\
      , release: [0.125, 0.25, 0.375].choose \
      , pulse_width: rrand(0.2, 0.8)\
      , divisor: 2 ^ rrand_i(1,3)\
      , mod_phase: 0.0625\
      , mod_range: 12
    
    
    sleep [half, whole, whole  * dotted].choose
  end
  
end



live_loop:kick do
  sync :dtick
  if get[:playkick] == 1 then
    
    sample :bd_fat, amp: 2
    sleep half * dotted
    sample :bd_fat, amp: 1.5
    sleep half * dotted
    sample :bd_fat, amp: 2
    sleep half
  end
  
end


live_loop :euclid do
  sync :ftick
  if get[:playeuclid] == 1 then
    localtonic = get[:tonic]
    
    
    use_synth :winwood_lead
    
    spread(rrand_i(3, 11), 16).each do |thisbeat|
      if thisbeat
        with_fx :flanger do
          ##| with_fx :echo, phase: whole * 2, decay: 0.25, mix: 0.25  do
          
          with_fx :distortion, distort: rrand(0.2, 0.5) do
            play scale(localtonic + (octave * 2), :minor_pentatonic, num_octaves:2).choose \
              , amp: rrand(1.25, 1.75) \
              , sustain: [0, eighth, eighth * dotted, quarter].choose \
              , cutoff: rrand(30, 70)\
              , release: [eighth, quarter, dotted * quarter].choose \
              , ramp_range: rrand(0, 0.1) \
              , lfo_width: rrand_i(0, 0.5)\
              , lfo_rate: [secsperbeat / 2, secsperbeat / 3, secsperbeat / 4, secsperbeat / 6, secsperbeat / 8].choose \
              , res: rrand(0.0, 0.8)
            
          end #distortion
        end #flanger
        
      end #if thisbeat
      sleep quarter
    end #each
  end #if playeuclid
end #liveloop




live_loop :chords do
  sync :ftick
  if get[:playchords] == 1 then
    localtonic = get[:tonic]
    
    ##| use_synth  [:blade, :dpulse, :hollow, :hoover, :pluck].choose
    use_synth [:rodeo, :blade, :pulse, :organ_tonewheel].choose
    sustain = [whole * 2, whole * 3, whole * 4, whole * 6].choose
    play [\
          chord(localtonic + octave, :minor7), \
          chord(localtonic + octave + min3, :sus2), \
          chord(localtonic + octave - wstep, '6'), \
          chord(localtonic + octave - maj3, :major7)\
    ].choose \
      , attack: [eighth, quarter, dotted * eighth].choose \
      , sustain: sustain \
      , release: [eighth, sixteenth, dotted * sixteenth].choose \
      , vibrato_rate: eighth \
      , vibrato_depth: rrand(0.0, 0.3) \
      , cutoff: rrand(30, 70) \
      , pulse_width: rrand(0.1, 0.9) \
      , dpulse_width: rrand(0.1, 0.9) \
      , detune: rrand(0.0, 0.1) \
      , res: rrand(0.2, 0.7) \
      , coef: rrand(0.1, 0.5) \
      , amp: 1
    
    sleep whole * [4, 6, 8].choose
  end #if playchords
end #liveloop



live_loop :kalimba do
  sync :qtick
  if get[:playkalimba] == 1 then
    localtonic = get[:tonic]
    
    use_synth :kalimba
    
    [\
     chord(localtonic, :m9, num_octaves: 2), \
     chord(localtonic  + octave+ min3, :sus2, num_octaves: 2), \
     chord(localtonic + octave- wstep, '6', num_octaves: 2), \
     chord(localtonic + octave- maj3, :major7, num_octaves: 2)\
    ].choose.shuffle.each do|thisnote|
      if thisnote > 0
        play thisnote  \
          , amp: rrand(1, 2) \
          , release: eighth
      end #if note > 0
      
      
      
      sleep [quarter, dotted * half, half].choose
    end #each
  end #if playkalimba
end #liveloop




live_loop :safari do
  sync :dtick
  if get[:playsafari] == 1 then
    sample :loop_safari, beat_stretch:  16
    sleep whole * 32
    
  end #if play
  
end #loop


live_loop :guitar do
  sync :dtick
  if get[:playguitar] == 1 then
    sleep whole * 4
    sample :guit_em9, pitch_stretch: 8
    sleep whole * 28
  end #if
end #liveloop



live_loop :tabla do
  sync :ftick
  if get[:playtabla] == 1 then
    
    
    sample  [:tabla_ghe4, :tabla_ghe5, :tabla_ghe6, :tabla_ghe8].choose, amp: 0.5
    sleep quarter
    
    2.times do
      sample [:tabla_ke1, :tabla_ke2, :tabla_ke3].choose, amp: 0.5
      sleep eighth
    end
    
    sample  [:tabla_tas1, :tabla_tas2, :tabla_tas3].choose, amp: 0.5
    sleep quarter
    
    4.times do
      
      sample [:tabla_te1, :tabla_te2, :tabla_te_m, :tabla_te_n3].choose, amp: 0.5
      sleep eighth
    end
    
    
    3.times do
      
      sample [:tabla_na, :tabla_na_o, :tabla_na_s, :tabla_tun1, :tabla_tun2, :tabla_tun3].choose, amp: 0.5
      sleep quarter
    end
    
    sleep whole * 16
    
    
    
    
    
    
  end #if
end #liveloop






ps once I get it debugged, I want the changes to be much slower (every 64 bars, instead of every 8). I sped it up to ease testing & debugging.

pps uncomment the setkey block to see the bug happen.

I mean keychange loop.

I think you want

comment do
  live_loop :keychange do

    [:a4, :b4, :e4, :e4].each do |thiskey|
      sleep whole * 32
      set :tonic, thiskey
    end
  end
end

D’oh!
Of course. Thanks for your help.
Works like a champ now.
Boy, this is fun!

(I would love to know how/why the solution works :wink: )

It’s just that thiskey was declared in the wrong place.
It’s the iterator variable in the each loop, not the live_loop (I’m not sure what it does when it’s behind the live_loop)

I completely missed that, well-spotted!

This sounds good now keychange sorted. One minor misstype
:tabla_te_n3 should be :tabla_te_ne

Good eye! Thanks for all the help!
I’m slowly reading through the helpfile, starting with the lang section. I’m learning so much. This is a well-thought-out platform, that’s for sure.
:slight_smile: