midi-message 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/midi-message.rb CHANGED
@@ -5,33 +5,36 @@
5
5
  #
6
6
  module MIDIMessage
7
7
 
8
+ module Event
9
+ end
10
+
8
11
  module Process
9
12
  end
10
13
 
11
- VERSION = "0.2.4"
14
+ VERSION = "0.3.0"
12
15
 
13
16
  end
14
17
 
15
- require 'yaml'
16
-
17
- # messages
18
-
19
- require 'midi-message/short_message'
20
- require 'midi-message/channel_message'
21
- require 'midi-message/constant'
22
- require 'midi-message/context'
23
- require 'midi-message/note_message'
24
- require 'midi-message/parser'
25
- require 'midi-message/system_message'
26
- require 'midi-message/system_exclusive'
27
- require 'midi-message/type_conversion'
18
+ # libs
19
+ require "forwardable"
20
+ require "yaml"
28
21
 
29
- # message processors
22
+ # messages (mixed format)
23
+ require "midi-message/short_message"
24
+ require "midi-message/channel_message"
25
+ require "midi-message/constant"
26
+ require "midi-message/context"
27
+ require "midi-message/note_message"
28
+ require "midi-message/parser"
29
+ require "midi-message/system_message"
30
+ require "midi-message/system_exclusive"
31
+ require "midi-message/type_conversion"
30
32
 
31
33
  # modules
32
34
  require "midi-message/process/processor"
33
35
 
34
36
  # classes
37
+ require "midi-message/event/note"
35
38
  require "midi-message/process/filter"
36
39
  require "midi-message/process/limit"
37
40
  require "midi-message/process/transpose"
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ module MIDIMessage
3
+
4
+ module Event
5
+
6
+ # an Event::Note is a pairing of a MIDI NoteOn and NoteOff message
7
+ # has a length that corresponds to sequencer ticks
8
+ class Note
9
+
10
+ extend Forwardable
11
+
12
+ attr_reader :start,
13
+ :finish,
14
+ :length
15
+
16
+ alias_method :duration, :length
17
+
18
+ def_delegators :start, :note
19
+
20
+ def initialize(start_message, duration, options = {})
21
+ @start = start_message
22
+ @length = duration
23
+
24
+ @finish = options[:finish] || start_message.to_note_off
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -11,45 +11,45 @@ module MIDIMessage
11
11
 
12
12
  attr_reader :bandwidth, :property, :reject
13
13
 
14
- def initialize(message, prop, bandwidth, options = {})
14
+ def initialize(prop, bandwidth, options = {})
15
15
  @bandwidth = [bandwidth].flatten
16
- @message = message
17
16
  @property = prop
18
17
  @reject = options[:reject] || false
19
- initialize_processor(message)
18
+
19
+ initialize_processor(options)
20
20
  end
21
21
 
22
- def process
23
- val = @message.send(@property)
24
- result = @bandwidth.map { |bw| val >= bw.min && val <= bw.max ? @message : nil }
25
- result.include?(@message) ^ @reject ? @message : nil
22
+ def process_single(message)
23
+ val = message.send(@property)
24
+ result = @bandwidth.map { |bw| val >= bw.min && val <= bw.max ? message : nil }
25
+ result.include?(message) ^ @reject ? message : nil
26
26
  end
27
27
 
28
28
  end
29
29
 
30
30
  class LowPassFilter < Filter
31
- def initialize(message, prop, max, options = {})
32
- super(message, prop, (0..max), options)
31
+ def initialize(prop, max, options = {})
32
+ super(prop, (0..max), options)
33
33
  end
34
34
  end
35
35
 
36
36
  class HighPassFilter < Filter
37
- def initialize(message, prop, min, options = {})
38
- super(message, prop, (min..127), options)
37
+ def initialize(prop, min, options = {})
38
+ super(prop, (min..127), options)
39
39
  end
40
40
  end
41
41
 
42
42
  class BandPassFilter < Filter
43
- def initialize(message, prop, accept_range, options = {})
43
+ def initialize(prop, accept_range, options = {})
44
44
  options[:reject] = false
45
- super(message, prop, accept_range, options)
45
+ super(prop, accept_range, options)
46
46
  end
47
47
  end
48
48
 
49
49
  class BandRejectFilter < Filter
50
- def initialize(message, prop, reject_range, options = {})
50
+ def initialize(prop, reject_range, options = {})
51
51
  options[:reject] = true
