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 control
ing 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
end
set :ns, helper
end
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
use_real_time
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]
vn=(on.to_f/128)+3
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
end # live loop :midi_note_on
live_loop :midi_note_off do
use_real_time
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]
begin
control ns[note], gate: 0
rescue
puts 'Could not kill synth.'
end
ns[note] = nil
set :ns, ns
end
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
end
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.