Record and feedback

I was experimenting with recording my live loops, cutting and shuffling the recording and overlaying them back on top of the loop. The idea was that I could have a fairly simple drum loop (with some interesting timing) but by having these re-ordered previous runs of the loop accumulating run after run build up into interesting patterns.

The core part of the machinery being:

def with_record(bufs)
  # Re-record one of the buffers
  buf = bufs.delete_at(rand_i(bufs.length))
  puts "recording #{buf.path.split("/")[-1]}"
  with_fx :record, buffer: buf do

def play_cuts(bufs, length, cuts, amp: 1.0)
  # Cut up one of the buffers and play pieces back in shuffled order
  play_buf = bufs.choose
  puts "playing #{play_buf.path.split("/")[-1]}"
  at line(0, length, steps: cuts), (0...cuts).to_a.shuffle do |s|
    sample play_buf, start: s.to_f/length, finish: (s.to_f + length.to_f/cuts)/length, amp: amp

And then using it something like this:

live_loop :drums do
  bufs = make_buffers(:drums, 4, 4)
  with_record bufs do
    # some seed drum patterns to play here, will be recorded to one of the buffers

    # play back a shffled buffer, with some fx and reduced levels so they fade out over multiple recordings
    with_fx :bitcrusher, mix: 0.3 do
      play_cuts bufs, 4, 8, amp: 0.7

I think the drum part sounded kind of cool. I didn’t get as far in applying it to the melody or harmony - it may be slightly harder as you may either have to use a single chord or accept some dissonance. But perhaps there is a clever way to make it work…

Lovely work, thanks for sharing!

Whilst I’m here, I should point out that using def and $global_vars might work in the current version of Sonic Pi but is not officially supported and may stop working without warning in future versions.

Please prefer define and using set and get over global variables to ensure your code remains future proof :slight_smile:

1 Like

This is cool. I looked over the code and I think it has one or two issues.
First you don’t define keyboard_keys used in a puts statement (easily commented out)
Secondly your play_cuts function in certain situations produces start: opt values greater than 1 (which is not possible) and causes errors.
otherwise, some nice ideas which I will play with further.

@robin.newman - thanks for taking a look and spotting that error!

@samaaron - thanks for the tip on get/set! I guess they are a few extra keystrokes, but I think setting up these control variables is not something you usually do in a hurry. As for define, I didn’t know how you could specify parameters to the defined, but it seems to just work:

define :foo do |x, y, arg:0|
  puts x, y, arg
foo(1, 2, arg:3)

Worth adding an example with arguments to the documentation?