I found this project with lots of test midi files. I downloaded them and tried midilib against them all. I’m also testing for these note events: ChannelPressure, Controller, KeySig, Marker, NoteOn, PitchBend, ProgramChange, Tempo, TimeSig. Here’s my code. I run this script in the Terminal, not Sonic-Pi.
load "/Users/jeng/midilib/lib/midilib.rb"
def open_midi_file(midi_file)
puts(midi_file)
seq = MIDI::Sequence.new()
File.open(midi_file, 'rb') do |file|
seq.read(file)
end
test_bpm = 80
seq.each_with_index do |track,idx|
tempoTrack = track.select { |e| e.is_a?(MIDI::Tempo) }
noteTrack = track.select { |e| e.is_a?(MIDI::NoteOn) }
keySigTrack = track.select { |e| e.is_a?(MIDI::KeySig) }
markerTrack = track.select { |e| e.is_a?(MIDI::Marker) }
timeSigTrack = track.select { |e| e.is_a?(MIDI::TimeSig) }
channelPressureTrack = track.select { |e| e.is_a?(MIDI::ChannelPressure) }
controllerTrack = track.select { |e| e.is_a?(MIDI::Controller) }
pitchBendTrack = track.select { |e| e.is_a?(MIDI::PitchBend) }
programChangeTrack = track.select { |e| e.is_a?(MIDI::ProgramChange) }
puts("------------------------")
if(tempoTrack.length > 0)
puts("tempoTrack")
puts(tempoTrack)
end
if(noteTrack.length > 0)
puts("noteTrack")
puts(noteTrack.length)
end
if(keySigTrack.length > 0)
puts("keySigTrack")
puts(keySigTrack)
end
if(markerTrack.length > 0)
puts("markerTrack")
puts(markerTrack.length)
end
if(timeSigTrack.length > 0)
puts("timeSigTrack")
puts(timeSigTrack)
end
if(channelPressureTrack.length > 0)
puts("channelPressureTrack")
puts(channelPressureTrack.length)
end
if(controllerTrack.length > 0)
puts("controllerTrack")
puts(controllerTrack.length)
end
if(pitchBendTrack.length > 0)
puts("pitchBendTrack")
puts(pitchBendTrack.length)
end
if(programChangeTrack.length > 0)
puts("programChangeTrack")
puts(programChangeTrack.length)
end
end
end
midi_files = Dir["/Users/jeng/test-midi-files/midi/*"]
midi_files.sort.each { |midi_file|
open_midi_file(midi_file)
}
It fails 19 tests, mainly tests involving corrupted midi files.
test-all-gm-percussion.mid
test-corrupt-file-missing-byte.mid
test-illegal-message-all.mid
test-illegal-message-f1-xx.mid
test-illegal-message-f2-xx-xx.mid
test-illegal-message-f3-xx.mid
test-illegal-message-f4.mid
test-illegal-message-f5.mid
test-illegal-message-f6.mid
test-illegal-message-f8.mid
test-illegal-message-f9.mid
test-illegal-message-fa.mid
test-illegal-message-fb.mid
test-illegal-message-fc.mid
test-illegal-message-fd.mid
test-illegal-message-fe.mid
test-non-midi-track.mid
test-sysex-7e-06-01-id-request.mid
test-syx-7e-06-01-id-request.syx
It passed 43 tests, though. These 2 files include the types of control I want to respond to.
test-rpn-00-00-pitch-bend-range.mid
test-rpn-00-05-modulation-depth-range.mid
Now I just need to figure out how to get Sonic-Pi to manipulate the signal based on the control data. I think I’d probably want to do something like this.
in_thread do
polyPressureTrack.each do |t|
sleep t.wait
control get(:v), amp: t.value/127.0
end
end
with_fx :level,amp: 1 do |v|
set :v,v
in_thread do
noteTrack.each do |e|
with_bpm test_bpm do
sleep e.wait
play e.note, sustain: e.sustain*0.8, decay: e.sustain*0.2, amp: e.velocity/127.0
# Do something with v
end
end
end
end