/music

Programming + music

I've loved music forever and have tried playing some instruments here and there but only recently started actually making songs after trying the awesome Sonic Pi with the help of Claude Code. These are the finished songs I've made so far.

The following sections have the Ruby code that generates the songs using Sonic Pi.

Programming + music

I've loved music forever and have tried playing some instruments here and there but only recently started actually making songs after trying the awesome Sonic Pi with the help of Claude Code. These are the finished songs I've made so far.

The following sections have the Ruby code that generates the songs using Sonic Pi.

Drifting Loops

# Intro comes from playing with the sleep values of loops. Ending timeline (at 60 BPM, 1 beat = 1 second):
# beat 600 (~10:00) - bells stop, ending begins
# beat 612 (~10:12) - accent stops
# beat 620-636      - slow drone fades out over 16 beats
# beat 636-652      - main guitar + ambient base fade out together
# beat 652-676      - kick plays solo (~24 beats)
# beat 676          - one last kick + last guitar
# vt = virtual time, beats elapsed since this thread started

# Returns 1.0 before fade_start, ramps to 0 over fade_dur beats, then stays at 0
define :calc_fade do |fade_start, fade_dur = 16.0|
  return 1.0 if vt <= fade_start
  [1.0 - ((vt - fade_start) / fade_dur), 0].max
end

define :reverb_kick do |rate: 1|
  with_fx :reverb, room: 1 do
    sample :bd_808, amp: 10, rate: rate
  end
end

live_loop :guitar_ambient_base do
  amp = calc_fade(636)
  stop if amp <= 0
  sample :guit_e_fifths, rate: -0.5, amp: amp
  sleep 12
end

live_loop :soft_kick do
  if vt > 676  # final iteration at ~11:16
    reverb_kick
    sleep 2
    sample :guit_e_fifths, rate: -0.5, amp: 0.4  # quiet guitar ghost to end the song
    stop
  end
  reverb_kick
  sleep 1
  reverb_kick rate: 0.5
  sleep 0.5
  reverb_kick rate: 0.5
  sleep 0.5
end

live_loop :guitar_main do
  tick
  sleep 12 if look == 0

  amp = calc_fade(636)
  stop if amp <= 0

  if look.even?
    sample :guit_e_fifths, rate: 1, amp: amp
  else
    with_fx :echo, mix: 1, phase: 0.25, decay: 4 do
      sample :guit_e_fifths, rate: 1, amp: amp
    end
  end
  sleep 6

  sample :guit_e_fifths, rate: 1, amp: amp
  sleep 6

  sample :guit_e_fifths, rate: 0.9, amp: amp
  sleep 3
end

live_loop :guitar_accent do
  tick
  stop if vt > 612  # stop at ~10:12
  if look == 0
    sleep 25 # first time
    sample :guit_e_fifths, rate: 1.6
  elsif look % 3 == 0
    sleep 4 # sync with guitar_main like the first time
    sample :guit_e_fifths, rate: 1.5 # listener expects 1.6
  else
    sleep 13 # every time after
    sample :guit_e_fifths, rate: rrand(1.6, 2)
  end
end

live_loop :guitar_slow_drone do
  tick
  sleep(look == 0 ? 27 : 15)

  amp = calc_fade(620)
  stop if amp <= 0
  sample :guit_e_fifths, rate: 0.3, amp: amp
end

live_loop :haunted_random_bells do
  stop if vt > 600  # first to go, stops at ~10:00
  sleep 15
  sample :perc_bell, amp: 0.5, rate: rrand(-0.5, 0.5)
end

Haunted Glitch Heaven

use_random_seed 1337
switchup_A = 120
stop_toggle_A = 220

set :kick_final_played, false
set :kick_B_final_played, false
set :lunar_ending_played, false
set :accent2_active, false

live_loop :robot_signifier do
  sleep 40
  stop if vt > stop_toggle_A + 10
  with_fx :reverb, room: 1 do
    with_fx :lpf, cutoff: 80 do
      sample :glitch_robot2
    end
  end
end

# -- intro blips A --
16.times do
  sample :elec_blip, rate: rrand(0.5, 2)
  sleep 0.125
