midilib 2.0.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ChangeLog +2 -1
- data/Credits +44 -2
- data/README.rdoc +42 -33
- data/Rakefile +36 -53
- data/TODO.rdoc +13 -2
- data/examples/from_scratch.rb +4 -6
- data/examples/measures_mbt.rb +11 -11
- data/examples/print_program_changes.rb +11 -11
- data/examples/reader2text.rb +191 -190
- data/examples/seq2text.rb +18 -18
- data/examples/split.rb +21 -20
- data/examples/strings.rb +15 -15
- data/examples/transpose.rb +41 -42
- data/install.rb +53 -34
- data/lib/midilib/consts.rb +406 -408
- data/lib/midilib/event.rb +335 -306
- data/lib/midilib/info.rb +5 -7
- data/lib/midilib/io/midifile.rb +424 -452
- data/lib/midilib/io/seqreader.rb +187 -192
- data/lib/midilib/io/seqwriter.rb +151 -147
- data/lib/midilib/measure.rb +78 -80
- data/lib/midilib/mergesort.rb +39 -0
- data/lib/midilib/sequence.rb +99 -86
- data/lib/midilib/track.rb +71 -118
- data/lib/midilib/utils.rb +17 -20
- data/lib/midilib.rb +5 -5
- data/test/event_equality.rb +50 -52
- data/test/test_event.rb +120 -124
- data/test/test_io.rb +107 -40
- data/test/test_mergesort.rb +37 -0
- data/test/test_midifile.rb +6 -19
- data/test/test_sequence.rb +64 -52
- data/test/test_track.rb +126 -155
- data/test/test_varlen.rb +23 -27
- metadata +20 -22
data/test/event_equality.rb
CHANGED
@@ -5,77 +5,75 @@
|
|
5
5
|
# classes. If someone disagrees, it would be trivial to move them there.
|
6
6
|
|
7
7
|
module MIDI
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@time_from_start == an_obj.time_from_start
|
15
|
-
end
|
8
|
+
class Event
|
9
|
+
def ==(other)
|
10
|
+
other.instance_of?(self.class) &&
|
11
|
+
@status == other.status &&
|
12
|
+
@delta_time == other.delta_time &&
|
13
|
+
@time_from_start == other.time_from_start
|
16
14
|
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
17
|
+
class ChannelEvent
|
18
|
+
def ==(other)
|
19
|
+
super(other) && @channel == other.channel
|
22
20
|
end
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
23
|
+
class NoteEvent < ChannelEvent
|
24
|
+
def ==(other)
|
25
|
+
super(other) &&
|
26
|
+
@note == other.note && @velocity == other.velocity
|
29
27
|
end
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
30
|
+
class Controller < ChannelEvent
|
31
|
+
def ==(other)
|
32
|
+
super(other) &&
|
33
|
+
@controller == other.controller && @value == other.value
|
36
34
|
end
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
37
|
+
class ProgramChange < ChannelEvent
|
38
|
+
def ==(other)
|
39
|
+
super(other) && @program == other.program
|
42
40
|
end
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
43
|
+
class ChannelPressure < ChannelEvent
|
44
|
+
def ==(other)
|
45
|
+
super(other) && @pressure == other.pressure
|
48
46
|
end
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
49
|
+
class PitchBend < ChannelEvent
|
50
|
+
def ==(other)
|
51
|
+
super(other) && @value == other.value
|
54
52
|
end
|
53
|
+
end
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
55
|
+
class SystemExclusive < SystemCommon
|
56
|
+
def ==(other)
|
57
|
+
super(other) && @data == other.data
|
60
58
|
end
|
59
|
+
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
61
|
+
class SongPointer < SystemCommon
|
62
|
+
def ==(other)
|
63
|
+
super(other) && @pointer == other.pointer
|
66
64
|
end
|
65
|
+
end
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
67
|
+
class SongSelect < SystemCommon
|
68
|
+
def ==(other)
|
69
|
+
super(other) && @song == other.song
|
72
70
|
end
|
71
|
+
end
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
73
|
+
class MetaEvent < Event
|
74
|
+
def ==(other)
|
75
|
+
super(other) && @meta_type == other.meta_type &&
|
76
|
+
@data == other.data
|
79
77
|
end
|
80
|
-
|
78
|
+
end
|
81
79
|
end
|
data/test/test_event.rb
CHANGED
@@ -7,131 +7,127 @@ require 'test/unit'
|
|
7
7
|
require 'midilib'
|
8
8
|
|
9
9
|
class EventTester < Test::Unit::TestCase
|
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
|
-
end
|
57
|
-
|
58
|
-
def test_pitch_bend
|
59
|
-
e = MIDI::PitchBend.new(0, 128)
|
60
|
-
b = e.data_as_bytes
|
61
|
-
assert_equal(0, b[1]) # lsb, 7 bits
|
62
|
-
assert_equal(1, b[2]) # msb, 7 bits
|
63
|
-
|
64
|
-
e.value = (3 << 7) + 42
|
65
|
-
b = e.data_as_bytes
|
66
|
-
assert_equal(42, b[1]) # lsb, 7 bits
|
67
|
-
assert_equal(3, b[2]) # msb, 7 bits
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_quantize
|
71
|
-
e = MIDI::NoteOn.new(0, 64, 64, 0)
|
72
|
-
e.quantize_to(80)
|
73
|
-
assert_equal(0, e.time_from_start)
|
74
|
-
|
75
|
-
e.time_from_start = 1
|
76
|
-
e.quantize_to(80)
|
77
|
-
assert_equal(0, e.time_from_start)
|
78
|
-
|
79
|
-
e.time_from_start = 70
|
80
|
-
e.quantize_to(80)
|
81
|
-
assert_equal(80, e.time_from_start)
|
82
|
-
|
83
|
-
e.time_from_start = 100
|
84
|
-
e.quantize_to(80)
|
85
|
-
assert_equal(80, e.time_from_start)
|
86
|
-
|
87
|
-
e.time_from_start = 398
|
88
|
-
e.quantize_to(80)
|
89
|
-
assert_equal(400, e.time_from_start)
|
90
|
-
|
91
|
-
e.time_from_start = 405
|
92
|
-
e.quantize_to(80)
|
93
|
-
assert_equal(400, e.time_from_start)
|
94
|
-
|
95
|
-
e.time_from_start = 439
|
96
|
-
e.quantize_to(80)
|
97
|
-
assert_equal(400, e.time_from_start)
|
98
|
-
|
99
|
-
e.time_from_start = 440
|
100
|
-
e.quantize_to(80)
|
101
|
-
assert_equal(480, e.time_from_start)
|
102
|
-
|
103
|
-
e.time_from_start = 441
|
104
|
-
e.quantize_to(80)
|
105
|
-
assert_equal(480, e.time_from_start)
|
10
|
+
def test_note_on
|
11
|
+
e = MIDI::NoteOn.new
|
12
|
+
assert_equal(MIDI::NOTE_ON, e.status)
|
13
|
+
assert_equal(0, e.channel)
|
14
|
+
assert_equal(64, e.note)
|
15
|
+
assert_equal(64, e.velocity)
|
16
|
+
assert_equal(0, e.delta_time)
|
17
|
+
assert_equal(0, e.time_from_start)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_to_s
|
21
|
+
e = MIDI::NoteOn.new
|
22
|
+
assert_equal('0: ch 00 on 40 40', e.to_s)
|
23
|
+
e.print_decimal_numbers = true
|
24
|
+
assert_equal('0: ch 0 on 64 64', e.to_s)
|
25
|
+
e.print_note_names = true
|
26
|
+
assert_equal('0: ch 0 on E4 64', e.to_s)
|
27
|
+
e.print_decimal_numbers = false
|
28
|
+
assert_equal('0: ch 00 on E4 40', e.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_pitch_bend
|
32
|
+
e = MIDI::PitchBend.new(0, 128)
|
33
|
+
b = e.data_as_bytes
|
34
|
+
assert_equal(0, b[1]) # lsb, 7 bits
|
35
|
+
assert_equal(1, b[2]) # msb, 7 bits
|
36
|
+
|
37
|
+
e.value = (3 << 7) + 42
|
38
|
+
b = e.data_as_bytes
|
39
|
+
assert_equal(42, b[1]) # lsb, 7 bits
|
40
|
+
assert_equal(3, b[2]) # msb, 7 bits
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_quantize_1
|
44
|
+
e = MIDI::NoteOn.new
|
45
|
+
e.quantize_to(4)
|
46
|
+
assert_equal(0, e.time_from_start)
|
47
|
+
|
48
|
+
# Each value in this array is the expected quantized value of
|
49
|
+
# its index in the array.
|
50
|
+
|
51
|
+
# Test with quantize_to(4)
|
52
|
+
[0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 16].each_with_index do |after, before|
|
53
|
+
e.time_from_start = before
|
54
|
+
e.quantize_to(4)
|
55
|
+
assert_equal(after, e.time_from_start)
|
106
56
|
end
|
107
57
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
58
|
+
# Test with quantize_to(6)
|
59
|
+
[0, 0, 0, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12,
|
60
|
+
18, 18, 18, 18, 18, 18, 24].each_with_index do |after, before|
|
61
|
+
e.time_from_start = before
|
62
|
+
e.quantize_to(6)
|
63
|
+
assert_equal(after, e.time_from_start)
|
114
64
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_quantize_2
|
68
|
+
e = MIDI::NoteOn.new(0, 64, 64, 0)
|
69
|
+
e.quantize_to(80)
|
70
|
+
assert_equal(0, e.time_from_start)
|
71
|
+
|
72
|
+
e.time_from_start = 1
|
73
|
+
e.quantize_to(80)
|
74
|
+
assert_equal(0, e.time_from_start)
|
75
|
+
|
76
|
+
e.time_from_start = 70
|
77
|
+
e.quantize_to(80)
|
78
|
+
assert_equal(80, e.time_from_start)
|
79
|
+
|
80
|
+
e.time_from_start = 100
|
81
|
+
e.quantize_to(80)
|
82
|
+
assert_equal(80, e.time_from_start)
|
83
|
+
|
84
|
+
e.time_from_start = 398
|
85
|
+
e.quantize_to(80)
|
86
|
+
assert_equal(400, e.time_from_start)
|
87
|
+
|
88
|
+
e.time_from_start = 405
|
89
|
+
e.quantize_to(80)
|
90
|
+
assert_equal(400, e.time_from_start)
|
91
|
+
|
92
|
+
e.time_from_start = 439
|
93
|
+
e.quantize_to(80)
|
94
|
+
assert_equal(400, e.time_from_start)
|
95
|
+
|
96
|
+
e.time_from_start = 440
|
97
|
+
e.quantize_to(80)
|
98
|
+
assert_equal(480, e.time_from_start)
|
99
|
+
|
100
|
+
e.time_from_start = 441
|
101
|
+
e.quantize_to(80)
|
102
|
+
assert_equal(480, e.time_from_start)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_meta_strings
|
106
|
+
e = MIDI::MetaEvent.new(MIDI::META_TEXT, [97, 98, 99])
|
107
|
+
assert_equal([97, 98, 99], e.data)
|
108
|
+
assert_equal('abc', e.data_as_str)
|
109
|
+
|
110
|
+
assert_equal([MIDI::META_EVENT, MIDI::META_TEXT, 3, 97, 98, 99], e.data_as_bytes)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_meta_event_string_in_ctor
|
114
|
+
e = MIDI::MetaEvent.new(MIDI::META_TEXT, 'abc')
|
115
|
+
assert_equal([97, 98, 99], e.data)
|
116
|
+
assert_equal('abc', e.data_as_str)
|
117
|
+
assert_equal([MIDI::META_EVENT, MIDI::META_TEXT, 3, 97, 98, 99], e.data_as_bytes)
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_meta_event_data_assignment
|
121
|
+
foobar_as_array = [102, 111, 111, 98, 97, 114]
|
122
|
+
|
123
|
+
e = MIDI::MetaEvent.new(MIDI::META_TEXT, [97, 98, 99])
|
124
|
+
e.data = 'foobar'
|
125
|
+
assert_equal('foobar', e.data_as_str)
|
126
|
+
assert_equal(foobar_as_array, e.data)
|
127
|
+
|
128
|
+
e.data = nil
|
129
|
+
e.data = foobar_as_array
|
130
|
+
assert_equal('foobar', e.data_as_str)
|
131
|
+
assert_equal(foobar_as_array, e.data)
|
132
|
+
end
|
137
133
|
end
|
data/test/test_io.rb
CHANGED
@@ -7,57 +7,124 @@ $LOAD_PATH[0, 0] = File.dirname(__FILE__)
|
|
7
7
|
|
8
8
|
require 'test/unit'
|
9
9
|
require 'midilib'
|
10
|
+
require 'midilib/consts'
|
10
11
|
require 'event_equality'
|
11
12
|
|
12
13
|
class IOTester < Test::Unit::TestCase
|
14
|
+
SEQ_TEST_FILE = File.join(File.dirname(__FILE__), 'test.mid')
|
15
|
+
OUTPUT_FILE = 'testout.mid'
|
16
|
+
TEMPFILE = '/tmp/midilib_test.mid'
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
t0.each_with_index { | ev0, i |
|
22
|
-
assert_equal(ev0, t1.events[i], 'events differ')
|
23
|
-
}
|
24
|
-
assert_equal(t0.instrument, t1.instrument)
|
25
|
-
end
|
26
|
-
|
27
|
-
def compare_sequences(s0, s1)
|
28
|
-
assert_equal(s0.name, s1.name, 'sequence names differ')
|
29
|
-
assert_equal(s0.tracks.length, s1.tracks.length,
|
30
|
-
'number of tracks differ')
|
31
|
-
s0.each_with_index { | track0, i |
|
32
|
-
compare_tracks(track0, s1.tracks[i])
|
33
|
-
}
|
34
|
-
end
|
18
|
+
def compare_tracks(t0, t1)
|
19
|
+
assert_equal(t0.name, t1.name, 'track names differ')
|
20
|
+
assert_equal(t0.events.length, t1.events.length,
|
21
|
+
'number of track events differ')
|
22
|
+
t0.each_with_index { |ev0, i| assert_equal(ev0, t1.events[i], 'events differ') }
|
23
|
+
assert_equal(t0.instrument, t1.instrument)
|
24
|
+
end
|
35
25
|
|
36
|
-
|
37
|
-
|
26
|
+
def compare_sequences(s0, s1)
|
27
|
+
assert_equal(s0.name, s1.name, 'sequence names differ')
|
28
|
+
assert_equal(s0.tracks.length, s1.tracks.length,
|
29
|
+
'number of tracks differ')
|
30
|
+
s0.each_with_index { |track0, i| compare_tracks(track0, s1.tracks[i]) }
|
31
|
+
end
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
def compare_sequences_format_0(multitrack_seq, format0_seq)
|
34
|
+
assert_equal(multitrack_seq.name, format0_seq.name, 'sequence names differ')
|
35
|
+
assert_equal(1, format0_seq.tracks.length, 'number of tracks differ')
|
36
|
+
format_1_count = multitrack_seq.tracks.map { |t| t.events.count }.reduce(:+)
|
37
|
+
format_0_count = format0_seq.tracks.map { |t| t.events.count }.reduce(:+)
|
38
|
+
assert_equal(format_1_count, format_0_count, 'same number of total events')
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
41
|
+
def test_read_and_write
|
42
|
+
seq0 = MIDI::Sequence.new
|
43
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq0.read(f) }
|
44
|
+
File.open(OUTPUT_FILE, 'wb') { |f| seq0.write(f) }
|
45
|
+
seq1 = MIDI::Sequence.new
|
46
|
+
File.open(OUTPUT_FILE, 'rb') { |f| seq1.read(f) }
|
47
|
+
compare_sequences(seq0, seq1)
|
48
|
+
ensure
|
49
|
+
File.delete(OUTPUT_FILE) if File.exist?(OUTPUT_FILE)
|
50
|
+
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
def test_read_and_write_format_0
|
53
|
+
seq0 = MIDI::Sequence.new
|
54
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq0.read(f) }
|
55
|
+
File.open(OUTPUT_FILE, 'wb') { |f| seq0.write(f, 0) }
|
56
|
+
seq1 = MIDI::Sequence.new
|
57
|
+
File.open(OUTPUT_FILE, 'rb') { |f| seq1.read(f) }
|
58
|
+
compare_sequences_format_0(seq0, seq1)
|
59
|
+
ensure
|
60
|
+
File.delete(OUTPUT_FILE) if File.exist?(OUTPUT_FILE)
|
61
|
+
end
|
49
62
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
63
|
+
def test_read_callback
|
64
|
+
seq = MIDI::Sequence.new
|
65
|
+
names = []
|
66
|
+
num_tracks = -1
|
67
|
+
File.open(SEQ_TEST_FILE, 'rb') do |f|
|
68
|
+
seq.read(f) do |track, ntracks, i|
|
69
|
+
names << (track ? track.name : nil)
|
70
|
+
num_tracks = ntracks
|
71
|
+
end
|
54
72
|
end
|
73
|
+
assert_equal(names, [nil, 'Sequence Name', 'My New Track'])
|
74
|
+
assert_equal(num_tracks, 2)
|
75
|
+
ensure
|
76
|
+
File.delete(OUTPUT_FILE) if File.exist?(OUTPUT_FILE)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_write_callback
|
80
|
+
seq = MIDI::Sequence.new
|
81
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq.read(f) }
|
55
82
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
83
|
+
names = []
|
84
|
+
num_tracks = -1
|
85
|
+
File.open(OUTPUT_FILE, 'wb') do |f|
|
86
|
+
seq.write(f) do |track, ntracks, i|
|
87
|
+
names << (track ? track.name : nil)
|
88
|
+
num_tracks = ntracks
|
89
|
+
end
|
61
90
|
end
|
91
|
+
assert_equal(names, [nil, 'Sequence Name', 'My New Track'])
|
92
|
+
assert_equal(num_tracks, 2)
|
93
|
+
ensure
|
94
|
+
File.delete(OUTPUT_FILE) if File.exist?(OUTPUT_FILE)
|
95
|
+
end
|
62
96
|
|
97
|
+
def test_read_strings
|
98
|
+
seq = MIDI::Sequence.new
|
99
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq.read(f) }
|
100
|
+
assert_equal('Sequence Name', seq.tracks[0].name)
|
101
|
+
assert_equal(MIDI::GM_PATCH_NAMES[0], seq.tracks[1].instrument)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_preserve_meta_deltas
|
105
|
+
out_seq = MIDI::Sequence.new
|
106
|
+
out_track = MIDI::Track.new(out_seq)
|
107
|
+
out_seq.tracks << out_track
|
108
|
+
out_track.events << MIDI::Tempo.new(MIDI::Tempo.bpm_to_mpq(120))
|
109
|
+
# Normally copyright and sequence name events are at time 0, but non-zero
|
110
|
+
# start times are allowed.
|
111
|
+
out_track.events << MIDI::MetaEvent.new(MIDI::META_COPYRIGHT, '(C) 1950 Donald Duck', 100)
|
112
|
+
out_track.events << MIDI::MetaEvent.new(MIDI::META_SEQ_NAME, 'Quack, Track 1', 200)
|
113
|
+
out_track.events << MIDI::NoteOn.new(0, 64, 127, 0)
|
114
|
+
out_track.events << MIDI::NoteOff.new(0, 64, 127, 100)
|
115
|
+
File.open('/tmp/midilib_test.mid', 'wb') { |file| out_seq.write(file) }
|
116
|
+
|
117
|
+
# Although start times are not written out to the MIDI file, we
|
118
|
+
# calculate them because we are about to compare the out events with the
|
119
|
+
# newly-read events which will have their start times set.
|
120
|
+
out_track.recalc_times
|
121
|
+
|
122
|
+
in_seq = MIDI::Sequence.new
|
123
|
+
File.open(TEMPFILE, 'rb') { |file| in_seq.read(file) }
|
124
|
+
in_track = in_seq.tracks[0]
|
125
|
+
assert_equal(out_track.events.length, in_track.events.length)
|
126
|
+
out_track.events.each_with_index do |event, i|
|
127
|
+
assert_equal(event, in_track.events[i])
|
128
|
+
end
|
129
|
+
end
|
63
130
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Start looking for MIDI classes in the directory above this one.
|
2
|
+
# This forces us to use the local copy of MIDI, even if there is
|
3
|
+
# a previously installed version out there somewhere.
|
4
|
+
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'midilib/mergesort'
|
8
|
+
|
9
|
+
class MergesortTester < Test::Unit::TestCase
|
10
|
+
def test_mergesort
|
11
|
+
track = MIDI::Track.new(nil)
|
12
|
+
track.events = []
|
13
|
+
|
14
|
+
# Two events with later start times but earlier in the event list
|
15
|
+
e2 = MIDI::NoteOff.new(0, 64, 64, 100)
|
16
|
+
e2.time_from_start = 100
|
17
|
+
track.events << e2
|
18
|
+
|
19
|
+
e3 = MIDI::NoteOn.new(0, 64, 64, 100)
|
20
|
+
e3.time_from_start = 100
|
21
|
+
track.events << e3
|
22
|
+
|
23
|
+
# Earliest start time, latest in the list of events
|
24
|
+
e1 = MIDI::NoteOn.new(0, 64, 64, 100)
|
25
|
+
e1.time_from_start = 0
|
26
|
+
track.events << e1
|
27
|
+
|
28
|
+
# Recalc sorts. Make sure note off/note on pair at t 100 are in the
|
29
|
+
# correct order.
|
30
|
+
track.recalc_delta_from_times
|
31
|
+
|
32
|
+
# These tests would fail before we moved to mergesort.
|
33
|
+
assert_equal(e1, track.events[0])
|
34
|
+
assert_equal(e2, track.events[1])
|
35
|
+
assert_equal(e3, track.events[2])
|
36
|
+
end
|
37
|
+
end
|
data/test/test_midifile.rb
CHANGED
@@ -8,30 +8,18 @@ require 'stringio'
|
|
8
8
|
require 'midilib'
|
9
9
|
|
10
10
|
class MIDI::IO::MIDIFile
|
11
|
-
|
12
|
-
@io = io
|
13
|
-
end
|
14
|
-
end
|
15
|
-
if RUBY_VERSION < '1.9'
|
16
|
-
class StringIO
|
17
|
-
def readbyte
|
18
|
-
c = getc()
|
19
|
-
raise 'unexpected EOF' unless c
|
20
|
-
c
|
21
|
-
end
|
22
|
-
end
|
11
|
+
attr_writer :io
|
23
12
|
end
|
24
13
|
|
25
14
|
class MIDIFileTester < Test::Unit::TestCase
|
26
|
-
|
27
15
|
def setup
|
28
16
|
@m = MIDI::IO::MIDIFile.new
|
29
17
|
end
|
30
18
|
|
31
19
|
def test_msg_io
|
32
20
|
io = StringIO.new
|
33
|
-
io.write(
|
34
|
-
io.rewind
|
21
|
+
io.write('abcdef')
|
22
|
+
io.rewind
|
35
23
|
@m.io = io
|
36
24
|
@m.msg_init
|
37
25
|
@m.msg_read(6)
|
@@ -41,9 +29,9 @@ class MIDIFileTester < Test::Unit::TestCase
|
|
41
29
|
def test_read32
|
42
30
|
io = StringIO.new
|
43
31
|
io.write("\0\0\0\6")
|
44
|
-
io.rewind
|
32
|
+
io.rewind
|
45
33
|
@m.io = io
|
46
|
-
assert_equal 6, @m.read32
|
34
|
+
assert_equal 6, @m.read32
|
47
35
|
end
|
48
36
|
|
49
37
|
def test_write32
|
@@ -52,8 +40,7 @@ class MIDIFileTester < Test::Unit::TestCase
|
|
52
40
|
$stdout = io
|
53
41
|
@m.write32(6)
|
54
42
|
$stdout = old_stdout
|
55
|
-
io.rewind
|
43
|
+
io.rewind
|
56
44
|
assert_equal "\0\0\0\6", io.string
|
57
45
|
end
|
58
|
-
|
59
46
|
end
|