Ambient Live Coding Improvisation with Sonic Pi

I’m working on a live ambient set that uses Sonic Pi to do asynchronous/un-quantized live looping/sampling. All of the sounds are played on the OP1 synthesizer/sampler and recorded into buffers using with_fx :record + live_audio. The buffers are then sampled, stretched, sliced, and manipulated in live_loops. Finally, the loops are sent to Ableton Live (using Loopback) where they are mixed and additional effects are applied. I’m also using a LaunchControlXL to arm the recording buffers in Sonic Pi and control levels and fx sends in Ableton.

The code and tracks below are some examples of my results so far. Thanks for taking a look/listen!

use_bpm 80

T = 1.0

count = (ring "1", "2", "3", "4", "5", "6", "7", "8")

rec1 = false
rec2 = false
rec3 = false
rec4 = false
rec5 = false


live_loop :midi_control do
  use_real_time
  v = sync "/midi/launch_control_xl/3/1/control_change"
  
  if v[0] == 36 and v[1] > 1
    rec1 = true
    print "BUFFER ONE ARMED"
  else
    rec1 = false
  end
  
  if v[0] == 42 and v[1] > 1
    rec2 = true
    print "BUFFER TWO ARMED"
  else
    rec2 = false
  end
  
  if v[0] == 43 and v[1] > 1
    rec3 = true
    print "BUFFER THREE ARMED"
  else
    rec3 = false
  end
  
  if v[0] == 44 and v[1] > 1
    rec4 = true
    print "BUFFER FOUR ARMED"
  else
    rec4 = false
  end
  
  if v[0] == 57 and v[1] > 1
    rec5 = true
    print "BUFFER FIVE ARMED"
  else
    rec5 = false
  end
end

live_loop :ticker do
  cue :tick
  sleep T
end

live_loop :metro, sync: :tick do
  print count.tick(:count)
  sleep T
end


###ONE###

live_loop :recorder1, sync: :tick do
  if rec1 == true
    print "RECORDING BUFFER ONE"
    with_fx :record, buffer: buffer(:buff_one) do
      with_fx :level, amp: 2 do
        live_audio :mic
        sleep T*16
      end
    end
  else
    sleep T*8
  end
end

live_loop :player1, sync: :tick do
  with_fx :sound_out_stereo, output: 3 do
    with_fx :pitch_shift, mix: 0.5, pitch: 12, window_size: 2 do
      sample buffer[:buff_one], rate: -0.5, rpitch: 0
    end
    sleep T*8
  end
end

live_loop :player1_2, sync: :tick do
  num_slices = 50
  with_fx :sound_out_stereo, output: 5 do
    sample buffer[:buff_one], slice: rrand(0,50), pan: rrand(-1,1) if one_in(2)
    sample buffer[:buff_one], slice: rrand(0,50), pan: rrand(-1,1), rpitch: 12, amp: 0.7 if one_in(4)
    sleep T/2
  end
end


###TWO##

live_loop :recorder2, sync: :tick do
  if rec2 == true
    print "RECORDING BUFFER TWO"
    with_fx :record, buffer: buffer(:buff_two) do
      with_fx :level, amp: 2 do
        live_audio :mic
        sleep T*16
      end
    end
  else
    sleep T*8
  end
end

live_loop :player2, sync: :tick do
  with_fx :sound_out_stereo, output: 7 do
    with_fx :pitch_shift, mix: 1, pitch: 12, window_size: 4 do
      sample buffer[:buff_two], rate: 1, rpitch: -5
    end
    sleep T*8
  end
end

live_loop :player2_2, sync: :tick do
  num_slices = 40
  s = rrand(0, 0.7)
  t = rrand(0.05, 0.3)
  e = s + t
  a = rrand(0.5, 1.0)
  with_fx :sound_out_stereo, output: 9 do
    with_fx :pitch_shift, mix: 0.5, pitch: 12, window_size: 0.1, time_dis: 0.5 do
      sample buffer[:buff_two], start: s, finish: e, pan: rrand(-1,1), rpitch: -5, rate: -0.5
      sleep T*2
    end
  end
end


###THREE###

live_loop :recorder3, sync: :tick do
  if rec3 == true
    print "RECORDING BUFFER THREE"
    with_fx :record, buffer: buffer(:buff_three) do
      with_fx :level, amp: 2 do
        live_audio :mic
        sleep T*16
      end
    end
  else
    sleep T*8
  end
end

live_loop :player3, sync: :tick do
  with_fx :sound_out_stereo, output: 11 do
    with_fx :ixi_techno, cutoff_min: 70, cutoff_max: 120, res: 0.2, phase: 7 do
      3.times do
        sample buffer[:buff_three], rate: 1, rpitch: 0
        sleep T*8
      end
    end
    2.times do
      sample buffer[:buff_three], rate: 1, rpitch: 7
      sleep T*4
    end
    
  end
end



###FOUR###

live_loop :recorder4, sync: :tick do
  if rec4 == true
    print "RECORDING BUFFER FOUR"
    with_fx :record, buffer: buffer(:buff_four) do
      with_fx :level, amp: 2 do
        live_audio :mic
        sleep T*16
      end
    end
  else
    sleep T*8
  end
end

live_loop :player4, sync: :tick  do
  with_fx :sound_out_stereo, output: 13 do
    sample buffer[:buff_four], rpitch: (ring 0, 0, 3, -2).tick
    sleep T*8
  end
end

###FIVE###

live_loop :recorder5, sync: :tick do
  if rec5 == true
    print "RECORDING BUFFER FIvE"
    with_fx :record, buffer: buffer(:buff_five) do
      with_fx :level, amp: 2 do
        live_audio :mic
        sleep T*16
      end
    end
  else
    sleep T*8
  end
end

live_loop :player5, sync: :tick  do
  with_fx :sound_out_stereo, output: 15 do
    with_fx :reverb, mix: 1, room: 0.9 do
      sample buffer[:buff_five],  rate: 1, rpitch: 24, amp: 0.2 if one_in(2)
    end
    sleep T*16
  end
end
4 Likes

This is very interesting. Great way of utilising Sonic Pi into a wider system.
It inspires me to have a go with this technique.

1 Like

It’s really an interesting sound ! Really reminds me of the tape-loop experiments of Brian Eno.

1 Like

Thanks Robin! I’ve been super impressed by your TouchOSC creations and it has me dreaming of creating a TouchOSC based interface for this kind of live sample looping/slicing in Sonic Pi (ala mlr from monome).

Thanks, that’s a huge compliment! I’m definitely inspired by a lot of those early tape looping/manipulating experiments, particularly the work of Carl Stone.

Hi @mattholamieux,

I am also interested in that stuff (see my Live Looper for SP, which is still alpha and work in progress as I do only have limeted time ressources).

If you are interested we could exchange, what we have so far … I have also a pre-alpha sketch of a sampling application for SP, which I currently control via Beatstep.

My plans are to control these applications via a Grid. I own an Adafruit Unztrument, which I still have to learn to program; I am also planning to buy a Monome Grid (which seems to have already some support for SP); so we definitely do share some ideas and the enthusiasm for things like mlr.

1 Like

Hi @Martin!

Wow, your Live Looper looks really promising! I will be sure to follow your progress. I’d also love to know how you’re able to integrate the Grid, if you do indeed get one.

At the moment, I don’t really have anything to share beyond the very simple code I put in my original post. I am hoping to create a TouchOSC interface to toggle recording/playback and control various parameters of the sampled audio, though I’m not sure when I’ll have time to work on this.

I’m not an experienced coder, so I’m sure I will really benefit from looking at your code and concept/schematics. When I do get around to working on this, I will probably have a ton of questions for you!

1 Like