end

sleep 1

define :beep_collection do
  ring(
    :elec_blip2,
    :elec_beep,
    :elec_bong,
    :elec_filt_snare,
    :elec_flip,
    :elec_hollow_kick,
    :elec_mid_snare,
    :elec_ping,
    :elec_plip,
    :elec_soft_kick,
    :elec_tick,
    :elec_twang,
    :elec_twip
  )
end

live_loop :kick do
  if vt > stop_toggle_A
    unless get[:kick_final_played]
      set :kick_final_played, true
      with_fx :reverb, room: 1 do
        sample :bd_haus, rate: 0.5, amp: 0.5
      end
      with_fx :echo, mix: 1, phase: 0.5, decay: 8 do
        sample :bd_haus, rate: 0.5, amp: 0.5
      end
      sleep 0.5
    else
      stop if vt > stop_toggle_A + 31
      with_fx :lpf, cutoff: 80 do
        with_fx :reverb, room: 1 do
          sample :bd_haus, rate: 0.35, amp: 0.2
        end
      end
      sleep 0.5
    end
  else
    tick
    if look < 40
      set :kick_rate, 0.8
    elsif look % 40 == 0
      set :kick_rate, vt >= switchup_A ? rrand(0.3, 0.6) : rrand(0.6, 0.9)
    end
    sample :bd_haus, rate: get[:kick_rate], amp: 0.6
    sleep 0.5
  end
end

live_loop :glitchy_beeps_barrage do
  stop if vt > stop_toggle_A
  tick
  sleep 8 if look == 0
  if vt < 20
    base_amp = 0.4
    ramp_amp = [base_amp * ((vt - 10.0) / 10.0), 0].max
  else
    ramp_amp = 0.4
  end
  run = look / 8
  s = if vt >= switchup_A and look.odd?
    beep_collection.tick(:phone_other)
  elsif vt >= 80 and run.odd?
    beep_collection[run / 2]
  else
    :elec_blip
  end
  sample s, rate: [1, 1, 1, 1, 0.5].choose, pan: [-1, 1].tick("pan_#{s}"), amp: ramp_amp
  sleep 0.25
end

live_loop :glitchy_beeps_main_burst do
  stop if vt > stop_toggle_A
  tick
  mod = look >= 20 ? 21 : 5
  if look % mod == 0 and look != 21
    burst = tick(:burst)
    s = if get[:accent2_active]
      burst.even? ? :elec_blip : beep_collection.tick(:other)
    else
      :elec_blip
    end
    8.times do
      sample s, rate: rrand(0.5, 2), amp: 0.5
      sleep 0.125
    end
  else
    sleep 0.25
  end
end

live_loop :drone do
  stop if vt > stop_toggle_A + 10
  sleep 20
  with_fx :reverb, room: 1 do
    with_fx :echo, phase: 1, decay: 10 do
      r = vt >= switchup_A ? rrand(0.2, 0.4) : rrand(0.4, 0.9)
      sample :ambi_drone, rate: r, amp: 0.2
    end
  end
end

live_loop :glitch_blam do
  stop if vt > stop_toggle_A + 15
  sleep 40
  with_fx :reverb, room: 1 do
    r = vt >= switchup_A ? rrand(0.65, 0.75) : rrand(0.75, 0.85)
    sample (ring :glitch_bass_g, :glitch_perc3).tick, rate: r, amp: 0.5
  end
end

live_loop :dark_ambient_rush do
  stop if vt > stop_toggle_A + 5
  tick(:iter)
  sleep(look(:iter) == 0 ? 40 : 20)
  set :accent2_active, true
  with_fx :reverb, room: 1 do
    samps = vt >= switchup_A ? (ring :ambi_dark_woosh, :ambi_lunar_land) : (ring :loop_drone_g_97, :loop_3d_printer)
    sample samps.tick, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
  end
end

