class MTK::IO::UniMIDIInput
Provides realtime MIDI
input for MRI/YARV Ruby via the unimidi gem. @note This class is optional and only available if you require ‘mtk/midi/unimidi_input’.
It depends on the 'unimidi' gem.
Attributes
device[R]
recording[R]
thread[R]
Public Class Methods
devices()
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 14 def self.devices @devices ||= ::UniMIDI::Input.all.reject{|d| d.name.strip.empty? } end
devices_by_name()
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 18 def self.devices_by_name @devices_by_name ||= devices.each_with_object( Hash.new ){|device,hash| hash[device.name] = device } end
new(input_device, options={})
click to toggle source
# File lib/mtk/io/midi_input.rb, line 57 def initialize(input_device, options={}) @device = input_device @device.open @options = options end
new(input_device, options={})
click to toggle source
Calls superclass method
MTK::IO::MIDIInput::new
# File lib/mtk/io/unimidi_input.rb, line 25 def initialize(input_device, options={}) super @open_time = Time.now.to_f end
Public Instance Methods
record(options={})
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 30 def record(options={}) @recording = [] unless options[:append] and @recording monitor = options[:monitor] stop @thread = Thread.new do @start_time = Time.now.to_f loop do @device.gets.each do |data| puts data if monitor record_raw_data data end sleep 0.001 end end time_limit = options[:time_limit] if time_limit puts "Blocking current thread for #{time_limit} seconds to record MIDI input." @thread.join(time_limit) end end
stop()
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 53 def stop Thread.kill @thread if @thread end
to_timeline(options={})
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 57 def to_timeline(options={}) return nil if not @recording bpm = options.fetch :bmp, 120 beats_per_second = bpm.to_f/60 timeline = MTK::Events::Timeline.new note_ons = {} start = nil @recording.each do |message, time| start ||= time time -= start time /= beats_per_second if message.is_a? MTK::Events::Event timeline.add time,message unless message.type == :unknown else message_type = message.type message_type = :note_off if message_type == :note_on and message.velocity == 0 # TODO: this will need to be made more robust when we support off velocities case message_type when :note_on pitch = message.pitch note_ons[pitch] = [message,time] when :note_off pitch = message.pitch if note_ons.has_key? pitch note_on, start_time = note_ons.delete(pitch) duration = time - start_time note = MTK::Events::Note.from_midi pitch, note_on.velocity, duration timeline.add time,note end end end end timeline.quantize! options[:quantize] if options.key? :quantize timeline.shift_to! options[:shift_to] if options.key? :shift_to timeline end
Private Instance Methods
record_raw_data(raw)
click to toggle source
# File lib/mtk/io/unimidi_input.rb, line 105 def record_raw_data raw status, data1, data2 = *raw[:data] # the 3 bytes of raw message data message = ( case status & 0xF0 when 0x80 then OpenStruct.new({:type => :note_off, :pitch => data1, :velocity => data2}) when 0x90 then OpenStruct.new({:type => :note_on, :pitch => data1, :velocity => data2}) else MTK::Events::Parameter.from_midi(status,data1,data2) end ) time = raw[:timestamp]/1000 - (@start_time - @open_time) @recording << [message, time] end