52
- super(message, prop, reject_range, options)
52
+ super(prop, reject_range, options)
53
53
  end
54
54
  end
55
55
  NotchFilter = BandRejectFilter
@@ -8,20 +8,25 @@ module MIDIMessage
8
8
 
9
9
  include Processor
10
10
 
11
- attr_reader :property, :range
11
+ attr_reader :property, :limit_to
12
+ alias_method :range, :limit_to
12
13
 
13
- def initialize(message, prop, range, options = {})
14
- @range = range
15
- @message = message
14
+ def initialize(prop, limit_to, options = {})
15
+ @limit_to = limit_to
16
16
  @property = prop
17
- initialize_processor(message)
17
+
18
+ initialize_processor(options)
18
19
  end
19
20
 
20
- def process
21
- val = @message.send(@property)
22
- @message.send("#{@property}=", @range.min) if val < @range.min
23
- @message.send("#{@property}=", @range.max) if val > @range.max
24
- @message
21
+ def process_single(message)
22
+ val = message.send(@property)
23
+ if @limit_to.kind_of?(Range)
24
+ message.send("#{@property}=", @limit_to.min) if val < @limit_to.min
25
+ message.send("#{@property}=", @limit_to.max) if val > @limit_to.max
26
+ elsif @limit_to.kind_of?(Numeric)
27
+ message.send("#{@property}=", @limit_to)
28
+ end
29
+ message
25
30
  end
26
31
 
27
32
  end
@@ -8,19 +8,27 @@ module MIDIMessage
8
8
 
9
9
  def self.included(base)
10
10
  base.extend(ClassMethods)
11
- base.send(:attr_reader, :message)
11
+ #base.send(:attr_reader, :message)
12
+ end
13
+
14
+ def process(messages = nil)
15
+ messages = @message unless @message.nil?
16
+ result = [messages].flatten.map { |message| process_single(message) }
17
+ result.kind_of?(Array) && result.size == 1 ? result.first : result
12
18
  end
13
19
 
14
20
  module ClassMethods
15
- def process(*a, &block)
16
- new(*a).process(&block)
21
+
22
+ def process(msg, *a, &block)
23
+ new(*a).process(msg, &block)
17
24
  end
25
+
18
26
  end
19
27
 
20
28
  private
21
29
 
22
- def initialize_processor(message)
23
- @message = message
30
+ def initialize_processor(options)
31
+ @message = options[:message]
24
32
  end
25
33
 
26
34
  end
@@ -10,17 +10,17 @@ module MIDIMessage
10
10
 
11
11
  attr_reader :factor, :property
12
12
 
13
- def initialize(message, prop, factor, options = {})
13
+ def initialize(prop, factor, options = {})
14
14
  @factor = factor
15
- @message = message
16
15
  @property = prop
17
- initialize_processor(message)
16
+
17
+ initialize_processor(options)
18
18
  end
19
19
 
20
- def process
21
- val = @message.send(@property)
22
- @message.send("#{@property}=", val + @factor)
23
- @message
20
+ def process_single(message)
21
+ val = message.send(@property)
22
+ message.send("#{@property}=", val + @factor)
23
+ message
24
24
  end
25
25
 
26
26
  end
data/test/test_filter.rb CHANGED
@@ -11,84 +11,84 @@ class FilterTest < Test::Unit::TestCase
11
11
  def test_high_pass_note_reject
12
12
  msg = MIDIMessage::NoteOn["C0"].new(0, 100)
13
13
  assert_equal(12, msg.note)
14
- outp = HighPassFilter.new(msg, :note, 20).process
14
+ outp = HighPassFilter.new(:note, 20).process(msg)
15
15
  assert_equal(nil, outp)
16
16
  end
17
17
 
18
18
  def test_high_pass_note_accept
19
19
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
20
20
  assert_equal(60, msg.note)
21
- outp = HighPassFilter.new(msg, :note, 20).process
21
+ outp = HighPassFilter.new(:note, 20).process(msg)
22
22
  assert_equal(msg, outp)
23
23
  end
24
24
 
25
25
  def test_low_pass_note_reject
26
26
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
27
27
  assert_equal(60, msg.note)
28
- outp = LowPassFilter.new(msg, :note, 50).process
28
+ outp = LowPassFilter.new(:note, 50).process(msg)
29
29
  assert_equal(nil, outp)
30
30
  end
31
31
 
