Performance Drums with MIDI Keyboard

Happy New Year

On the whole I’ve avoided trying to make SPi a MIDI playing instrument, opting for live coding instead. But I wrote this to see if it’s useful. I’ll try it in practice to see if it’s a good thing or not.

It’s to work with a 25-note midi keyboard. The idea is that you can pop this in a separate buffer use the get[:dmr][look] in the drumkit. Example in 2nd code block below.

In use, you can build a pattern by toggling beats on/off by pressing a midi key, and clear the pattern with the top key. In the log, it prints out the pattern like this so you can see what you’ve got so far.

{run: 9, time: 559.6633, thread: :live_loop_kybdmr}
 └─ "xx-x xx-- x--- x--- ---- ---- "
live_loop :kybdmr do
  use_real_time
  # Use a 25-note midi keyboard starting at C3 to toggle
  # beats on/off.  The top key resets the pattern.
  # Use 'get[:dmr][i]' in drum pattern.
  # e.g.
  #
  # p(2) if ("----------------"[look]=="x") or get[:dmr][look]
  #
  numbeats=24
  #Init
  if tick==0;x=[];for n in 0..numbeats-1;x[n]=false;end;set :dmr,x;end;
  
  #Get and copy the last pattern
  x=get[:dmr];y=[];
  for i in 0..numbeats-1;y[i]=x[i];end
  
  #Toggle beats based on note value, or reset
  i,v = sync "/midi:mpk_mini:0:1/note_on"
  if i>47 and i<48+numbeats
    j=i-48
    y[j] ? y[j]=false : y[j]=true
  elsif i==48+numbeats
    #Reset
    for j in 0..numbeats-1;y[j]=false;end
  end
  
  #Add a sleep to make sure the set happens after the get (above).
  sleep 0.1
  set :dmr,y
  
  #Print the pattern in x-x- notation
  s=""
  for i in 0..numbeats-1
    s+=y[i] ? "x" : "-"
    s+=" " if (i+1)%4==0
  end
  puts s
end
#Example drumkit
use_bpm 110

live_loop :drumtest do
  #stop
  cue :bar
  sleep 4
end

live_loop :drums do
  sync :bar
  a = 1.0
  s = [:bd_tek, :bass_voxy_hit_c, :elec_cymbal]
  
  define :p do |i|
    case i
    when 0
      sample s[i], beat_stretch: 1, amp: a*0.5
    when 1
      sample s[i], beat_stretch: 3, amp: a*0.2
    when 2
      sample s[i], beat_stretch: 0.25, amp: a*0.3
    end
  end
  
  with_fx :echo, mix: 0.1, phase: 0.75, decay: 12 do
    in_thread do
      16.times do
        tick
        p(0) if ("x-------x---x---"[look]=="x")
        p(1) if ("------x---x-----"[look]=="x")
        p(2) if ("----------------"[look]=="x") or get[:dmr][look]
        sleep 1.0/4
      end
    end
  end
end
2 Likes

Looks great. One of the plans going forward is to find ways to make little expressive pattern languages like this easier to write and share. I think there’s huge value in them :slight_smile:

2 Likes

Thanks @samaaron. As it goes, I’d forgotten all about this, got sidetracked onto so many other things.

I keep swinging between controlling SPi with midi vs using pure live coding. This season I’m back with live coding. But this does look quite interesting, I agree :smile:

It does lead to a different style of performance. Live coding leans towards a slower evoluation, using midi more rapid changes.

1 Like