public
Description: A customizable Ruby-based MIDI drum controller for the Wii remote and nunchuk on OS X
Homepage: http://studiobleep.com
Clone URL: git://github.com/jmileham/drumchuk.git
drumchuk / midi_in.rb
100644 61 lines (51 sloc) 1.508 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# This is a mild refactor of this code:
# http://github.com/gilesbowkett/rbcoremidi/blob/ca3fa0954f3064d92b68df94e7e597e34f95009b/midi_in.rb
 
# Doesn't slam the processor when capturing: rate limited (somewhat inelegantly) to 1KHz.
 
require 'coremidi'
 
class Controller < Struct.new(:controller, :data) ; end
class Note < Struct.new(:on_off, :note_number, :velocity) ; end
 
class MidiIn
  include CoreMIDI
 
  CAPTURE_INTERVAL= 0.001
 
  def initialize
    # Names are arbitrary
    client = CoreMIDI.create_client("SB")
    @port = CoreMIDI.create_input_port(client, "PortA")
  end
 
  def scan
    CoreMIDI.sources.each_with_index do |source, index|
      puts "source #{index}: #{source}"
    end
  end
 
  def link(source)
    connect_source_to_port(source, @port) # 0 is index into CoreMIDI.sources array
  end
 
  def capture
    time = Time.now
    while true
      prev_time = time
      time = Time.now
      interval = time - prev_time
      sleep(CAPTURE_INTERVAL - interval) unless interval > CAPTURE_INTERVAL
      if packets = new_data?
        yield parse(packets)
      end
    end
  end
 
  def parse(packets)
    packets.collect do |packet|
      outputs = []
      while (d = packet.data.slice!(0,3)).length > 0
        case d[0]
        when 144..146
          outputs << Note.new(:on, d[1], d[2])
        when 128..130
          outputs << Note.new(:off, d[1], d[2])
        when 176
          outputs << Controller.new(d[1], d[2])
        end
      end
      outputs
    end.flatten
  end
end