midi-message 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad978e231aef5931892a5fb96573c4e709f3ad64
4
- data.tar.gz: 53cc976f50cb5c4d5ba619f3d3d4b1aaa10a71d9
3
+ metadata.gz: 539a68753cc6d0c17fed06cae7103d1f7b0f95a8
4
+ data.tar.gz: 2b3949261e5e5fa7061cb7860c325d6a0c067efb
5
5
  SHA512:
6
- metadata.gz: 6a51573df46bbee8bc764be4d139b52c7366c192c0402846bb3cae67efa4e5cbfa87b4ad1982765fc80f2d6d3e088c857f6ee5a9b0bc6d0f68a2e2ca08f3a931
7
- data.tar.gz: c7264a018b5b523aeaa7391ab2f387aab0a2a9b66f583692bdd05a12eb7968c9ebc0ef120de61cfe82ab42e6f8c3301522fe957f6fc9ca9b5969d387ff8f1c5c
6
+ metadata.gz: edc31730d5ffc918377fb342f63c3ce095b187e8f17ed194a47756a701286f3a78b7d7102f05850a2eeca59108d90ec3ed1a9cb5e0e78294cea699c6ede821b6
7
+ data.tar.gz: 86c8b7a355baa3a46d93ca63294a512538dc8478fbea9844be00c917916fe1d13fde7bd19eb599a2cf61fefff021df45f853a43622d6bb8380322f03136e6e30
data/lib/midi-message.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  #
6
6
  module MIDIMessage
7
7
 
8
- VERSION = "0.4.1"
8
+ VERSION = "0.4.2"
9
9
 
10
10
  end
11
11
 
@@ -46,8 +46,8 @@ module MIDIMessage
46
46
  protected
47
47
 
48
48
  def self.included(base)
49
- base.include(ShortMessage)
50
- base.extend(ClassMethods)
49
+ base.send(:include, ShortMessage)
50
+ base.send(:extend, ClassMethods)
51
51
  end
52
52
 
53
53
  private
@@ -11,12 +11,12 @@ module MIDIMessage
11
11
  end
12
12
 
13
13
  def find(name)
14
- @constants.find { |const| const.key.to_s.downcase.eql?(name.to_s.downcase) }
14
+ @constants.find { |const| const.key.to_s.downcase == name.to_s.downcase }
15
15
  end
16
16
  alias_method :[], :find
17
17
 
18
18
  def find_by_value(value)
19
- @constants.find { |const| const.value.to_s.downcase.eql?(value.to_s.downcase) }
19
+ @constants.find { |const| const.value.to_s.downcase == value.to_s.downcase }
20
20
  end
21
21
 
22
22
  def self.all
@@ -26,7 +26,7 @@ module MIDIMessage
26
26
 
27
27
  def self.[](key)
28
28
  ensure_initialized
29
- @groups.find { |g| g.key.to_s.downcase.eql?(key.to_s.downcase) }
29
+ @groups.find { |g| g.key.to_s.downcase == key.to_s.downcase }
30
30
  end
31
31
 
32
32
  private
@@ -1,7 +1,3 @@
1
- #!/usr/bin/env ruby
2
- #
3
- #
4
-
5
1
  module MIDIMessage
6
2
 
7
3
  class Context
@@ -109,13 +109,13 @@ module MIDIMessage
109
109
 
110
110
  attr_reader :data
111
111
 
112
- def initialize(*a)
113
- options = a.last.kind_of?(Hash) ? a.pop : {}
112
+ def initialize(*args)
113
+ options = args.last.kind_of?(Hash) ? args.pop : {}
114
114
  @const = options[:const]
115
- id = @const.nil? ? a.shift : @const.value
115
+ id = @const.nil? ? args.shift : @const.value
116
116
  id = strip_redundant_nibble(id)
117
117
  initialize_short_message(0xF, id)
118
- @data = [a[0], a[1]]
118
+ @data = args.slice(0..1)
119
119
  end
120
120
 
121
121
  end
@@ -129,10 +129,10 @@ module MIDIMessage
129
129
 
130
130
  DISPLAY_NAME = "System Realtime"
131
131
 
132
- def initialize(*a)
133
- options = a.last.kind_of?(Hash) ? a.pop : {}
132
+ def initialize(*args)
133
+ options = args.last.kind_of?(Hash) ? args.pop : {}
134
134
  @const = options[:const]
