# https://gist.github.com/darinwilson/a3e5909db339838a67fe

#########################################
## Sonic Pi Drum Machine
## coded by Darin Wilson
##

use_bpm 128
use_debug false

def context

  in_thread {

    live_loop :hat do
      sleep 1 if one_in(2)
      sample :drum_bass_hard
      sleep 1
    end

    live_loop :kick do
      sample :bd_fat
      sleep 4
    end

    live_loop :snare do
      sleep 2
      sample :elec_mid_snare
      sleep 2
    end

    live_loop :snare2 do
      sleep 1
      sample :elec_hollow_kick
    end

    live_loop :drums do
      with_fx :distortion, amp: 1 do
        with_fx :wobble, phase: 16 do
          sample :loop_breakbeat, beat_stretch: 32
        end
      end
      sleep 32
    end
    with_fx :pitch_shift, pitch: -3 do
      live_loop :yo2 do
        with_fx :echo, decay: 1, mix: 0.025 do
          with_fx :ring_mod, freq: rand(8..32) do
            sample :elec_beep, rate: rrand(1,5), amp: 0.5#, pan: -1
            sleep [0.5, 0.25].choose * 2
          end
        end
      end
      live_loop :yo3 do
        with_fx :echo, decay: 1, mix: 0.025 do
          with_fx :ring_mod, freq: rand(8..32) do
            use_random_seed rrand_i(0, 10000)
            sample :elec_twip, rate: rrand(1, 3), amp: 0.5#, pan: 1
            sleep [0.5, 0.25].choose * 2
          end
        end
      end
    end
  }

end

context

# src: https://gist.github.com/xavriley/cdacb93dc127eafd1f16

# Playing ASCII drum tabs with Sonic Pi

# Ruby is an awesome language for String manipulation.
# Lets use that fact to play some drums!

# Tab for the Amen break taken from Wikipedia
# http://en.wikipedia.org/wiki/Amen_break

# Note that %Q{ ... } is just another way 
# to define a string in Ruby
amen_tab = %Q{
C |----------------|----------------|----------------|----------x-----|
R |x-x-x-x-x-x-x-x-|x-x-x-x-x-x-x-x-|x-x-x-x-x-x-x-x-|x-x-x-x-x---x-x-|
S |----o--o-o--o--o|----o--o-o--o--o|----o--o-o----o-|-o--o--o-o----o-|
B |o-o-------oo----|o-o-------oo----|o-o-------o-----|--oo------o-----|
}

# This is a random tab for the drum intro to "Cold Sweat" by James Brown
cold_sweat_tab = %Q{
C |----------o-----|----------o-----|----------o-----|----------o-----|
hh|x---x---x---x---|x---x---x---x---|x---x---x---x---|x---x---x---x---|
S |----o--g------o-|-o--o--g----o---|----o--g------o-|-o--o--g----o---|
B |o---------o-----|--oo----o-o-----|o---------o-----|--oo----o-o-----|
  |1e+a2e+a3e+a4e+a|1e+a2e+a3e+a4e+a|1e+a2e+a3e+a4e+a|1e+a2e+a3e+a4e+a|
}

# use_bpm 220 # 192.0 # tempo of the sampled break

# use_sample_bpm :loop_amen_full
# use_bpm_mul 1*16

def main_59857418(tab, repeat, delay=0)

  sleep delay

  # reduce to just essential characters
  # in this case 'x', 'o', 'g', - (hyphen) and line break
  drum_lines = tab.strip.gsub!(/[^\-xog\n]/, '')

  tab = drum_lines.split(/\n+/).map {|line|
    line.chars.map do |c|
      1 if (c == 'x' || c == 'o' || c == 'g')
    end
  }

  # We've turned our text into an array of arrays
  tab.each {|row| puts row }

  define :beat do |crash, ride, snare, bass|
    sample :drum_splash_hard   if crash
    sample :drum_cymbal_closed if ride
    sample :elec_snare         if snare
    sample :drum_heavy_kick    if bass
  end

  # We get the number of beats
  tab_length = tab.first.length

  in_thread do

    #sleep 4

    (1..repeat).each { |x|
      tab_length.times.with_index do |i|

        # the '*' here is called a splat!
        # it means we can call beat(0, 1, 0, 1)
        # instead of beat([0, 1, 0, 1])
        with_fx :distortion, distort: 0.5, pre_amp: 2, amp: 0.75 do
          beat *tab.map {|row| row[i] }
        end

        sleep 0.25 * 2
      
        # Make it sound like a bad drummer
        # sleep rrand(0.15, 0.35)
      end
    }
  end

  # Uncomment this to see how we did
  in_thread do
    #sleep 4
    (1..repeat).each { |x|
      with_fx :distortion, distort: 0.5, pre_amp: 2, amp: 0.5 do
        with_fx :pitch_shift, pitch: 0 do
          # sample :loop_amen_full, beat_stretch: 32
        end
      end
      sleep 32
    }
  end

