MIDI keyboard with gated synths

I have been working a bit on Robin’s keyboard driver. I had a lot of fun with it, but found 2 points for improvement: There is a certain likelihood for a »runaway synth«, i. e. a synth that keeps playing, because the note_off is missed, or to be precise, not properly recorded for timing issues. Also, emulating a gated synth by controling it down to amp: 0 somehow doesn’t feel right.

»Gated« means that the synth has a gated envelope and a gate: option to control it. A gated synth is started with the gate open and sustained until the gate is set to 0 (with control), which will induce the release phase.

So, here’s a different sketch (but read the notes below …):

# Polyphonic midi input program with sustained notes
# Ben Marx, February 2023
# based Robin Newman's programme, November 2017:
# https://in-thread.sonic-pi.net/t/polyphonic-gated-synth-for-sonic-pi-3-works-on-a-pi3/452
# https://gist.github.com/rbnpi/ebedd26d61180230db891ccbd9d74971

use_debug false

load_synthdef "<PATH_TO_THE_GATED_SYNTHDEFS>/sonic-pi-winwood_lead_gated.scsyndef"

set :synth, 'sonic-pi-winwood_lead_gated'

if get[:ns].nil? then
  set :ns, []#array to store note playing references
  helper = {}
  128.times do |i|
    helper[i]= nil

  set :ns, helper

ns = {}
# Deep copy; time state elements are immutable
get(:ns).each{|key, value| ns[key] = value}

white_key_scale = scale(0, :major, num_octaves: 12)
current_scale = scale(12, :major, num_octaves: 12)

with_fx :reverb, room: 0.8,mix: 0.6 do #add some reverb
  live_loop :midi_note_on do
    note, on = sync "/midi:mpk_mini_3_mpk_mini_3_midi_1_*/note_on"
    white_key_index = white_key_scale.to_a.index(note)
    unless white_key_index.nil?
      note = current_scale[white_key_index]
      use_synth get(:synth)
      x = play note, amp: vn #start playing note
      ns[note] = x #store reference to note in ns array
      set :ns, ns
  end # live loop :midi_note_on
  live_loop :midi_note_off do
    note, on = sync "/midi:mpk_mini_3_mpk_mini_3_midi_1_*/note_off"
    white_key_index = white_key_scale.to_a.index(note)
    unless white_key_index.nil?
      note = current_scale[white_key_index]
        control ns[note], gate: 0
        puts 'Could not kill synth.'
      ns[note] = nil
      set :ns, ns
  end # live loop :midi_note_off
  live_loop :pitch_bend do #get current pitchbend value adjusted in range -12 to +12 (octave)
    b = sync "/midi:mpk_mini_3_mpk_mini_3_midi_1_*/pitch_bend" #change to match your controller
    ns.each do |note, sth|
      unless sth.nil?
        control sth, note: note + (b[0]-8192).to_f/8192*24
  end # live loop pitch_bend
end #reverb

Some notes, I think important:

  • Vary rarely, this may be liable to »runaway synths«, i. e. synths that are not stored in the ns var and hence can never get killed, unless you Alt-S (stop all runs).
  • Unlike in Robins solution, runaway synths will not run for 100 beats, but forever. The probability, I think, is now lower, but you sure get one if you Alt-R (re-run) while a key is held. There is a workaround, though, particularly for live performances: Just run this in a Sonic Pi of its own, so that stopping will only affect this Sonic Pi instance, while others continue running. I think using several SP in parallel should be supported on most (all?) operating systems.
  • You need real gated synths, i. e. standard synths that SP comes along with, won’t do. Using them will end up in cacophony, as they will never terminate.
  • Gated synths are non-standard in SP. One of the basic requirements for the standard synths is for them to be self-terminating. Some of them (and I hope more in future) can be found here, at current just the piano (which admittedly benefits little from this approach, for its plucked nature), the tonewheel organ, and the Winwood lead synth. In order to use them, copy them somewhere on your file system where SP can access them and use them as described in the code above.
  • You may have noticed the white_key_scale thingy in the code. This has nothing to do with the synths as such, but rather with me being a piano keyboard noob. This construction just maps any (note) key to C major, so I can play anything with the white keys only, and it always sound right. I have never understood, why one would squeeze some black keys between the white keys anyway.