live_loop :creepy_choir do
  stop if vt > stop_toggle_A + 10
  tick
  sleep(look == 0 ? 55 : 15)
  with_fx :reverb, room: 1 do
    with_fx :echo, phase: 1, decay: 10 do
      r = vt >= switchup_A ? rrand(0.3, 0.6) : rrand(0.6, 0.9)
      sample :ambi_choir, rate: r, amp: 0.4
    end
  end
end

# ========================================================================================
# PART B
# ========================================================================================
in_thread do
  sleep stop_toggle_A + 30 - 1

  switchup_B = 20
  stop_toggle_B = 470

  define :main_burst_B do |s, amps|
    8.times do
      sample s, rate: rrand(0.5, 2), amp: amps[0]
      sleep 0.125
    end
    sleep 1
    8.times do
      sample s, rate: rrand(0.5, 1), amp: amps[1]
      sleep 0.125
    end
    sleep 1
    with_fx :echo, mix: 1, phase: 0.25, decay: 4 do
      8.times do
        sample s, rate: rrand(0.5, 2), amp: amps[2]
        sleep 0.125
      end
    end
    sleep 1
    with_fx :echo, mix: 1, phase: 0.25, decay: 4 do
      8.times do
        sample s, rate: rrand(0.1, 0.5), amp: amps[3]
        sleep 0.125
      end
    end
    sleep 1
  end

  # -- intro blips B (takes 8 beats) --
  main_burst_B :elec_blip, [0.8, 0.8, 1, 0.5]

  b_start = vt # try to have a 0 reference point once part B starts

  live_loop :robot_signifier_B do
    stop if vt > stop_toggle_B - 5
    sleep(tick == 0 ? switchup_B : 40)
    with_fx :reverb, room: 1 do
      with_fx :lpf, cutoff: 80 do
        sample :glitch_robot2
      end
    end
  end

  live_loop :glitchy_beeps_main_burst_B do
    stop if vt > stop_toggle_B + 8
    b_vt = vt - b_start
    if b_vt >= switchup_B && b_vt < switchup_B + 18
      sleep 1
      next
    end
    s = b_vt > switchup_B ? beep_collection.tick(:other) : :elec_blip
    main_burst_B s, [0.4, 0.4, 0.5, 0.3]
  end

  live_loop :kick_B do
    b_vt = vt - b_start
    if vt > stop_toggle_B
      unless get[:kick_B_final_played]
        set :kick_B_final_played, true
        with_fx :reverb, room: 1 do
          sample :bd_haus, rate: 0.5, amp: 0.4
        end
        with_fx :echo, mix: 1, phase: 0.5, decay: 8 do
          sample :bd_haus, rate: 0.5, amp: 0.4
        end
        sleep 0.5
      else
        fade_dur = 16.0
        elapsed = vt - stop_toggle_B
        stop if elapsed > fade_dur
        fade_amp = 0.2 * (1.0 - (elapsed / fade_dur))
        # trigger lunar landing once at the start of the trailing kicks
        unless get[:lunar_ending_played]
          set :lunar_ending_played, true
          with_fx :reverb, room: 1 do
            sample :ambi_lunar_land, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
          end
        end
        with_fx :lpf, cutoff: 80 do
          with_fx :reverb, room: 1 do
            sample :bd_haus, rate: 0.35, amp: fade_amp
          end
        end
        sleep 0.5
      end
    else
      # drop out for a beat then 3 rapid kicks every 40 beats (synced to robot_signifier_B)
      cycle = b_vt >= switchup_B ? (b_vt - switchup_B) % 40 : nil
      if cycle && cycle < 1
        sleep 0.5
      elsif cycle && cycle >= 1 && cycle < 1.75
        with_fx :reverb, room: 0.8 do
          sample :bd_haus, rate: 0.3, amp: 0.6
        end
        sleep 0.25
      else
        tick
        if look < 40
          set :kick_B_rate, 0.6
        elsif look % 40 == 0
          set :kick_B_rate, rrand(0.4, 0.6)
        end
        with_fx :reverb, room: 0.8 do
          sample :bd_haus, rate: get[:kick_B_rate], amp: 0.6
        end
        sleep 0.5
      end
    end
  end

  live_loop :drone_B do
    stop if vt > stop_toggle_B - 3
    tick
    sleep switchup_B + 2
    with_fx :reverb, room: 1 do
      with_fx :echo, phase: 1, decay: 10 do
        sample :ambi_drone, rate: rrand(0.2, 0.4), amp: 0.2
      end
    end
  end

  live_loop :glitch_blam_B do
    stop if vt > stop_toggle_B - 6
    tick
    sleep switchup_B
    with_fx :reverb, room: 1 do
      sample (ring :tbd_highkey_c4, :glitch_perc3).look, rate: rrand(0.65, 0.75), amp: 0.8
    end
  end

  live_loop :creepy_choir_B do
    stop if vt > stop_toggle_B - 2
    tick
    sleep(look == 0 ? 30 : 15)
    with_fx :reverb, room: 1 do
      with_fx :echo, phase: 1, decay: 10 do
        sample :ambi_choir, rate: rrand(0.8, 0.9), amp: 0.8
      end
    end
  end

  live_loop :dark_ambient_rush_B do
    stop if vt > stop_toggle_B - 4
    tick
    sleep 40
    with_fx :reverb, room: 1 do
      sample (ring :ambi_dark_woosh, :tbd_fxbed_loop).look, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
    end
  end

  live_loop :glitchy_beeps_barrage_B do
    stop if vt > stop_toggle_B - 10
    tick(:init)
    sleep switchup_B if look(:init) == 0
    tick
    run = look / 8
    s = if look.odd?
      beep_collection.tick(:phone_other)
    elsif run.odd?
      beep_collection[run / 2]
    else
      :elec_blip
    end
    sample s, rate: [1, 1, 1, 1, 0.5].choose, pan: [-1, 1].tick("pan_#{s}"), amp: 0.6
    sleep 0.25
  end
