Lofi house, my first code

Hey everybody! Just started messing around with Sonic PI, so much fun! I can already tell that this is a really good tool for breaking out of creative blocks. Here’s my first little thing I made, a sort of chill out house beat with a live mixer for muting different instruments. Any feedback on how to write it cleaner would be highly appreciated :slightly_smiling_face:

# PROJECT SETTINGS

use_bpm 118

live_loop :met1 do
  sleep 1
end


# SEQUENCER SETTINGS

define :pattern do |pattern|
  return pattern.ring.tick == "x"
end


# LIVE MIXER (0 = mute, 1 = channel on)

kickon  = 1
hihaton = 1
rimon   = 1

chordon = 1
basson  = 1
bellon  = 1


# DRUMS

live_loop :kick, sync: :met1 do
  with_swing -0.08, 2 do
    sample :bd_tek, rate: 0.8, sustain: 0, release: 0.3, amp: 0.8 if pattern "x---x---x---x---" and kickon == 1
  end
  sleep 0.25
end

live_loop :kick_soft, sync: :met1 do
  with_swing -0.08, 2 do
    sample :bd_tek, rate: 0.7, sustain: 0, release: 0.2, amp: 0.2 if pattern "---------------x---------x------" and kickon == 1
  end
  sleep 0.25
end

live_loop :hh, sync: :met1 do
  with_swing -0.08, 2 do
    sample :drum_cymbal_closed, sustain: 0, release: 0.15, amp: 0.8, rate: 1.1 if pattern "--x---x---x---x-" and hihaton == 1
  end
  sleep 0.25
end

live_loop :hh_short, sync: :met1 do
  with_swing -0.08, 2 do
    sample :drum_cymbal_pedal, sustain: 0, release: 0.05, pan: -0.4, amp: 0.3, start: 0.1 if pattern "--xx--x--xx--x-x" and hihaton == 1
  end
  sleep 0.25
end

with_fx :reverb, damp: 1, mix: 0.3 do
  live_loop :rimshot, sync: :met1 do
    with_swing -0.08, 2 do
      sample :sn_generic, amp: 0.4, sustain: 0, release: 0.10 if pattern "----x-------x---" and rimon == 1
    end
    sleep 0.25
  end
end

live_loop :rimshot2, sync: :met1 do
  with_swing -0.08, 2 do
    sample :elec_filt_snare, sustain: 0, release: 0.10, pan: 0.4, rate: 0.5, amp: 0.2 if pattern "----x--x----x-------x--x-x--x---" and rimon == 1
  end
  sleep 0.25
end


# SIDECHAIN (chords, bass, melody)