32
32
  def test_low_pass_note_accept
33
33
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
34
34
  assert_equal(60, msg.note)
35
- outp = LowPassFilter.new(msg, :note, 100).process
35
+ outp = LowPassFilter.new(:note, 100).process(msg)
36
36
  assert_equal(msg, outp)
37
37
  end
38
38
 
39
39
  def test_band_pass_note_reject
40
40
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
41
41
  assert_equal(60, msg.note)
42
- outp = BandPassFilter.new(msg, :note, (20..50)).process
42
+ outp = BandPassFilter.new(:note, (20..50)).process(msg)
43
43
  assert_equal(nil, outp)
44
44
  end
45
45
 
46
46
  def test_band_pass_note_accept
47
47
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
48
48
  assert_equal(60, msg.note)
49
- outp = BandPassFilter.new(msg, :note, (20..100)).process
49
+ outp = BandPassFilter.new(:note, (20..100)).process(msg)
50
50
  assert_equal(msg, outp)
51
51
  end
52
52
 
53
53
  def test_band_reject_note_reject
54
54
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
55
55
  assert_equal(60, msg.note)
56
- outp = NotchFilter.new(msg, :note, (20..70)).process
56
+ outp = NotchFilter.new(:note, (20..70)).process(msg)
57
57
  assert_equal(nil, outp)
58
58
  end
59
59
 
60
60
  def test_band_reject_note_accept
61
61
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
62
62
  assert_equal(60, msg.note)
63
- outp = NotchFilter.new(msg, :note, (20..50)).process
63
+ outp = NotchFilter.new(:note, (20..50)).process(msg)
64
64
  assert_equal(msg, outp)
65
65
  end
66
66
 
67
67
  def test_multiband_note_reject
68
68
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
69
69
  assert_equal(60, msg.note)
70
- outp = Filter.new(msg, :note, [(20..30), (40..50)]).process
70
+ outp = Filter.new(:note, [(20..30), (40..50)]).process(msg)
71
71
  assert_equal(nil, outp)
72
72
  end
73
73
 
74
74
  def test_multiband_note_accept
75
75
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
76
76
  assert_equal(60, msg.note)
77
- outp = Filter.new(msg, :note, [(20..30), (50..70)]).process
77
+ outp = Filter.new(:note, [(20..30), (50..70)]).process(msg)
78
78
  assert_equal(msg, outp)
79
79
  end
80
80
 
81
81
  def test_multinotch_note_reject
82
82
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
83
83
  assert_equal(60, msg.note)
84
- outp = Filter.new(msg, :note, [(20..30), (55..65)], :reject => true).process
84
+ outp = Filter.new(:note, [(20..30), (55..65)], :reject => true).process(msg)
85
85
  assert_equal(nil, outp)
86
86
  end
87
87
 
88
88
  def test_multinotch_note_accept
89
89
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
90
90
  assert_equal(60, msg.note)
91
- outp = Filter.new(msg, :note, [(20..30), (40..50)], :reject => true).process
91
+ outp = Filter.new(:note, [(20..30), (40..50)], :reject => true).process(msg)
92
92
  assert_equal(msg, outp)
93
93
  end
94
94
 
data/test/test_limit.rb CHANGED
@@ -7,32 +7,39 @@ class LimitTest < Test::Unit::TestCase
7
7
  include MIDIMessage
8
8
  include MIDIMessage::Process
9
9
  include TestHelper
10
+
11
+ def test_numeric_range
12
+ msg = MIDIMessage::NoteOn["C0"].new(0, 100)
13
+ assert_equal(12, msg.note)
14
+ Limit.new(:note, 30).process(msg)
15
+ assert_equal(30, msg.note)
16
+ end
10
17
 
11
18
  def test_low_note
12
19
  msg = MIDIMessage::NoteOn["C0"].new(0, 100)
13
20
  assert_equal(12, msg.note)
14
- Limit.new(msg, :note, (20..50)).process
21
+ Limit.new(:note, (20..50)).process(msg)
15
22
  assert_equal(20, msg.note)
16
23
  end
17
24
 
18
25
  def test_high_note
19
26
  msg = MIDIMessage::NoteOn["C6"].new(0, 100)
20
27
  assert_equal(84, msg.note)
21
- Limit.new(msg, :note, (20..50)).process
28
+ Limit.new(:note, (20..50)).process(msg)
22
29
  assert_equal(50, msg.note)
23
30
  end