end

Haunted Glitch Heaven

use_random_seed 1337
switchup_A = 120
stop_toggle_A = 220

set :kick_final_played, false
set :kick_B_final_played, false
set :lunar_ending_played, false
set :accent2_active, false

live_loop :robot_signifier do
  sleep 40
  stop if vt > stop_toggle_A + 10
  with_fx :reverb, room: 1 do
    with_fx :lpf, cutoff: 80 do
      sample :glitch_robot2
    end
  end
end

# -- intro blips A --
16.times do
  sample :elec_blip, rate: rrand(0.5, 2)
  sleep 0.125
end

sleep 1

define :beep_collection do
  ring(
    :elec_blip2,
    :elec_beep,
    :elec_bong,
    :elec_filt_snare,
    :elec_flip,
    :elec_hollow_kick,
    :elec_mid_snare,
    :elec_ping,
    :elec_plip,
    :elec_soft_kick,
    :elec_tick,
    :elec_twang,
    :elec_twip
  )
end

live_loop :kick do
  if vt > stop_toggle_A
    unless get[:kick_final_played]
      set :kick_final_played, true
      with_fx :reverb, room: 1 do
        sample :bd_haus, rate: 0.5, amp: 0.5
      end
      with_fx :echo, mix: 1, phase: 0.5, decay: 8 do
        sample :bd_haus, rate: 0.5, amp: 0.5
      end
      sleep 0.5
    else
      stop if vt > stop_toggle_A + 31
      with_fx :lpf, cutoff: 80 do
        with_fx :reverb, room: 1 do
          sample :bd_haus, rate: 0.35, amp: 0.2
        end
      end
      sleep 0.5
    end
  else
    tick
    if look < 40
      set :kick_rate, 0.8
    elsif look % 40 == 0
      set :kick_rate, vt >= switchup_A ? rrand(0.3, 0.6) : rrand(0.6, 0.9)
    end
    sample :bd_haus, rate: get[:kick_rate], amp: 0.6
    sleep 0.5
  end
end