with_fx :slicer, phase: 1, wave: 0, invert_wave: 1, mix: 0.9 do
  
  with_fx :level, amp: 0.15 do
    live_loop :housechords1, sync: :met1 do
      use_synth :mod_fm
      with_fx :pitch_shift, pitch: -3.9, reps: 2 do
        play chord(:a3, "m11"), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
        play chord(:a3, "m11"), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
        sleep 4
      end
      with_fx :pitch_shift, pitch: 7.1, reps: 4 do
        play chord(:f3, "m11"), pan: 1, decay: 2, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
        play chord(:f3, "m11"), pan: -1, decay: 2, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
        sleep 2
      end
      with_fx :pitch_shift, pitch: -1.9, reps: 2 do
        play chord(:f3, "m11"), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
        play chord(:f3, "m11"), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
        sleep 4
      end
      with_fx :pitch_shift, pitch: 5.1, reps: 4 do
        play chord(:f3, "m11"), pan: 1, decay: 2, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
        play chord(:f3, "m11"), pan: -1, decay: 2, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
        sleep 2
      end
    end
  end
  
  with_fx :ping_pong, phase: 0.75 do
    with_fx :level, amp: 0.2 do
      live_loop :housechords, sync: :met1 do
        use_synth :mod_fm
        2.times do
          play (chord_invert(chord :f3, "m11"), 2), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
          play chord(:f3, "m11"), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
          sleep 4
        end
        2.times do
          play (chord_invert(chord :c3, "m11"), 4), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
          play (chord_invert(chord :c3, "m11"), 3), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
          sleep 4
        end
        2.times do
          play chord(:Eb3, "m11"), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
          play chord(:Eb3, "m11"), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
          sleep 4
        end
        2.times do
          play (chord_invert(chord :Bb2, "m11"), 2), pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.3, mod_wave: 3 if chordon == 1
          play (chord_invert(chord :Bb2, "m11"), 5), pan: -1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01, divisor: 1, mod_range: 0.2, mod_wave: 3 if chordon == 1
          sleep 4
        end
      end
    end
  end
  
  with_fx :reverb, room: 1 do
    with_fx :ping_pong, phase: 0.75 do
      with_fx :lpf, cutoff: 130, pre_amp: 1.5 do
        live_loop :lilmelo, sync: :met1 do
          
          define :bellp do |n, m|
            
            sleep 2
            play n + 0.3 if bellon == 1
            sleep 0.1
            play n + 17 if bellon == 1
            sleep 0.4
            play n + 0.2 if bellon == 1
            sleep 0.1
            play n + 12 if bellon == 2
            sleep 0.9
            play m + 0.2 if bellon == 1
            play m + 24 if bellon == 1
            sleep 0.5
            
          end
          
          use_synth :kalimba
          
          bellp 70, 67
          bellp 65, 63
          bellp 67, 65
          bellp 70, 58
          bellp 68, 65
          bellp 63, 61
          bellp 60, 65
          bellp 72, 70
          
        end
      end
    end
  end
  
  live_loop :Bassline, sync: :met1 do
    
    define :basn do |n, r|
      play n, release: r, cutoff: rrand(55, 125) if basson == 1
      sleep r
    end
    
    use_synth :tri
    
    basn 29, 0.75
    basn 34, 0.75
    basn 36, 1
    basn 39, 1
    basn 41, 0.5
    
    basn 29, 0.75
    basn 34, 0.75
    basn 36, 1
    basn 41, 0.5
    basn 39, 0.5
    basn 34, 0.5
    
    basn 29+7, 0.75
    basn 34-5, 0.75
    basn 36-5, 1
    basn 39-5, 1
    basn 39, 0.5
    
    basn 29+7, 0.75
    basn 34+7, 0.75
    basn 36+7, 1
    basn 41-5, 0.5
    basn 39-5, 0.5
    basn 34-5, 0.5
    
    basn 29-2, 0.75
    basn 34-2, 0.75
    basn 36-2, 1
    basn 39-2, 1
    basn 41-2, 0.5
    
    basn 29-2, 0.75
    basn 34-2, 0.75
    basn 36-2, 1
    basn 41-2, 0.5
    basn 39-2, 0.5
    basn 34-2, 0.5
    
    basn 29+5, 0.75
    basn 34-7, 0.75
    basn 36-7, 1
    basn 39-7, 1
    basn 37, 0.5
    
    basn 29+5, 0.75
    basn 34+5, 0.75
    basn 36+5, 1
    basn 41-7, 0.5
    basn 39-7, 0.5
    basn 34-7, 0.5
    
  end
end

with_fx :reverb do
  live_loop :vinylNoise, sync: :met1 do
    sample :vinyl_hiss, amp: 0.15
    sleep sample_duration :vinyl_hiss
  end
end
8 Likes

Love the sound, unfortunately on my SP 3.2.2 & Win 10 x64, your code
locks up my SP once I hit stop… I have to wait about 10 mins before any
Audio plays in SP… I was hoping to tinker, using spread() to replace your
pattern define… perhaps it’s just old n tired, like me. :slight_smile:

Eli…

Haha, I noticed on my computer that the patch gets an awful lot of “running behind” errors so yeah it might not be the most efficient code. But it runs smooth like butter though, I have a huawei matebook with intel i7. What is an “SP”?

SP is the short term most of us use for Sonic Pi.

I think I’vew got it… it was the IF statement in yourdefine: Bass…

Converted it to:

  define :basn do |n, r|
      if basson == 1 then
      play n, release: r, cutoff: rrand(55, 125) 
      sleep r
    end
end

and it seems a lot more reliable (for me).

Have fun!

Eli…

Alright, cool!
…but I think you wanna add an else condition too, otherwise you’ll get a thread death if you try to mute the bass with basson = 0 :upside_down_face:

So maybe more like this I guess:

define :basn do |n, r|
      if basson == 1 then
        play n, release: r, cutoff: rrand(55, 125)
        sleep r
      else
        sleep r
      end
    end

Very true. Hate bugs. :slight_smile:

I think you could save yourself a lot of typing (or cut n paste at least), if you used
use_synth_defaults, and only 1 x if chordon == 1 then .