135
- id = @const.nil? ? a[0] : @const.value
135
+ id = @const.nil? ? args.first : @const.value
136
136
  id = strip_redundant_nibble(id)
137
137
  initialize_short_message(0xF, id)
138
138
  end
@@ -149,7 +149,7 @@ module MIDIMessage
149
149
  # A command message is identified by having a status byte equal to 0x12
150
150
  class Command
151
151
 
152
- include SystemExclusive::InstanceMethods
152
+ include SystemExclusive
153
153
 
154
154
  attr_accessor :data
155
155
  alias_method :value, :data
@@ -158,7 +158,11 @@ module MIDIMessage
158
158
 
159
159
  def initialize(address, data, options = {})
160
160
  # store as a byte if it's a single byte
161
- @data = (data.kind_of?(Array) && data.length.eql?(1)) ? data[0] : data
161
+ @data = if data.kind_of?(Array) && data.length == 1
162
+ data.first
163
+ else
164
+ data
165
+ end
162
166
  initialize_sysex(address, options)
163
167
  end
164
168
 
@@ -168,7 +172,7 @@ module MIDIMessage
168
172
  # A request message is identified by having a status byte equal to 0x11
169
173
  class Request
170
174
 
171
- include SystemExclusive::InstanceMethods
175
+ include SystemExclusive
172
176
 
173
177
  attr_reader :size
174
178
  alias_method :value, :size
@@ -176,19 +180,23 @@ module MIDIMessage
176
180
  TypeByte = 0x11
177
181
 
178
182
  def initialize(address, size, options = {})
179
- self.size = (size.kind_of?(Array) && size.length.eql?(1)) ? size[0] : size
183
+ self.size = if size.kind_of?(Array) && size.count == 1
184
+ size.first
185
+ else
186
+ size
187
+ end
180
188
  initialize_sysex(address, options)
181
189
  end
182
190
 
183
- def size=(val)
191
+ def size=(value)
184
192
  # accepts a Numeric or Array but
185
193
  # must always store value as an array of three bytes
186
194
  size = []
187
- if val.kind_of?(Array) && val.size <= 3
188
- size = val
189
- elsif val.kind_of?(Numeric) && (((val + 1) / 247) <= 2)
195
+ if value.kind_of?(Array) && value.size <= 3
196
+ size = value
197
+ elsif value.kind_of?(Numeric) && (value + 1) / 247 <= 2
190
198
  size = []
191
- div, mod = *val.divmod(247)
199
+ div, mod = *value.divmod(247)
192
200
  size << mod unless mod.zero?
193
201
  div.times { size << 247 }
194
202
  end
@@ -4,7 +4,7 @@ module MIDIMessage
4
4
  module NoteMessage
5
5
 
6
6
  def self.included(base)
7
- base.include(ChannelMessage)
7
+ base.send(:include, ChannelMessage)
8
8
  end
9
9
 
10
10
  # The octave number of the note
@@ -1,48 +1,46 @@
1
- #!/usr/bin/env ruby
2
- #
3
-
4
1
  module MIDIMessage
5
2
 
