My first creation -- a funky groove

Here’s my very first sonic pi creation. It’s a funky groove, using just built-in samples.
I’m pretty happy with it. Let me know what you think.

# Funky groove.rb by Harry LeBlanc
# My first sonic pi composition!


use_debug false

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

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

chunk = 16
slab = 128

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
  sync :wtick
  
  [:a2, :b2, :e3, :e3].each do |thiskey|
    sleep whole * 256
    set :tonic, thiskey
    puts "key change to " + thiskey.to_s
  end
end

live_loop :arrange do
  sync :wtick
  
  (1..8).each do |i|
    
    puts "loop " + i.to_s
    case i
    
    
    when 1
      puts "init loop"
      set :playkick, 1
      sleep chunk
      
      set :playbeat, 1
      sleep chunk
      
      set :playtabla, 1
      sleep chunk
      
      set :playsafari, 1
      sleep chunk
      
      set :playbass, 1
      sleep chunk
      
      set :playguitar, 1
      sleep chunk
      
      set :playchords, 1
      sleep chunk
      
      set :playkalimba, 1
      sleep chunk
      
      set :playeuclid, 1
      sleep chunk
      
    when 8
      puts "breakout phase"
      
      set :playeuclid, -1
      sleep chunk
      
      set :playkalimba, -1
      sleep chunk
      
      set :playchords, -1
      sleep chunk
      
      set :playguitar, -1
      sleep chunk
      
      set :playbass, -1
      sleep chunk
      
      set :playsafari, -1
      sleep chunk
      
      set :playtabla, -1
      sleep chunk
      
      set :playbeat, -1
      
      sleep chunk
      
      set :playkick, -1
      sleep chunk
      
    else
      puts "normal loop"
      sleep slab
    end #case i
  end #each
  break if get[:playkick] == -1
end #liveloop




live_loop:kick do
  sync :dtick
  puts "kick should stop"  if get[:playkick] == -1
  break if get[:playkick] == -1
  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 #if playkick
  
end #liveloop





live_loop :beat do
  sync :qtick
  puts "beat should stop"  if get[:playbeat] == -1
  break if get[:playbeat] == -1
  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 #if one in 4
  end #if playbeat
end #liveloop


live_loop :tabla do
  sync :ftick
  puts "tabla should stop"  if get[:playtabla] == -1
  break if get[:playtabla] == -1
  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_ne].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









live_loop :safari do
  sync :dtick
  puts "safari should stop"  if get[:playsafari] == -1
  break if get[:playsafari] == -1
  if get[:playsafari] == 1 then
    sample :loop_safari, beat_stretch:  16
    sleep whole * 32
    
  end #if play
  
end #liveloop






live_loop :bass do
  sync :htick
  puts "bass should stop"  if get[:playbass] == -1
  break if get[:playbass] == -1
  if get[:playbass] == 1 then
    
    use_synth [:blade, :bass_foundation, :pulse, :tb303, :subpulse].choose
    play scale(get[:tonic] - (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 #if playbass
  
end #liveloop







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




live_loop :chords do
  sync :ftick
  puts "chords should stop"  if get[:playchords] == -1
  break if get[:playchords] == -1
  if get[:playchords] == 1 then
    
    ##| 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(get[:tonic] + octave, :minor7), \
          chord(get[:tonic] + octave + min3, :sus2), \
          chord(get[:tonic] + octave - wstep, '6'), \
          chord(get[:tonic] + 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
  puts "kalimba should stop"  if get[:playkalimba] == -1
  break if get[:playkalimba] == -1
  if get[:playkalimba] == 1 then
    
    
    use_synth :kalimba
    
    [\
     chord(get[:tonic], :m9, num_octaves: 2), \
     chord(get[:tonic ]  + octave+ min3, :sus2, num_octaves: 2), \
     chord(get[:tonic ] + octave- wstep, '6', num_octaves: 2), \
     chord(get[:tonic ] + 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 :euclid do
  sync :ftick
  puts "euclid should stop"  if get[:playeuclid] == -1
  break if get[:playeuclid] == -1
  if get[:playeuclid] == 1 then
    
    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(get[:tonic] + (octave * 2), :minor_pentatonic, num_octaves:2).choose \
              , amp: rrand(0.8, 1.3) \
              , 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






3 Likes

Fantastic Harry! @HarryLeBlanc It’s a complex and exciting musical patch…Lot of sounds playing around with an also complex rythm! Bravo, There are plenty of interesting things to learn and reuse…Thanks for sharing Harry! :smile:

Funky indeed! You’ve been busy :wink:

1 Like

Yeah, the combination of eighth notes, quarter notes and dotted quarter notes, chosen randomly, really brings the funk.

1 Like

What’s the programming language you’ve used the most? I’m seeing conventions that must have become habit over time.

Jeez, I’ve used so many over the years. C, Basic, Java/j2ee/ejb, Lisp, Perl, Tcl, Pascal, Fortran, Cobol, C++, Javascript, Sql, T-sql, Pl-sql, shell scripting… I’ve lost track over the years.
I haven’t done much programming in the last 20 years, though. I changed careers to become a psychotherapist. I’m just getting back to it now. I’m having a ton of fun with sonic-pi – I’m just putting the finishing touches on some super useful methods, to easily apply lfos and envelopes to any parameter that’s slideable, on either samples or synths; to arrange whole scores with a concise syntax, to handle the ugly math needed to pitch stretch while keeping tempo, etc.
I also plan on doing some projects in kontakt ksp scripting. I have an idea for a samchillian (if you don’t know what that is, it’s worth googling), and for a way to smoothly blend between 4 arbitrary voices, a la Cube or Fables or Lore.
I’m also working on a new musical about Mary Magdalene, and am part of a musical duo doing instrumental music that’s hard to describe but is basically psychedelic classical.
Oh, and working fulltime as a therapist.
So many projects, so little time! But it’s fun. :slight_smile:

1 Like