See below…

use_bpm 118

set_sched_ahead_time! 4

live_loop :met1 do
  sleep 1
end

kickon  = 1
hihaton = 1
rimon   = 1

chordon = 1
basson  = 1
bellon  = 1

with_fx :slicer, phase: 1, wave: 0, invert_wave: 1, mix: 0.9 do
  
  with_fx :level, amp: 0.15 do
    live_loop :housechords1, sync: :met1 do
      if chordon == 1 then
        use_synth :mod_fm
        use_synth_defaults pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01,
          divisor: 1, mod_range: 0.2, mod_wave: 3
        
        with_fx :pitch_shift, pitch: -3.9, reps: 2 do
          play chord(:a3, "m11")
          play chord(:a3, "m11"), pan: -1, mod_range: 0.3
          
          sleep 4
        end
        with_fx :pitch_shift, pitch: 7.1, reps: 4 do
          play chord(:f3, "m11"), decay: 2, mod_range: 0.3
          play chord(:f3, "m11"), pan: -1, decay: 2
          sleep 2
        end
        with_fx :pitch_shift, pitch: -1.9, reps: 2 do
          play chord(:f3, "m11")
          play chord(:f3, "m11"), pan: -1, mod_range: 0.3
          sleep 4
        end
        with_fx :pitch_shift, pitch: 5.1, reps: 4 do
          play chord(:f3, "m11"), decay: 2, mod_range: 0.3
          play chord(:f3, "m11"), pan: -1, decay: 2
          sleep 2
        end
      else
        sleep 1
      end
    end
  end
  
  with_fx :ping_pong, phase: 0.75 do
    with_fx :level, amp: 0.2 do
      live_loop :housechords, sync: :met1 do
        if chordon == 1 then
          use_synth :mod_fm
          use_synth_defaults pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01,
            divisor: 1, mod_range: 0.2, mod_wave: 3
          2.times do
            play (chord_invert(chord :f3, "m11"), 2)
            play chord(:f3, "m11"), pan: -1, mod_range: 0.3
            sleep 4
          end
          2.times do
            play (chord_invert(chord :c3, "m11"), 4), mod_range: 0.3
            play (chord_invert(chord :c3, "m11"), 3), pan: -1
          end
          2.times do
            play chord(:Eb3, "m11")
            play chord(:Eb3, "m11"), pan: -1,mod_range: 0.3
            sleep 4
          end
          2.times do
            play (chord_invert(chord :Bb2, "m11"), 2), mod_range: 0.3
            play (chord_invert(chord :Bb2, "m11"), 5), pan: -1, mod_range: 0.2
            sleep 4
          end
        else
          sleep 1
        end
      end
    end
  end
end

I’m having fun with this… I think I’m going to pinch the lot of it and make me some lofi…

My previous attempts have been okay, but this really works well…

Regards,

Eli…

1 Like

So, I’ve got a pretty much finished piece… added some :ixi_techno to
the bass and chords functions for variety, and put in my standard loop
control functions…

The thing is @Ludvig, I’m not an ‘innovator’ like you are… I can take
existing code and tinker it into something new or different, but I dont
have the basic skill of writing code that sounds good like you do.

Still, I’ll settle for ‘tinkering’ if thats all I can get.

Regards,

Eli…

#Original code by Ludvig. Loop control, bass_ixi and chord_ixi
# by Eli... 

use_bpm 118
set_sched_ahead_time! 4
# You can control loops from here or from scripted commands
# at the end of the code...
# loops = [1,1,1,1,1,1,1,0,0]
#loops =  [1,1,1,1,0,1,0,1,0]
loops =   [0,0,0,0,0,0,0,0,0]

kicks  = 0
hats = 1
rims   = 2
chords = 3
chords_ixi = 4
bass  = 5
bass_ixi = 6
bells  = 7
hiss = 8

bass_note  = [29,34,36,39,41,29,34,36,41,39,34,36,29,31,34,39,36,41,43,36,34,29,
              27,32,34,37,39,27,32,34,39,37,32,34,27,29,32,37,34,39,41,34,32,27]

bass_rel =   [0.75,0.75,1,1,0.5,0.75,0.75,1,0.5,0.5,0.5,0.75,0.75,1,1,0.5,0.75,0.75,1,0.5,0.5,0.5,
              0.75,0.75,1,1,0.5,0.75,0.75,1,0.5,0.5,0.5,0.75,0.75,1,1,0.5,0.75,0.75,1,0.5,0.5,0.5]

