class MTK::IO::JSoundInput

Provides realtime MIDI input for JRuby via the jsound gem. @note This class is optional and only available if you require ‘mtk/midi/jsound_input’.

It depends on the 'jsound' gem.

Attributes

device[R]

Public Class Methods

devices() click to toggle source
# File lib/mtk/io/jsound_input.rb, line 13
def self.devices
  @devices ||= ::JSound::Midi::INPUTS.devices
end
devices_by_name() click to toggle source
# File lib/mtk/io/jsound_input.rb, line 17
def self.devices_by_name
  @devices_by_name ||= devices.each_with_object( Hash.new ){|device,hash| hash[device.description] = device }
end
new(input_device, options={}) click to toggle source
# File lib/mtk/io/jsound_input.rb, line 24
def initialize(input_device, options={})
  @device = input_device
  @recorder = ::JSound::Midi::Devices::Recorder.new(false)
  @device.open
end

Public Instance Methods

name() click to toggle source
# File lib/mtk/io/jsound_input.rb, line 30
def name
  @device.description
end
record(options={}) click to toggle source
# File lib/mtk/io/jsound_input.rb, line 34
def record(options={})
  if options[:monitor]
    @monitor = ::JSound::Midi::Devices::Monitor.new
    @device >> [@monitor, @recorder]
  else
    @device >> @recorder
  end

  @recorder.clear
  @recorder.start
end
stop() click to toggle source
# File lib/mtk/io/jsound_input.rb, line 46
def stop
  @recorder.stop
end
to_timeline(options={}) click to toggle source
# File lib/mtk/io/jsound_input.rb, line 50
def to_timeline(options={})
  bpm = options.fetch :bmp, 120
  beats_per_second = bpm.to_f/60
  timeline = MTK::Events::Timeline.new
  note_ons = {}
  start = nil

  @recorder.messages_with_timestamps.each do |message,time|
    start = time unless start
    time -= start
    time /= beats_per_second

    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

    next if message_type == :unknown # Ignore garbage messages

    case message_type
      when :note_on
        note_ons[message.pitch] = [message,time]

      when :note_off
        if note_ons.has_key? message.pitch
          note_on, start_time = note_ons.delete(message.pitch)
          duration = time - start_time
          note = MTK::Events::Note.from_midi(note_on.pitch, note_on.velocity, duration, message.channel)
          timeline.add time,note
        end

      else timeline.add time, MTK::Events::Parameter.from_midi([message_type, message.channel], message.data1, message.data2)
    end
  end

  timeline.quantize! options[:quantize] if options.key? :quantize
  timeline.shift_to! options[:shift_to] if options.key? :shift_to

  timeline
end