end

in_thread do
  main_59857418(amen_tab, 4, 16)
  main_59857418(cold_sweat_tab, 4, 16*4)
end

arr = {'HH' => [], 'BD' => [], 'SD' => [], 'CC' => []}

arr['HH'][0] = [5, 0, 5, 0,  5, 0, 5, 0,  5, 0, 5, 0,  5, 0, 5, 0]
arr['BD'][0] = [9, 0, 9, 0,  0, 0, 0, 0,  9, 0, 0, 3,  0, 0, 0, 0]
arr['SD'][0] = [0, 0, 0, 0,  9, 0, 0, 2,  0, 1, 0, 0,  9, 0, 0, 1]
arr['CC'][0] = [2, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0]

i = 0

pat = (0..7).to_a * 2

# in_thread(name: :drum_machine) do
# live_loop :drum_machine do

#   # choose your kit here:
#   i = i + 1
#   case i
#     when -> (n) { (0..16).to_a.include?(n)  } then use_kit :toy
#     when -> (n) { (17..32).to_a.include?(n) } then use_kit i % 2 == 0 ? :electro : :toy 
#     else use_kit [:acoustic, :electro, :toy].choose
#   end

#   # program your pattern here - each item in the list represents 1/4 of a beat
#   # for each item, enter a number between 0 and 9 (0=silent,9=loudest)
#   with_fx :distortion, distort: 0.9, pre_amp: 2, amp: 1 do
#     hat          arr['HH'][0] * 4  + pat.sort # + arr['HH'][0] + arr['HH'][0] + arr['HH'][0].shuffle + (0..7).to_a
#   end
#   with_fx :bitcrusher, bits: 8, sample_rate: 128*rand(0..16).round do
#     kick         arr['BD'][0] + arr['BD'][0].shuffle + arr['BD'][0] + arr['BD'][0].shuffle + (0..7).to_a * 2
#   end
#   snare        arr['SD'][0] + arr['SD'][0].shuffle + arr['SD'][0] + arr['SD'][0].shuffle + pat.sort
#   crash_cymbal arr['CC'][0] + [0]*(16*3) + pat.sort

#   sleep 1

# end

##################################################################
##
## The gory details - you don't need to change anything down here,
## unless you're curious :)
##

drum_kits = {
  acoustic: {
    hat:   :drum_cymbal_closed,
    kick:  :drum_bass_hard,
    snare: :drum_snare_hard,
    crash_cymbal: :elec_cymbal
  },
  acoustic_soft: {
    hat:   :drum_cymbal_closed,
    kick:  :drum_bass_soft,
    snare: :drum_snare_soft,
    crash_cymbal: :elec_cymbal
  },
  electro: {
    hat:   :elec_wood,
    kick:  :elec_soft_kick,
    snare: :elec_hi_snare,
    crash_cymbal: :elec_cymbal
  },
  toy: {
    hat:   :elec_blup,
    kick:  :elec_hollow_kick,
    snare: :elec_pop,
    crash_cymbal: :elec_cymbal
  }
}

current_drum_kit = drum_kits[:acoustic]

define :use_kit do |kit_name|
  current_drum_kit = drum_kits[kit_name]
end

live_loop :pulse do
  sleep 4
end

define :run_pattern do |name, pattern|
  in_thread(name: name) {
    sync :pulse
    pattern.each do |p|
      sample current_drum_kit[name], amp: p/9.0
      sleep 0.25
    end
  }
end

define :hat do |pattern|
  run_pattern :hat, pattern
end

define :kick do |pattern|
  run_pattern :kick, pattern
end

define :snare do |pattern|
  with_fx :pitch_shift, pitch: rand(-12..12) do
    run_pattern :snare, pattern
  end
end

define :crash_cymbal do |pattern|
  run_pattern :crash_cymbal, pattern
end

Link: https://sonic-pi-gallery.s3.amazonaws.com/3cdf801644e7e6606c25e24dcc9afaa4.wav