24
31
 
25
32
  def test_low_velocity
26
33
  msg = MIDIMessage::NoteOn["C0"].new(0, 10)
27
34
  assert_equal(10, msg.velocity)
28
- Limit.new(msg, :velocity, (30..110)).process
35
+ Limit.new(:velocity, (30..110)).process(msg)
29
36
  assert_equal(30, msg.velocity)
30
37
  end
31
38
 
32
39
  def test_high_velocity
33
40
  msg = MIDIMessage::NoteOn["C6"].new(0, 120)
34
41
  assert_equal(120, msg.velocity)
35
- Limit.new(msg, :velocity, (25..75)).process
42
+ Limit.new(:velocity, (25..75)).process(msg)
36
43
  assert_equal(75, msg.velocity)
37
44
  end
38
45
 
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class NoteEventTest < Test::Unit::TestCase
6
+
7
+ include MIDIMessage
8
+ include TestHelper
9
+
10
+ def test_create_event
11
+ msg = NoteOn.new(0, 0x40, 0x40)
12
+ event = Event::Note.new(msg, 10)
13
+ assert_equal(msg, event.start)
14
+ assert_equal(10, event.duration)
15
+ assert_equal(NoteOff, event.finish.class)
16
+ assert_equal(msg.note, event.finish.note)
17
+ assert_equal(msg.note, event.note)
18
+ end
19
+
20
+ def test_override_finish
21
+ msg = NoteOn.new(0, 0x40, 0x40)
22
+ msg2 = NoteOff.new(0, 0x40, 127)
23
+ event = Event::Note.new(msg, 5, :finish => msg2)
24
+ assert_equal(msg, event.start)
25
+ assert_equal(5, event.duration)
26
+ assert_equal(0x40, event.start.velocity)
27
+ assert_equal(NoteOff, event.finish.class)
28
+ assert_equal(0x40, event.finish.note)
29
+ assert_equal(127, event.finish.velocity)
30
+ end
31
+
32
+ end
@@ -11,28 +11,28 @@ class TransposeTest < Test::Unit::TestCase
11
11
  def test_transpose_note_up
12
12
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
13
13
  assert_equal(60, msg.note)
14
- Transpose.new(msg, :note, 5).process
14
+ Transpose.new(:note, 5).process(msg)
15
15
  assert_equal(65, msg.note)
16
16
  end
17
17
 
18
18
  def test_transpose_velocity_up
19
19
  msg = MIDIMessage::NoteOn["C4"].new(0, 82)
20
20
  assert_equal(82, msg.velocity)
21
- Transpose.new(msg, :velocity, 10).process
21
+ Transpose.new(:velocity, 10).process(msg)
22
22
  assert_equal(92, msg.velocity)
23
23
  end
24
24
 
25
25
  def test_transpose_note_down
26
26
  msg = MIDIMessage::NoteOn["C4"].new(0, 100)
27
27
  assert_equal(60, msg.note)
28
- Transpose.new(msg, :note, -5).process
28
+ Transpose.new(:note, -5).process(msg)
29
29
  assert_equal(55, msg.note)
30
30
  end
31
31
 
32
32
  def test_transpose_velocity_down
33
33
  msg = MIDIMessage::NoteOn["C4"].new(0, 82)
34
34
  assert_equal(82, msg.velocity)
35
- Transpose.new(msg, :velocity, -10).process
35
+ Transpose.new(:velocity, -10).process(msg)
36
36
  assert_equal(72, msg.velocity)
37
37
  end
38
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: midi-message
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-12 00:00:00.000000000Z
12
+ date: 2011-09-27 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: MIDI messages, objectified in Ruby
15
15
  email:
@@ -21,6 +21,7 @@ files:
21
21
  - lib/midi-message/channel_message.rb
22
22
  - lib/midi-message/constant.rb
23
23
  - lib/midi-message/context.rb
24
+ - lib/midi-message/event/note.rb
24
25
  - lib/midi-message/note_message.rb
25
26
  - lib/midi-message/parser.rb
26
27
  - lib/midi-message/process/filter.rb
@@ -39,6 +40,7 @@ files:
39
40
  - test/test_filter.rb
40
41
  - test/test_limit.rb
41
42
  - test/test_mutability.rb
43
+ - test/test_note_event.rb
42
44
  - test/test_parser.rb
43
45
  - test/test_processor.rb
44
46
  - test/test_short_message.rb