6
- # very simple parsing
7
- # for more advanced parsing check out {nibbler}[http://github.com/arirusso/nibbler]
8
- class Parser
9
-
10
- # can take either a hex string eg Parser.new("904040")
11
- # or bytes eg Parser.new(0x90, 0x40, 0x40)
12
- # or an array of bytes eg Parser.new([0x90, 0x40, 0x40])
13
- def initialize(*a)
14
- @data = case a.first
15
- when Array then a.first
16
- when Numeric then a
17
- when String then TypeConversion.hex_string_to_numeric_byte_array(a.first)
18
- end
19
- end
20
-
21
- def parse
22
- first_nibble = ((@data.first & 0xF0) >> 4)
23
- second_nibble = (@data.first & 0x0F)
24
- case first_nibble
25
- when 0x8 then NoteOff.new(second_nibble, @data[1], @data[2])
26
- when 0x9 then NoteOn.new(second_nibble, @data[1], @data[2])
27
- when 0xA then PolyphonicAftertouch.new(second_nibble, @data[1], @data[2])
28
- when 0xB then ControlChange.new(second_nibble, @data[1], @data[2])
29
- when 0xC then ProgramChange.new(second_nibble, @data[1])
30
- when 0xD then ChannelAftertouch.new(second_nibble, @data[1])
31
- when 0xE then PitchBend.new(second_nibble, @data[1], @data[2])
32
- when 0xF then case second_nibble
33
- when 0x0 then SystemExclusive.new(*@data)
34
- when 0x1..0x6 then SystemCommon.new(second_nibble, @data[1], @data[2])
35
- when 0x8..0xF then SystemRealtime.new(second_nibble)
36
- else nil
37
- end
38
- else nil
3
+ # Very simple parsing
4
+ # for more advanced parsing check out {nibbler}[http://github.com/arirusso/nibbler]
5
+ class Parser
6
+
7
+ # Can take either a hex string eg Parser.new("904040")
8
+ # or bytes eg Parser.new(0x90, 0x40, 0x40)
9
+ # or an array of bytes eg Parser.new([0x90, 0x40, 0x40])
10
+ def initialize(*args)
11
+ @data = case args.first
12
+ when Array then args.first
13
+ when Numeric then args
14
+ when String then TypeConversion.hex_string_to_numeric_byte_array(args.first)
15
+ end
16
+ end
17
+
18
+ # Parse the data and return a message
19
+ def parse
20
+ first_nibble = ((@data.first & 0xF0) >> 4)
21
+ second_nibble = (@data.first & 0x0F)
22
+ case first_nibble
23
+ when 0x8 then NoteOff.new(second_nibble, @data[1], @data[2])
24
+ when 0x9 then NoteOn.new(second_nibble, @data[1], @data[2])
25
+ when 0xA then PolyphonicAftertouch.new(second_nibble, @data[1], @data[2])
26
+ when 0xB then ControlChange.new(second_nibble, @data[1], @data[2])
27
+ when 0xC then ProgramChange.new(second_nibble, @data[1])
28
+ when 0xD then ChannelAftertouch.new(second_nibble, @data[1])
29
+ when 0xE then PitchBend.new(second_nibble, @data[1], @data[2])
30
+ when 0xF then case second_nibble
31
+ when 0x0 then SystemExclusive.new(*@data)
32
+ when 0x1..0x6 then SystemCommon.new(second_nibble, @data[1], @data[2])
33
+ when 0x8..0xF then SystemRealtime.new(second_nibble)
34
+ else nil
39
35
  end
36
+ else nil
40
37
  end
41
-
42
- end
43
-
44
- def self.parse(*a)
45
- Parser.new(*a).parse
46
- end
38
+ end
39
+
40
+ end
41
+
42
+ def self.parse(*args)
43
+ Parser.new(*args).parse
44
+ end
47
45
 
48
46
  end
@@ -35,7 +35,7 @@ module MIDIMessage
35
35
  protected
36
36
 
37
37
  def self.included(base)
38
- base.extend(ClassMethods)
38
+ base.send(:extend, ClassMethods)
39
39
  end
40
40
 
41
41
  def update
@@ -3,6 +3,10 @@ module MIDIMessage
3
3
  # MIDI System-Exclusive Messages (SysEx)
4
4
  module SystemExclusive
5
5
 
6
+ def self.included(base)
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
6
10
  # Common SysEx data that a message class will contain
7
11
  module InstanceMethods
8
12
 
@@ -15,16 +19,17 @@ module MIDIMessage
15
19
  # an array of message parts. multiple byte parts will be represented as an array of bytes
16
20
  def to_a(options = {})
17
21
  omit = options[:omit] || []
22
+ node = @node.to_a(options) unless @node.nil? || omit.include?(:node)
18
23
  # this may need to be cached when properties are updated
19
24
  # might be worth benchmarking
20
25
  [
21
- self.class::StartByte,
22
- (@node.to_a(options) unless @node.nil? || omit.include?(:node)),
26
+ start_byte,
27
+ node,
23
28
  (type_byte unless omit.include?(:type)),
24
29
  [address].compact.flatten,
25
30
  [value].compact.flatten,
26
31
  (checksum unless omit.include?(:checksum)),
27
- self.class::EndByte
32
+ end_byte
28
33
  ].compact
29
34
  end
30
35
 
@@ -39,7 +44,12 @@ module MIDIMessage
39
44
 
40
45
  # string representation of the object's bytes
41
46
  def to_hex_s
42
- to_bytes.map { |b| s = b.to_s(16); s.length.eql?(1) ? "0#{s}" : s }.join.upcase
47
+ strings = to_bytes.map do |byte|
48
+ string = byte.to_s(16)
49
+ string = "0#{string}" if string.length == 1
50
+ string
51
+ end
52
+ strings.join.upcase
43
53
  end
44
54
  alias_method :to_bytestr, :to_hex_s