live_loop :glitchy_beeps_barrage do
  stop if vt > stop_toggle_A
  tick
  sleep 8 if look == 0
  if vt < 20
    base_amp = 0.4
    ramp_amp = [base_amp * ((vt - 10.0) / 10.0), 0].max
  else
    ramp_amp = 0.4
  end
  run = look / 8
  s = if vt >= switchup_A and look.odd?
    beep_collection.tick(:phone_other)
  elsif vt >= 80 and run.odd?
    beep_collection[run / 2]
  else
    :elec_blip
  end
  sample s, rate: [1, 1, 1, 1, 0.5].choose, pan: [-1, 1].tick("pan_#{s}"), amp: ramp_amp
  sleep 0.25
end

live_loop :glitchy_beeps_main_burst do
  stop if vt > stop_toggle_A
  tick
  mod = look >= 20 ? 21 : 5
  if look % mod == 0 and look != 21
    burst = tick(:burst)
    s = if get[:accent2_active]
      burst.even? ? :elec_blip : beep_collection.tick(:other)
    else
      :elec_blip
    end
    8.times do
      sample s, rate: rrand(0.5, 2), amp: 0.5
      sleep 0.125
    end
  else
    sleep 0.25
  end
end

live_loop :drone do
  stop if vt > stop_toggle_A + 10
  sleep 20
  with_fx :reverb, room: 1 do
    with_fx :echo, phase: 1, decay: 10 do
      r = vt >= switchup_A ? rrand(0.2, 0.4) : rrand(0.4, 0.9)
      sample :ambi_drone, rate: r, amp: 0.2
    end
  end
end

live_loop :glitch_blam do
  stop if vt > stop_toggle_A + 15
  sleep 40
  with_fx :reverb, room: 1 do
    r = vt >= switchup_A ? rrand(0.65, 0.75) : rrand(0.75, 0.85)
    sample (ring :glitch_bass_g, :glitch_perc3).tick, rate: r, amp: 0.5
  end
end

live_loop :dark_ambient_rush do
  stop if vt > stop_toggle_A + 5
  tick(:iter)
  sleep(look(:iter) == 0 ? 40 : 20)
  set :accent2_active, true
  with_fx :reverb, room: 1 do
    samps = vt >= switchup_A ? (ring :ambi_dark_woosh, :ambi_lunar_land) : (ring :loop_drone_g_97, :loop_3d_printer)
    sample samps.tick, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
  end
end

live_loop :creepy_choir do
  stop if vt > stop_toggle_A + 10
  tick
  sleep(look == 0 ? 55 : 15)
  with_fx :reverb, room: 1 do
    with_fx :echo, phase: 1, decay: 10 do
      r = vt >= switchup_A ? rrand(0.3, 0.6) : rrand(0.6, 0.9)
      sample :ambi_choir, rate: r, amp: 0.4
    end
  end
end

# ========================================================================================
# PART B
# ========================================================================================
in_thread do
  sleep stop_toggle_A + 30 - 1

  switchup_B = 20
  stop_toggle_B = 470

  define :main_burst_B do |s, amps|
    8.times do
      sample s, rate: rrand(0.5, 2), amp: amps[0]
      sleep 0.125
    end
    sleep 1
    8.times do
      sample s, rate: rrand(0.5, 1), amp: amps[1]
      sleep 0.125
    end
    sleep 1
    with_fx :echo, mix: 1, phase: 0.25, decay: 4 do
      8.times do
        sample s, rate: rrand(0.5, 2), amp: amps[2]
        sleep 0.125
      end
    end
    sleep 1
    with_fx :echo, mix: 1, phase: 0.25, decay: 4 do
      8.times do
        sample s, rate: rrand(0.1, 0.5), amp: amps[3]
        sleep 0.125
      end
    end
    sleep 1
  end

  # -- intro blips B (takes 8 beats) --
  main_burst_B :elec_blip, [0.8, 0.8, 1, 0.5]

  b_start = vt # try to have a 0 reference point once part B starts

  live_loop :robot_signifier_B do
    stop if vt > stop_toggle_B - 5
    sleep(tick == 0 ? switchup_B : 40)
    with_fx :reverb, room: 1 do
      with_fx :lpf, cutoff: 80 do
        sample :glitch_robot2
      end
    end
  end

  live_loop :glitchy_beeps_main_burst_B do
    stop if vt > stop_toggle_B + 8
    b_vt = vt - b_start
    if b_vt >= switchup_B && b_vt < switchup_B + 18
      sleep 1
      next
    end
    s = b_vt > switchup_B ? beep_collection.tick(:other) : :elec_blip
    main_burst_B s, [0.4, 0.4, 0.5, 0.3]
  end

  live_loop :kick_B do
    b_vt = vt - b_start
    if vt > stop_toggle_B
      unless get[:kick_B_final_played]
        set :kick_B_final_played, true
        with_fx :reverb, room: 1 do
          sample :bd_haus, rate: 0.5, amp: 0.4
        end
        with_fx :echo, mix: 1, phase: 0.5, decay: 8 do
          sample :bd_haus, rate: 0.5, amp: 0.4
        end
        sleep 0.5
      else
        fade_dur = 16.0
        elapsed = vt - stop_toggle_B
        stop if elapsed > fade_dur
        fade_amp = 0.2 * (1.0 - (elapsed / fade_dur))
        # trigger lunar landing once at the start of the trailing kicks
        unless get[:lunar_ending_played]
          set :lunar_ending_played, true
          with_fx :reverb, room: 1 do
            sample :ambi_lunar_land, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
          end
        end
        with_fx :lpf, cutoff: 80 do
          with_fx :reverb, room: 1 do
            sample :bd_haus, rate: 0.35, amp: fade_amp
          end
        end
        sleep 0.5
      end
    else
      # drop out for a beat then 3 rapid kicks every 40 beats (synced to robot_signifier_B)
      cycle = b_vt >= switchup_B ? (b_vt - switchup_B) % 40 : nil
      if cycle && cycle < 1
        sleep 0.5
      elsif cycle && cycle >= 1 && cycle < 1.75
        with_fx :reverb, room: 0.8 do
          sample :bd_haus, rate: 0.3, amp: 0.6
        end
        sleep 0.25
      else
        tick
        if look < 40
          set :kick_B_rate, 0.6
        elsif look % 40 == 0
          set :kick_B_rate, rrand(0.4, 0.6)
        end
        with_fx :reverb, room: 0.8 do
          sample :bd_haus, rate: get[:kick_B_rate], amp: 0.6
        end
        sleep 0.5
      end
    end
  end

  live_loop :drone_B do
    stop if vt > stop_toggle_B - 3
    tick
    sleep switchup_B + 2
    with_fx :reverb, room: 1 do
      with_fx :echo, phase: 1, decay: 10 do
        sample :ambi_drone, rate: rrand(0.2, 0.4), amp: 0.2
      end
    end
  end

  live_loop :glitch_blam_B do
    stop if vt > stop_toggle_B - 6
    tick
    sleep switchup_B
    with_fx :reverb, room: 1 do
      sample (ring :tbd_highkey_c4, :glitch_perc3).look, rate: rrand(0.65, 0.75), amp: 0.8
    end
  end

  live_loop :creepy_choir_B do
    stop if vt > stop_toggle_B - 2
    tick
    sleep(look == 0 ? 30 : 15)
    with_fx :reverb, room: 1 do
      with_fx :echo, phase: 1, decay: 10 do
        sample :ambi_choir, rate: rrand(0.8, 0.9), amp: 0.8
      end
    end
  end

  live_loop :dark_ambient_rush_B do
    stop if vt > stop_toggle_B - 4
    tick
    sleep 40
    with_fx :reverb, room: 1 do
      sample (ring :ambi_dark_woosh, :tbd_fxbed_loop).look, pitch_stretch: 12, attack: 4, sustain: 4, release: 4
    end
  end

  live_loop :glitchy_beeps_barrage_B do
    stop if vt > stop_toggle_B - 10
    tick(:init)
    sleep switchup_B if look(:init) == 0
    tick
    run = look / 8
    s = if look.odd?
      beep_collection.tick(:phone_other)
    elsif run.odd?
      beep_collection[run / 2]
    else
      :elec_blip
    end
    sample s, rate: [1, 1, 1, 1, 0.5].choose, pan: [-1, 1].tick("pan_#{s}"), amp: 0.6
    sleep 0.25
  end
end