midilib 2.0.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +2 -1
- data/Credits +44 -2
- data/README.rdoc +13 -9
- 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 -191
- 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/html/MIDI/ActiveSense.html +89 -213
- data/html/MIDI/ChannelEvent.html +95 -224
- data/html/MIDI/ChannelPressure.html +103 -241
- data/html/MIDI/Clock.html +89 -213
- data/html/MIDI/Continue.html +89 -213
- data/html/MIDI/Controller.html +105 -246
- data/html/MIDI/Event.html +134 -358
- data/html/MIDI/IO/MIDIFile.html +544 -1148
- data/html/MIDI/IO/SeqReader.html +273 -577
- data/html/MIDI/IO/SeqWriter.html +233 -439
- data/html/MIDI/IO.html +48 -164
- data/html/MIDI/KeySig.html +148 -291
- data/html/MIDI/Marker.html +73 -192
- data/html/MIDI/Measure.html +104 -267
- data/html/MIDI/Measures.html +106 -259
- data/html/MIDI/MetaEvent.html +171 -352
- data/html/MIDI/NoteEvent.html +114 -276
- data/html/MIDI/NoteOff.html +95 -223
- data/html/MIDI/NoteOn.html +95 -223
- data/html/MIDI/PitchBend.html +104 -242
- data/html/MIDI/PolyPressure.html +102 -246
- data/html/MIDI/ProgramChange.html +103 -241
- data/html/MIDI/Realtime.html +96 -230
- data/html/MIDI/Sequence.html +256 -576
- data/html/MIDI/SongPointer.html +104 -242
- data/html/MIDI/SongSelect.html +103 -241
- data/html/MIDI/Start.html +89 -213
- data/html/MIDI/Stop.html +89 -213
- data/html/MIDI/SystemCommon.html +73 -192
- data/html/MIDI/SystemExclusive.html +106 -244
- data/html/MIDI/SystemReset.html +89 -213
- data/html/MIDI/Tempo.html +127 -309
- data/html/MIDI/TimeSig.html +119 -300
- data/html/MIDI/Track.html +214 -494
- data/html/MIDI/TuneRequest.html +96 -230
- data/html/MIDI/Utils.html +91 -233
- data/html/MIDI.html +142 -526
- data/html/Object.html +197 -0
- data/html/README_rdoc.html +280 -486
- data/html/TODO_rdoc.html +68 -145
- data/html/created.rid +15 -14
- data/html/css/fonts.css +167 -0
- data/html/css/rdoc.css +639 -0
- data/html/fonts/Lato-Light.ttf +0 -0
- data/html/fonts/Lato-LightItalic.ttf +0 -0
- data/html/fonts/Lato-Regular.ttf +0 -0
- data/html/fonts/Lato-RegularItalic.ttf +0 -0
- data/html/fonts/SourceCodePro-Bold.ttf +0 -0
- data/html/fonts/SourceCodePro-Regular.ttf +0 -0
- data/html/images/add.png +0 -0
- data/html/images/arrow_up.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/index.html +230 -446
- data/html/js/darkfish.js +22 -91
- data/html/js/navigation.js +4 -41
- data/html/js/navigation.js.gz +0 -0
- data/html/js/search.js +41 -25
- data/html/js/search_index.js +1 -1
- data/html/js/search_index.js.gz +0 -0
- data/html/js/searcher.js +9 -8
- data/html/js/searcher.js.gz +0 -0
- data/html/table_of_contents.html +1111 -505
- 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 +200 -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 +93 -87
- 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 +118 -38
- data/test/test_mergesort.rb +37 -0
- data/test/test_midifile.rb +6 -19
- data/test/test_sequence.rb +62 -61
- data/test/test_track.rb +126 -155
- data/test/test_varlen.rb +23 -27
- metadata +67 -62
- data/html/IO.html +0 -259
- data/html/MIDI/MIDI/MIDI/Array.html +0 -353
- data/html/MIDI/MIDI/MIDI.html +0 -204
- data/html/MIDI/MIDI.html +0 -204
- data/html/js/jquery.js +0 -18
- data/html/rdoc.css +0 -543
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,137 @@ $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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
25
|
+
|
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
|
32
|
+
|
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
|
40
|
+
|
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
|
51
|
+
|
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
|
26
62
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
34
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
|
35
78
|
|
36
|
-
|
37
|
-
|
79
|
+
def test_write_callback
|
80
|
+
seq = MIDI::Sequence.new
|
81
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq.read(f) }
|
38
82
|
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
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
|
42
96
|
|
43
|
-
|
44
|
-
|
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
|
45
103
|
|
46
|
-
|
47
|
-
|
48
|
-
|
104
|
+
def test_preserve_deltas_in_some_situations
|
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))
|
49
109
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
110
|
+
# 1) The meta events with non-zero delta time
|
111
|
+
# Normally copyright and sequence name events are at time 0, but non-zero
|
112
|
+
# start times are allowed.
|
113
|
+
begin
|
114
|
+
out_track.events << MIDI::MetaEvent.new(MIDI::META_COPYRIGHT, '(C) 1950 Donald Duck', 100)
|
115
|
+
out_track.events << MIDI::MetaEvent.new(MIDI::META_SEQ_NAME, 'Quack, Track 1', 200)
|
116
|
+
out_track.events << MIDI::NoteOn.new(0, 64, 127, 0)
|
117
|
+
out_track.events << MIDI::NoteOff.new(0, 64, 127, 100)
|
54
118
|
end
|
55
119
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
120
|
+
# 2) The unusual note off event with non-zero delta time
|
121
|
+
begin
|
122
|
+
out_track.events << MIDI::NoteOff.new(0, 65, 127, 120)
|
123
|
+
out_track.events << MIDI::NoteOn.new(0, 65, 127, 0)
|
124
|
+
# Add note off (which will be complemented at #end_track if missing) for later comparison.
|
125
|
+
out_track.events << MIDI::NoteOff.new(0, 65, 127, 230)
|
61
126
|
end
|
62
127
|
|
128
|
+
File.open('/tmp/midilib_test.mid', 'wb') { |file| out_seq.write(file) }
|
129
|
+
|
130
|
+
# Although start times are not written out to the MIDI file, we
|
131
|
+
# calculate them because we are about to compare the out events with the
|
132
|
+
# newly-read events which will have their start times set.
|
133
|
+
out_track.recalc_times
|
134
|
+
|
135
|
+
in_seq = MIDI::Sequence.new
|
136
|
+
File.open(TEMPFILE, 'rb') { |file| in_seq.read(file) }
|
137
|
+
in_track = in_seq.tracks[0]
|
138
|
+
assert_equal(out_track.events.length, in_track.events.length)
|
139
|
+
out_track.events.each_with_index do |event, i|
|
140
|
+
assert_equal(event, in_track.events[i])
|
141
|
+
end
|
142
|
+
end
|
63
143
|
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
|