define :start_loop do |i|
  loops[i] = 1
end

define :stop_loop do |i|
  loops[i] = 0
end

define :stop_all do
  loops[0] = 0
  loops[1] = 0
  loops[2] = 0
  loops[3] = 0
  loops[4] = 0
  loops[5] = 0
  loops[6] = 0
  loops[7] = 0
  loops[8] = 0
end

define :pattern do |pattern|
  return pattern.ring.tick == "x"
end

define :bellp do |n, m|
  if loops[bells] == 1 then
    n.each.with_index do |n,id|
      sleep 2
      play n + 0.3
      sleep 0.1
      play n + 17
      sleep 0.4
      play n + 0.2
      sleep 0.1
      play n + 12
      sleep 0.9
      play m[id] + 0.2
      play m[id] + 24
      sleep 0.5
    end
  else
    sleep 1
  end
end

define :basn do |n, r|
  n.each.with_index do |n, id|
    # if loops[bass] is changed while this is playing, the next
    # line lets the define break out and return.
    if loops[bass] == 0 then
      return
    else
      play n, release: r[id], cutoff: rrand(55, 125)
      sleep r[id]
    end
  end
end

live_loop :met1 do
  sleep 1
end

live_loop :kicks, sync: :met1 do
  if loops[kicks] == 1 then
    with_swing -0.08, 2 do
      sample :bd_tek, rate: 0.8, sustain: 0, release: 0.3, amp: 0.8 if
      pattern "x---x---x---x---"
    end
    sleep 0.25
  else
    sleep 1
  end
end

live_loop :kick_soft, sync: :met1 do
  if loops[kicks] == 1 then
    with_swing -0.08, 2 do
      sample :bd_tek, rate: 0.7, sustain: 0, release: 0.2, amp: 0.2 if
      pattern "---------------x---------x------"
    end
    sleep 0.25
  else
    sleep 1
  end
end

live_loop :hh, sync: :met1 do
  if loops[hats] == 1 then
    with_swing -0.08, 2 do
      sample :drum_cymbal_closed, sustain: 0, release: 0.15, amp: 0.8, rate: 1.1 if pattern "--x---x---x---x-"
    end
    sleep 0.25
  else
    sleep 1
  end
end

live_loop :hh_short, sync: :met1 do
  if loops[hats] == 1 then
    with_swing -0.08, 2 do
      sample :drum_cymbal_pedal, sustain: 0, release: 0.05, pan: -0.4, amp: 0.3, start: 0.1 if pattern "--xx--x--xx--x-x"
    end
    sleep 0.25
  else
    sleep 1
  end
end

with_fx :reverb, damp: 1, mix: 0.3 do
  live_loop :rimshot, sync: :met1 do
    if loops[rims] == 1 then
      with_swing -0.08, 2 do
        sample :sn_generic, amp: 0.4, sustain: 0, release: 0.10 if pattern "----x-------x---"
      end
      sleep 0.25
    else
      sleep 1
    end
  end
end

live_loop :rimshot2, sync: :met1 do
  if loops[rims] == 1 then
    with_swing -0.08, 2 do
      sample :elec_filt_snare, sustain: 0, release: 0.10, pan: 0.4, rate: 0.5, amp: 0.2 if pattern "----x--x----x-------x--x-x--x---"
    end
    sleep 0.25
  else
    sleep 1
  end
end

with_fx :slicer, phase: 1, wave: 0, invert_wave: 1, mix: 0.9 do
  
  with_fx :level, amp: 0.15 do
    live_loop :housechords1, sync: :met1 do
      if loops[chords] == 1 then
        if loops[chords_ixi] == 1 then
          with_fx :ixi_techno, phase: 0.75 do
            use_synth :mod_fm
            use_synth_defaults pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01,
              divisor: 1, mod_range: 0.2, mod_wave: 3
            
            with_fx :pitch_shift, pitch: -3.9, reps: 2 do
              play chord(:a3, "m11")
              play chord(:a3, "m11"), pan: -1, mod_range: 0.3
              sleep 4
            end
            with_fx :pitch_shift, pitch: 7.1, reps: 4 do
              play chord(:f3, "m11"), decay: 2, mod_range: 0.3
              play chord(:f3, "m11"), pan: -1, decay: 2
              sleep 2
            end
            with_fx :pitch_shift, pitch: -1.9, reps: 2 do
              play chord(:f3, "m11")
              play chord(:f3, "m11"), pan: -1, mod_range: 0.3
              sleep 4
            end
            with_fx :pitch_shift, pitch: 5.1, reps: 4 do
              play chord(:f3, "m11"), decay: 2, mod_range: 0.3
              play chord(:f3, "m11"), pan: -1, decay: 2
              sleep 2
            end
          end
          
        else
          use_synth :mod_fm
          use_synth_defaults pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01,
            divisor: 1, mod_range: 0.2, mod_wave: 3
          
          with_fx :pitch_shift, pitch: -3.9, reps: 2 do
            play chord(:a3, "m11")
            play chord(:a3, "m11"), pan: -1, mod_range: 0.3
            sleep 4
          end
          with_fx :pitch_shift, pitch: 7.1, reps: 4 do
            play chord(:f3, "m11"), decay: 2, mod_range: 0.3
            play chord(:f3, "m11"), pan: -1, decay: 2
            sleep 2
          end
          with_fx :pitch_shift, pitch: -1.9, reps: 2 do
            play chord(:f3, "m11")
            play chord(:f3, "m11"), pan: -1, mod_range: 0.3
            sleep 4
          end
          with_fx :pitch_shift, pitch: 5.1, reps: 4 do
            play chord(:f3, "m11"), decay: 2, mod_range: 0.3
            play chord(:f3, "m11"), pan: -1, decay: 2
            sleep 2
          end
        end
        
      else
        sleep 1
      end
    end
  end
  
  with_fx :ping_pong, phase: 0.75 do
    with_fx :level, amp: 0.2 do
      live_loop :housechords, sync: :met1 do
        if loops[chords] == 1 then
          use_synth :mod_fm
          use_synth_defaults pan: 1, decay: 4, sustain_level: 0, sustain: 0, release: 0.01,
            divisor: 1, mod_range: 0.2, mod_wave: 3
          2.times do
            play (chord_invert(chord :f3, "m11"), 2)
            play chord(:f3, "m11"), pan: -1, mod_range: 0.3
            sleep 4
          end
          2.times do
            play (chord_invert(chord :c3, "m11"), 4), mod_range: 0.3
            play (chord_invert(chord :c3, "m11"), 3), pan: -1
          end
          2.times do
            play chord(:Eb3, "m11")
            play chord(:Eb3, "m11"), pan: -1,mod_range: 0.3
            sleep 4
          end
          2.times do
            play (chord_invert(chord :Bb2, "m11"), 2), mod_range: 0.3
            play (chord_invert(chord :Bb2, "m11"), 5), pan: -1, mod_range: 0.2
            sleep 4
          end
        else
          sleep 1
        end
      end
    end
  end
end

live_loop :Bassline, sync: :met1 do
  if loops[bass] == 1 then
    use_synth :tri
    if loops[bass_ixi] == 1 then
      with_fx :ixi_techno, phase: 0.75 do
        basn bass_note, bass_rel
      end
    else
      basn bass_note, bass_rel
    end
    
  else
    sleep 1
  end
end

with_fx :reverb, room: 1 do
  with_fx :ping_pong, phase: 0.75 do
    with_fx :lpf, cutoff: 130, pre_amp: 0.0625 do
      live_loop :lilmelo, sync: :met1 do
        if loops[bells] == 1 then
          use_synth :pluck
          bell_notes = [70,65,67,70,68,63,60,72]
          bell_rel = [67,63,65,58,65,61,65,70]
          
          bellp bell_notes, bell_rel
        else
          sleep 1
        end
      end
    end
  end
end

with_fx :reverb do
  live_loop :vinyl, sync: :met1 do
    if loops[hiss] == 1 then
      sample :vinyl_hiss, amp: 0.15
      sleep sample_duration :vinyl_hiss
    else
      sleep 1
    end
  end
end

start_loop hiss
sleep 4
start_loop rims
sleep 8
start_loop hats
sleep 8
start_loop chords
sleep 16
start_loop kicks
sleep 16
start_loop bass
sleep 32
start_loop bells
sleep 32
stop_loop bass
sleep 16
start_loop bass_ixi
start_loop bass
sleep 32
stop_loop bass
stop_loop bass_ixi
sleep 4
start_loop chords_ixi
sleep 32
stop_all


Amazing! Thanks for sharing this!