45
55
 
@@ -48,6 +58,14 @@ module MIDIMessage
48
58
  end
49
59
  alias_method :verbose_name, :name
50
60
 
61
+ def start_byte
62
+ self.class::StartByte
63
+ end
64
+
65
+ def end_byte
66
+ self.class::EndByte
67
+ end
68
+
51
69
  def type_byte
52
70
  self.class::TypeByte
53
71
  end
@@ -55,8 +73,9 @@ module MIDIMessage
55
73
  # alternate method from
56
74
  # http://www.2writers.com/eddie/TutSysEx.htm
57
75
  def checksum
58
- sum = (address + [value].flatten).inject { |a, b| a + b }
59
- (128 - sum.divmod(128)[1])
76
+ sum = (address + [value].flatten).inject(&:+)
77
+ mod = sum.divmod(128)[1]
78
+ 128 - mod
60
79
  end
61
80
 
62
81
  private
@@ -78,20 +97,25 @@ module MIDIMessage
78
97
  attr_accessor :data
79
98
 
80
99
  def initialize(data, options = {})
81
- @data = (data.kind_of?(Array) && data.length.eql?(1)) ? data[0] : data
100
+ @data = if data.kind_of?(Array) && data.length == 1
101
+ data.first
102
+ else
103
+ data
104
+ end
82
105
  initialize_sysex(nil, options)
83
106
  end
84
107
 
85
108
  # an array of message parts. multiple byte parts will be represented as an array of bytes
86
109
  def to_a(options = {})
87
110
  omit = options[:omit] || []
111
+ node = @node.to_a(options) unless @node.nil? || omit.include?(:node)
88
112
  # this may need to be cached when properties are updated
89
113
  # might be worth benchmarking
90
114
  [
91
- self.class::StartByte,
92
- (@node.to_a(options) unless @node.nil? || omit.include?(:node)),
115
+ start_byte,
116
+ node,
93
117
  @data,
94
- self.class::EndByte
118
+ end_byte
95
119
  ].compact
96
120
  end
97
121
 
@@ -109,16 +133,17 @@ module MIDIMessage
109
133
  def initialize(manufacturer, options = {})
110
134
  @device_id = options[:device_id]
111
135
  @model_id = options[:model_id]
112
- @manufacturer_id = manufacturer.kind_of?(Numeric) ? manufacturer : Constant.find("Manufacturer", manufacturer).value
136
+ @manufacturer_id = get_manufacturer_id(manufacturer)
113
137
  end
114
138
 
115
139
  def to_a(options = {})
116
- omit = options[:omit] || []
117
- [
118
- (@manufacturer_id unless omit.include?(:manufacturer) || omit.include?(:manufacturer_id)),
119
- (@device_id unless omit.include?(:device) || omit.include?(:device_id)),
120
- (@model_id unless omit.include?(:model) || omit.include?(:model_id))
121
- ].compact
140
+ omit = options[:omit] || []
141
+ properties = [:manufacturer, :device, :model].map do |property|
142
+ unless omit.include?(property) || omit.include?("#{property.to_s}_id")
143
+ instance_variable_get("@#{property.to_s}_id")
144
+ end
145
+ end
146
+ properties.compact
122
147
  end
123
148
 
124
149
  # this message takes a prototype message, copies it, and returns the copy with its node set
@@ -143,6 +168,17 @@ module MIDIMessage
143
168
  request
144
169
  end
145
170
 
171
+ private
172
+
173
+ def get_manufacturer_id(manufacturer)
174
+ if manufacturer.kind_of?(Numeric)
175
+ manufacturer
176
+ else
177
+ const = Constant.find("Manufacturer", manufacturer)
178
+ const.value
179
+ end
180
+ end
181
+
146
182
  end
147
183
 
148
184
  # Convert raw MIDI data to SysEx message objects
@@ -151,7 +187,7 @@ module MIDIMessage
151
187
  start_status = bytes.shift
152
188
  end_status = bytes.pop
153
189
 
154
- if start_status.eql?(0xF0) && end_status.eql?(0xF7)
190
+ if start_status == 0xF0 && end_status == 0xF7
155
191
 
156
192
  type_byte = bytes[3]
157
193
 
@@ -4,7 +4,7 @@ module MIDIMessage
4
4
  module SystemMessage
5
5
 
6
6
  def self.included(base)
7
- base.include(ShortMessage)
7
+ base.send(:include, ShortMessage)
8
8
  end
9
9
 
10
10
  # In the case of something like SystemCommon.new(0xF2, 0x00, 0x08), the first nibble F is redundant because
@@ -5,8 +5,13 @@ module MIDIMessage
5
5
 
6
6
  extend self
7
7
 
8
+ # Convert an array of hex nibbles to an array of numeric bytes
9
+ # eg ["9", "0", "4", "0"] to [0x90, 0x40]
10
+ #
11
+ # @param [Array<String>] An array of hex nibbles eg ["9", "0", "4", "0"]
12
+ # @return [Array<Fixnum] An array of numeric bytes eg [0x90, 0x40]
8
13
  def hex_chars_to_numeric_byte_array(nibbles)
9
- nibbles = nibbles.dup
14
+ nibbles = nibbles.dup # Don't mess with the input
10
15
  # get rid of last nibble if there's an odd number
11
16
  # it will be processed later anyway
12
17
  nibbles.slice!(nibbles.length-2, 1) if nibbles.length.odd?
@@ -18,30 +23,57 @@ module MIDIMessage
18
23
  bytes
19
24
  end
20
25
 
21
- # Convert byte str to byte array
22
- def hex_string_to_numeric_byte_array(str)
23
- str = str.dup
26
+ # Convert byte string to an array of numeric bytes
27
+ # eg. "904040" to [0x90, 0x40, 0x40]
28
+ # @param [String] string A string representing hex digits eg "904040"
29
+ # @return [Array<Fixnum>] An array of numeric bytes eg [0x90, 0x40, 0x40]
30
+ def hex_string_to_numeric_byte_array(string)
31
+ string = string.dup
24
32
  bytes = []
25
- until str.eql?("")
26
- bytes << str.slice!(0, 2).hex
33
+ until string.length == 0
34
+ bytes << string.slice!(0, 2).hex
27
35
  end
28
36
  bytes
29
37
  end
30
38
 
31
- # Converts a string of hex digits to bytes
32
- def hex_str_to_hex_chars(str)
33
- str.split(//)
39
+ # Convert a string of hex digits to an array of nibbles
40
+ # eg. "904040" to ["9", "0", "4", "0", "4", "0"]
41
+ # @param [String] string A string representing hex digits eg "904040"
42
+ # @return [Array<String>] An array of hex nibble chars eg ["9", "0", "4", "0", "4", "0"]
43
+ def hex_str_to_hex_chars(string)
44
+ string.split(//)
34
45
  end
35
46
 
47
+ # Convert an array of numeric bytes to a string of hex digits
48
+ # eg. [0x90, 0x40, 0x40] to "904040"
49
+ # @param [Array<Fixnum>] bytes An array of numeric bytes eg [0x90, 0x40, 0x40]
50
+ # @return [String] A string representing hex digits eg "904040"
36
51
  def numeric_byte_array_to_hex_string(bytes)
37
- bytes.map { |b| s = b.to_s(16); s.length.eql?(1) ? "0#{s}" : s }.join.upcase
52
+ string_bytes = bytes.map do |byte|
53
+ string = byte.to_s(16)
54
+ string = "0#{string}" if string.length == 1
55
+ string
56
+ end
57
+ string_bytes.join.upcase
38
58
  end
39
59
 
60
+ # Convert a numeric byte to hex chars
61
+ # eg 0x90 to ["9", "0"]
62
+ # @param [Fixnum] num A numeric byte eg 0x90
63
+ # @return [Array<String>] An array of hex nibble chars eg ["9", "0"]
40
64
  def numeric_byte_to_hex_chars(num)
41
- [((num & 0xF0) >> 4), (num & 0x0F)].map { |n| n.to_s(16) }
65
+ nibbles = numeric_byte_to_nibbles(num)
66
+ nibbles.map { |n| n.to_s(16) }
67
+ end
68
+
69
+ # Convert a numeric byte to nibbles
70
+ # eg 0x90 to [0x9, 0x0]
71
+ # @param [Fixnum] num A numeric byte eg 0x90
72
+ # @return [Array<Fixnum>] An array of nibbles eg [0x9, 0x0]
73
+ def numeric_byte_to_nibbles(num)
74
+ [((num & 0xF0) >> 4), (num & 0x0F)]
42
75
  end
43
76
 
44
-
45
77
  end
46
78
 
47
79
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: midi-message
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Russo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-01 00:00:00.000000000 Z
11
+ date: 2014-09-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Objects and classes for dealing with MIDI messages.
14
14
  email: