midilib 3.1.0 → 4.0.0
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 +4 -4
- data/ChangeLog +12 -12
- data/Credits +7 -0
- data/README.rdoc +10 -1
- data/Rakefile +0 -1
- data/TODO.rdoc +8 -7
- data/lib/midilib/event.rb +2 -2
- data/lib/midilib/info.rb +3 -3
- data/lib/midilib/io/seqreader.rb +11 -27
- data/lib/midilib/io/seqwriter.rb +6 -4
- data/lib/midilib/track.rb +38 -6
- data/test/test_event.rb +12 -0
- data/test/test_io.rb +28 -2
- data/test/test_track.rb +65 -1
- metadata +3 -87
- data/html/MIDI/ActiveSense.html +0 -171
- data/html/MIDI/ChannelEvent.html +0 -190
- data/html/MIDI/ChannelPressure.html +0 -212
- data/html/MIDI/Clock.html +0 -171
- data/html/MIDI/Continue.html +0 -171
- data/html/MIDI/Controller.html +0 -224
- data/html/MIDI/Event.html +0 -349
- data/html/MIDI/IO/MIDIFile.html +0 -1392
- data/html/MIDI/IO/SeqReader.html +0 -642
- data/html/MIDI/IO/SeqWriter.html +0 -442
- data/html/MIDI/IO.html +0 -91
- data/html/MIDI/KeySig.html +0 -292
- data/html/MIDI/Marker.html +0 -138
- data/html/MIDI/Measure.html +0 -260
- data/html/MIDI/Measures.html +0 -222
- data/html/MIDI/MetaEvent.html +0 -353
- data/html/MIDI/NoteEvent.html +0 -255
- data/html/MIDI/NoteOff.html +0 -188
- data/html/MIDI/NoteOn.html +0 -188
- data/html/MIDI/PitchBend.html +0 -213
- data/html/MIDI/PolyPressure.html +0 -216
- data/html/MIDI/ProgramChange.html +0 -212
- data/html/MIDI/Realtime.html +0 -194
- data/html/MIDI/Sequence.html +0 -641
- data/html/MIDI/SongPointer.html +0 -213
- data/html/MIDI/SongSelect.html +0 -212
- data/html/MIDI/Start.html +0 -171
- data/html/MIDI/Stop.html +0 -171
- data/html/MIDI/SystemCommon.html +0 -138
- data/html/MIDI/SystemExclusive.html +0 -215
- data/html/MIDI/SystemReset.html +0 -171
- data/html/MIDI/Tempo.html +0 -292
- data/html/MIDI/TimeSig.html +0 -286
- data/html/MIDI/Track.html +0 -489
- data/html/MIDI/TuneRequest.html +0 -194
- data/html/MIDI/Utils.html +0 -178
- data/html/MIDI.html +0 -281
- data/html/Object.html +0 -197
- data/html/README_rdoc.html +0 -545
- data/html/TODO_rdoc.html +0 -123
- data/html/created.rid +0 -15
- data/html/css/fonts.css +0 -167
- data/html/css/rdoc.css +0 -639
- 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/brick.png +0 -0
- data/html/images/brick_link.png +0 -0
- data/html/images/bug.png +0 -0
- data/html/images/bullet_black.png +0 -0
- data/html/images/bullet_toggle_minus.png +0 -0
- data/html/images/bullet_toggle_plus.png +0 -0
- data/html/images/date.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/find.png +0 -0
- data/html/images/loadingAnimation.gif +0 -0
- data/html/images/macFFBgHack.png +0 -0
- data/html/images/package.png +0 -0
- data/html/images/page_green.png +0 -0
- data/html/images/page_white_text.png +0 -0
- data/html/images/page_white_width.png +0 -0
- data/html/images/plugin.png +0 -0
- data/html/images/ruby.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/images/tag_green.png +0 -0
- data/html/images/transparent.png +0 -0
- data/html/images/wrench.png +0 -0
- data/html/images/wrench_orange.png +0 -0
- data/html/images/zoom.png +0 -0
- data/html/index.html +0 -534
- data/html/js/darkfish.js +0 -84
- data/html/js/navigation.js +0 -105
- data/html/js/navigation.js.gz +0 -0
- data/html/js/search.js +0 -110
- data/html/js/search_index.js +0 -1
- data/html/js/search_index.js.gz +0 -0
- data/html/js/searcher.js +0 -229
- data/html/js/searcher.js.gz +0 -0
- data/html/table_of_contents.html +0 -1258
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f41957f8222283fa766d489f32dc603edf23fe904682107e216bb5646325fd27
|
|
4
|
+
data.tar.gz: 2c55d4cb9c3d2255b721725d622936a59456e87e70df4da77cfb1b82f230a338
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 884f3ab3488afa1c717ec571de2ebca279ce1e13caa69039b7e0dec2bcf265c3285169d5abe8500cf9cd60f55d818876774bcd3daa0782f2e76d6c4955b1511f
|
|
7
|
+
data.tar.gz: fce2b737b8c56017d35e27117bee86f2455a05286df63685b354c8d44666369a28353c4efc4e86a8fe01edbf803bc38a8d8549c8ea94003d66fd30eaea8eb3bd
|
data/ChangeLog
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
This change log is no longer maintaned. For further change descriptions,
|
|
2
2
|
see the Git logs.
|
|
3
3
|
|
|
4
|
-
2007-12-11 Jim Menard <jim@
|
|
4
|
+
2007-12-11 Jim Menard <jim@jimmenard.com>
|
|
5
5
|
|
|
6
6
|
* lib/midilib/io/seqreader.rb: Fixed text method and added default
|
|
7
7
|
implementation of key_signature.
|
|
8
8
|
|
|
9
|
-
2007-12-09 Jim Menard <jim@
|
|
9
|
+
2007-12-09 Jim Menard <jim@jimmenard.com>
|
|
10
10
|
|
|
11
11
|
* examples/measures_mbt.rb: Added.
|
|
12
12
|
|
|
13
|
-
2007-12-09 Jim Menard <jim@
|
|
13
|
+
2007-12-09 Jim Menard <jim@jimmenard.com>
|
|
14
14
|
|
|
15
15
|
* lib/midilib/event.rb: Added code that fixes bpm calculation
|
|
16
16
|
bugs, and his TimeSig and KeySig classes.
|
|
@@ -19,17 +19,17 @@ see the Git logs.
|
|
|
19
19
|
|
|
20
20
|
* lib/midilib/sequence.rb: Fixed clock. Added get_measures method.
|
|
21
21
|
|
|
22
|
-
2007-12-09 Jim Menard <jim@
|
|
22
|
+
2007-12-09 Jim Menard <jim@jimmenard.com>
|
|
23
23
|
|
|
24
24
|
* lib/midilib/event.rb: added program_change? and
|
|
25
25
|
print_channel_numbers_from_one to Event.
|
|
26
26
|
|
|
27
|
-
2007-03-17 Jim Menard <
|
|
27
|
+
2007-03-17 Jim Menard <jim@jimmenard.com>
|
|
28
28
|
|
|
29
29
|
* Version 1.0.0 released. I will no longer be maintaining this
|
|
30
30
|
change log; the Subversion comments should be sufficient.
|
|
31
31
|
|
|
32
|
-
2006-08-20 Jim Menard <
|
|
32
|
+
2006-08-20 Jim Menard <jim@jimmenard.com>
|
|
33
33
|
|
|
34
34
|
* lib/midilib/event.rb (PolyPressure::initialize): Fixed the
|
|
35
35
|
misspelled POLY_PRESSURE cosntant, thanks to Mario Pehle
|
|
@@ -39,7 +39,7 @@ see the Git logs.
|
|
|
39
39
|
|
|
40
40
|
* test/test.mid: created (copied examples/from_scratch.mid).
|
|
41
41
|
|
|
42
|
-
2005-03-21 Jim Menard <
|
|
42
|
+
2005-03-21 Jim Menard <jim@jimmenard.com>
|
|
43
43
|
|
|
44
44
|
* Version 0.8.4 released.
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ see the Git logs.
|
|
|
48
48
|
(SystemCommon::initialize): moved @is_system = true to here
|
|
49
49
|
(SystemExclusive::initialize): ...from here.
|
|
50
50
|
|
|
51
|
-
2005-03-20 Jim Menard <
|
|
51
|
+
2005-03-20 Jim Menard <jim@jimmenard.com>
|
|
52
52
|
|
|
53
53
|
* lib/midilib/sequence.rb (Sequence::note_to_delta): created.
|
|
54
54
|
(Sequence::note_to_length): created.
|
|
@@ -56,11 +56,11 @@ see the Git logs.
|
|
|
56
56
|
|
|
57
57
|
* examples/from_scratch.rb: created.
|
|
58
58
|
|
|
59
|
-
2004-07-16 Jim Menard <
|
|
59
|
+
2004-07-16 Jim Menard <jim@jimmenard.com>
|
|
60
60
|
|
|
61
61
|
* Version 0.8.3 released.
|
|
62
62
|
|
|
63
|
-
2004-07-10 Jim Menard <
|
|
63
|
+
2004-07-10 Jim Menard <jim@jimmenard.com>
|
|
64
64
|
|
|
65
65
|
* lib/midilib/event.rb (NoteEvent::note_to_s): created.
|
|
66
66
|
(Event::number_to_s): created.
|
|
@@ -68,7 +68,7 @@ see the Git logs.
|
|
|
68
68
|
attributes.
|
|
69
69
|
(to_s all classes): use @print_note_names and @print_decimal_numbers
|
|
70
70
|
|
|
71
|
-
2004-06-30 Jim Menard <
|
|
71
|
+
2004-06-30 Jim Menard <jim@jimmenard.com>
|
|
72
72
|
|
|
73
73
|
* Version 0.8.2 released.
|
|
74
74
|
|
|
@@ -103,7 +103,7 @@ see the Git logs.
|
|
|
103
103
|
* lib/midilib/io/seqreader.rb (SeqReader::initialize): added block
|
|
104
104
|
rdoc comment.
|
|
105
105
|
|
|
106
|
-
2004-06-27 Jim Menard <
|
|
106
|
+
2004-06-27 Jim Menard <jim@jimmenard.com>
|
|
107
107
|
|
|
108
108
|
* Version 0.8.1 released.
|
|
109
109
|
|
data/Credits
CHANGED
|
@@ -96,3 +96,10 @@ Miika Alonen (@amiika on Github)
|
|
|
96
96
|
|
|
97
97
|
Found a bug caused by note offs coming right before note ons. See
|
|
98
98
|
https://github.com/jimm/midilib/pull/21 for a detailed write-up.
|
|
99
|
+
|
|
100
|
+
@mike-bourgeous on Github
|
|
101
|
+
|
|
102
|
+
Opened an issue (https://github.com/jimm/midilib/issues/24) which led to
|
|
103
|
+
the addition of end of track meta events when reading and writing MIDI
|
|
104
|
+
files.
|
|
105
|
+
Found and fixed a bug in SongPointer#data_as_bytes.
|
data/README.rdoc
CHANGED
|
@@ -91,6 +91,15 @@ This bit mask is set when the track is read from the MIDI file by a SeqReader
|
|
|
91
91
|
but is _not_ kept up to date by any other methods. Specifically, if you add
|
|
92
92
|
events to a track at any other time, the bit mask will not be updated.
|
|
93
93
|
|
|
94
|
+
When a Track is read from a MIDI file, a MIDI::META_TRACK_END event is added
|
|
95
|
+
to the end if there isn't one in the file already. When a Track is written
|
|
96
|
+
to a MIDI file, a MIDI::META_TRACK_END event is always output even if the
|
|
97
|
+
Track does not have one.
|
|
98
|
+
|
|
99
|
+
The Track#merge method ensures that there is only one MIDI::META_TRACK_END
|
|
100
|
+
event after the merge and that it's at its proper place at the end of the
|
|
101
|
+
list of events. It does so by calling Track#ensure_track_end_meta_event.
|
|
102
|
+
|
|
94
103
|
=== MIDI::Measure
|
|
95
104
|
|
|
96
105
|
This class contains information about a measure from the sequence. Measure
|
|
@@ -133,7 +142,7 @@ string. When assigning to a meta event's data, if you pass in a string it will
|
|
|
133
142
|
get converted to an array of bytes.
|
|
134
143
|
|
|
135
144
|
|
|
136
|
-
== How To Use
|
|
145
|
+
== How To Use midilib
|
|
137
146
|
|
|
138
147
|
The following examples show you how to use midilib to read, write, and
|
|
139
148
|
manipulate MIDI files and modify track events. See also the files in the
|
data/Rakefile
CHANGED
|
@@ -33,7 +33,6 @@ spec = Gem::Specification.new do |s|
|
|
|
33
33
|
s.author = 'Jim Menard'
|
|
34
34
|
s.email = 'jim@jimmenard.com'
|
|
35
35
|
s.homepage = 'http://github.com/jimm/midilib'
|
|
36
|
-
s.rubyforge_project = PROJECT_NAME
|
|
37
36
|
s.license = 'Ruby'
|
|
38
37
|
|
|
39
38
|
s.summary = 'MIDI file and event manipulation library'
|
data/TODO.rdoc
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
== Bugs
|
|
2
2
|
|
|
3
3
|
midilib does not handle tempo changes when calculating +beats_per_minute+.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
See https://github.com/jimm/midilib/issues/8 which describes the issue. The
|
|
5
|
+
tempo events are correctly handled when reading/writing/moving them around,
|
|
6
|
+
it's just the functions that answer questions about the current tempo that
|
|
7
|
+
are wrong. See https://github.com/jimm/midilib/issues/8. The method
|
|
8
|
+
+beats_per_minute+ and related methods like +pulses_to_seconds+ will have to
|
|
9
|
+
take into account the possibility of more than one tempo event. They will
|
|
10
|
+
probably have to take new arguments specifying where in the sequence the
|
|
11
|
+
beats or pulses are being requested. For example we could have
|
|
11
12
|
+beats_per_minute(at_seconds: 0.0, at_beat: 0.0)+ (where the two keyword
|
|
12
13
|
args are mutually exclusive). Perhaps there should be separately named
|
|
13
14
|
public methods like +beats_per_minute_at_seconds+ and
|
data/lib/midilib/event.rb
CHANGED
data/lib/midilib/info.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module MIDI
|
|
2
|
-
VERSION_MAJOR =
|
|
3
|
-
VERSION_MINOR =
|
|
2
|
+
VERSION_MAJOR = 4
|
|
3
|
+
VERSION_MINOR = 0
|
|
4
4
|
VERSION_TWEAK = 0
|
|
5
5
|
Version = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_TWEAK}"
|
|
6
|
-
Copyright = 'Copyright (c) 2003-
|
|
6
|
+
Copyright = 'Copyright (c) 2003-2023 by Jim Menard <jim@jimmenard.com>'
|
|
7
7
|
end
|
data/lib/midilib/io/seqreader.rb
CHANGED
|
@@ -8,16 +8,9 @@ module MIDI
|
|
|
8
8
|
# callback methods for each MIDI event and use them to build Track and
|
|
9
9
|
# Event objects and give the tracks to a Sequence.
|
|
10
10
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# the track's start (see end_track below).
|
|
15
|
-
#
|
|
16
|
-
# META_TRACK_END events are not added to tracks. This way, we don't have
|
|
17
|
-
# to worry about making sure the last event is always a track end event.
|
|
18
|
-
# We rely on the SeqWriter to append a META_TRACK_END event to each
|
|
19
|
-
# track when it is output.
|
|
20
|
-
|
|
11
|
+
# Ensures that each track ends with an end of track meta event, and that
|
|
12
|
+
# Track#recalc_times is called at the end of the track so it can update
|
|
13
|
+
# each event with its time from the track's start (see end_track below).
|
|
21
14
|
class SeqReader < MIDIFile
|
|
22
15
|
# The optional &block is called once at the start of the file and
|
|
23
16
|
# again at the end of each track. There are three arguments to the
|
|
@@ -51,12 +44,9 @@ module MIDI
|
|
|
51
44
|
@pending.each { |on| make_note_off(on, 64) }
|
|
52
45
|
@pending = nil
|
|
53
46
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# Let the track calculate event times from start of track. This is
|
|
59
|
-
# in lieu of calling Track.add for each event.
|
|
47
|
+
# Make sure track has an end of track event and that all of the
|
|
48
|
+
# `time_from_start` values are correct.
|
|
49
|
+
@track.ensure_track_end_meta_event
|
|
60
50
|
@track.recalc_times
|
|
61
51
|
|
|
62
52
|
# Store bitmask of all channels used into track
|
|
@@ -102,7 +92,7 @@ module MIDI
|
|
|
102
92
|
|
|
103
93
|
if $DEBUG
|
|
104
94
|
warn "note off with no earlier note on (ch #{chan}, note" +
|
|
105
|
-
|
|
95
|
+
" #{note}, vel #{vel})"
|
|
106
96
|
end
|
|
107
97
|
end
|
|
108
98
|
end
|
|
@@ -143,6 +133,10 @@ module MIDI
|
|
|
143
133
|
@track.events << SystemExclusive.new(msg, @curr_ticks)
|
|
144
134
|
end
|
|
145
135
|
|
|
136
|
+
def eot
|
|
137
|
+
@track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
|
|
138
|
+
end
|
|
139
|
+
|
|
146
140
|
def meta_misc(type, msg)
|
|
147
141
|
@track.events << MetaEvent.new(type, msg, @curr_ticks)
|
|
148
142
|
end
|
|
@@ -168,16 +162,6 @@ module MIDI
|
|
|
168
162
|
end
|
|
169
163
|
end
|
|
170
164
|
|
|
171
|
-
# --
|
|
172
|
-
# Don't bother adding the META_TRACK_END event to the track. This way,
|
|
173
|
-
# we don't have to worry about always making sure the last event is
|
|
174
|
-
# always a track end event. We just have to make sure to write one when
|
|
175
|
-
# the track is output back to a file.
|
|
176
|
-
# def eot()
|
|
177
|
-
# @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
|
|
178
|
-
# end
|
|
179
|
-
# ++
|
|
180
|
-
|
|
181
165
|
def time_signature(numer, denom, clocks, qnotes)
|
|
182
166
|
@seq.time_signature(numer, denom, clocks, qnotes)
|
|
183
167
|
@track.events << TimeSig.new(numer, denom, clocks, qnotes, @curr_ticks)
|
data/lib/midilib/io/seqwriter.rb
CHANGED
|
@@ -66,10 +66,12 @@ module MIDI
|
|
|
66
66
|
prev_status = status
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
# Write track end event.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
# Write track end event if the track doesn't have one.
|
|
70
|
+
unless track.events.last.is_a?(MetaEvent) && track.events.last.meta_type == META_TRACK_END
|
|
71
|
+
event = MetaEvent.new(META_TRACK_END)
|
|
72
|
+
write_var_len(0)
|
|
73
|
+
@bytes_written += write_bytes(event.data_as_bytes)
|
|
74
|
+
end
|
|
73
75
|
|
|
74
76
|
# Go back to beginning of track data and write number of bytes,
|
|
75
77
|
# then come back here to end of file.
|
data/lib/midilib/track.rb
CHANGED
|
@@ -59,11 +59,48 @@ module MIDI
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# Iterates over events, yielding each one.
|
|
63
|
+
def each(&block) # :yields: event
|
|
64
|
+
@events.each(&block)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# If `event` exists in @events, deletes it, updates the delta time of
|
|
68
|
+
# the event after it, and calls `recalc_times` by default.
|
|
69
|
+
def delete_event(event, call_recalc_times = true)
|
|
70
|
+
i = @events.index(event)
|
|
71
|
+
return unless i
|
|
72
|
+
|
|
73
|
+
@events[i + 1].delta_time += @events[i].delta_time if i != (@events.length - 1)
|
|
74
|
+
@events.delete_at(i)
|
|
75
|
+
recalc_times if call_recalc_times
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Makes sure that we have one and only one end track meta event at the
|
|
79
|
+
# end of this track.
|
|
80
|
+
def ensure_track_end_meta_event
|
|
81
|
+
track_ends = @events.select { |e| e.is_a?(MetaEvent) && e.meta_type == META_TRACK_END }
|
|
82
|
+
has_end = !@events.empty? && track_ends[-1] == @events.last
|
|
83
|
+
|
|
84
|
+
# If we only have one end event and it's the last one, there's nothing
|
|
85
|
+
# to do.
|
|
86
|
+
return if track_ends.length == 1 && has_end
|
|
87
|
+
|
|
88
|
+
# If we have an end of track event already, leave it alone.
|
|
89
|
+
track_ends.pop if has_end
|
|
90
|
+
track_ends.each { |track_end| delete_event(track_end, false) }
|
|
91
|
+
return if has_end
|
|
92
|
+
|
|
93
|
+
mte = MetaEvent.new(META_TRACK_END, nil, 0)
|
|
94
|
+
mte.time_from_start = @events.last.time_from_start + mte.delta_time if @events.last
|
|
95
|
+
@events << mte
|
|
96
|
+
end
|
|
97
|
+
|
|
62
98
|
# Merges an array of events into our event list. After merging, the
|
|
63
99
|
# events' time_from_start values are correct so you don't need to worry
|
|
64
|
-
# about calling recalc_times.
|
|
100
|
+
# about calling #recalc_times.
|
|
65
101
|
def merge(event_list)
|
|
66
102
|
@events = merge_event_lists(@events, event_list)
|
|
103
|
+
ensure_track_end_meta_event
|
|
67
104
|
end
|
|
68
105
|
|
|
69
106
|
# Merges two event arrays together. Does not modify this track.
|
|
@@ -121,11 +158,6 @@ module MIDI
|
|
|
121
158
|
end
|
|
122
159
|
end
|
|
123
160
|
|
|
124
|
-
# Iterate over events.
|
|
125
|
-
def each(&block) # :yields: event
|
|
126
|
-
@events.each(&block)
|
|
127
|
-
end
|
|
128
|
-
|
|
129
161
|
# Sort events by their time_from_start. After sorting,
|
|
130
162
|
# recalc_delta_from_times is called to make sure that the delta times
|
|
131
163
|
# reflect the possibly new event order.
|
data/test/test_event.rb
CHANGED
|
@@ -130,4 +130,16 @@ class EventTester < Test::Unit::TestCase
|
|
|
130
130
|
assert_equal('foobar', e.data_as_str)
|
|
131
131
|
assert_equal(foobar_as_array, e.data)
|
|
132
132
|
end
|
|
133
|
+
|
|
134
|
+
def test_song_pointer
|
|
135
|
+
e = MIDI::SongPointer.new(1)
|
|
136
|
+
b = e.data_as_bytes
|
|
137
|
+
assert_equal(1, b[1]) # lsb, 7 bits
|
|
138
|
+
assert_equal(0, b[2]) # msb, 7 bits
|
|
139
|
+
|
|
140
|
+
e.pointer = (3 << 7) + 42
|
|
141
|
+
b = e.data_as_bytes
|
|
142
|
+
assert_equal(42, b[1]) # lsb, 7 bits
|
|
143
|
+
assert_equal(3, b[2]) # msb, 7 bits
|
|
144
|
+
end
|
|
133
145
|
end
|
data/test/test_io.rb
CHANGED
|
@@ -35,7 +35,12 @@ class IOTester < Test::Unit::TestCase
|
|
|
35
35
|
assert_equal(1, format0_seq.tracks.length, 'number of tracks differ')
|
|
36
36
|
format_1_count = multitrack_seq.tracks.map { |t| t.events.count }.reduce(:+)
|
|
37
37
|
format_0_count = format0_seq.tracks.map { |t| t.events.count }.reduce(:+)
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
# The format 1 file will have one more event because there is an end of
|
|
40
|
+
# track meta event at the end of each track (the track 0 metadata track
|
|
41
|
+
# and track 1 with the notes), whereas the format 0 file only has one
|
|
42
|
+
# track, thus one end of track meta event.
|
|
43
|
+
assert_equal(format_1_count, format_0_count + 1, 'different number of total events')
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
def test_read_and_write
|
|
@@ -101,6 +106,22 @@ class IOTester < Test::Unit::TestCase
|
|
|
101
106
|
assert_equal(MIDI::GM_PATCH_NAMES[0], seq.tracks[1].instrument)
|
|
102
107
|
end
|
|
103
108
|
|
|
109
|
+
# This is a regression test.
|
|
110
|
+
def test_read_eot_preserves_delta
|
|
111
|
+
seq = MIDI::Sequence.new
|
|
112
|
+
File.open(SEQ_TEST_FILE, 'rb') { |f| seq.read(f) }
|
|
113
|
+
track = seq.tracks.last
|
|
114
|
+
mte = MIDI::MetaEvent.new(MIDI::META_TRACK_END, nil, 123)
|
|
115
|
+
track.events << mte
|
|
116
|
+
track.recalc_times
|
|
117
|
+
File.open(OUTPUT_FILE, 'wb') { |f| seq.write(f) }
|
|
118
|
+
File.open(OUTPUT_FILE, 'rb') { |f| seq.read(f) }
|
|
119
|
+
|
|
120
|
+
assert_equal(mte, seq.tracks.last.events.last)
|
|
121
|
+
ensure
|
|
122
|
+
File.delete(OUTPUT_FILE) if File.exist?(OUTPUT_FILE)
|
|
123
|
+
end
|
|
124
|
+
|
|
104
125
|
def test_preserve_deltas_in_some_situations
|
|
105
126
|
out_seq = MIDI::Sequence.new
|
|
106
127
|
out_track = MIDI::Track.new(out_seq)
|
|
@@ -135,9 +156,14 @@ class IOTester < Test::Unit::TestCase
|
|
|
135
156
|
in_seq = MIDI::Sequence.new
|
|
136
157
|
File.open(TEMPFILE, 'rb') { |file| in_seq.read(file) }
|
|
137
158
|
in_track = in_seq.tracks[0]
|
|
138
|
-
assert_equal(out_track.events.length, in_track.events.length)
|
|
159
|
+
assert_equal(out_track.events.length + 1, in_track.events.length) # read added end of track meta event
|
|
139
160
|
out_track.events.each_with_index do |event, i|
|
|
140
161
|
assert_equal(event, in_track.events[i])
|
|
141
162
|
end
|
|
163
|
+
|
|
164
|
+
# Last event is a end of track meta event
|
|
165
|
+
e = in_track.events.last
|
|
166
|
+
assert(e.is_a?(MIDI::MetaEvent))
|
|
167
|
+
assert(e.meta_type == MIDI::META_TRACK_END)
|
|
142
168
|
end
|
|
143
169
|
end
|
data/test/test_track.rb
CHANGED
|
@@ -61,7 +61,8 @@ class TrackTester < Test::Unit::TestCase
|
|
|
61
61
|
def test_merge
|
|
62
62
|
list = (1..12).collect { |i| MIDI::NoteOn.new(0, 64, 64, 10) }
|
|
63
63
|
@track.merge(list)
|
|
64
|
-
|
|
64
|
+
# We merged 15 events, but an end of track meta event was added by merge
|
|
65
|
+
assert_equal(16, @track.events.length)
|
|
65
66
|
assert_equal(10, @track.events[0].time_from_start)
|
|
66
67
|
assert_equal(10, @track.events[0].delta_time)
|
|
67
68
|
assert_equal(20, @track.events[1].time_from_start)
|
|
@@ -79,6 +80,7 @@ class TrackTester < Test::Unit::TestCase
|
|
|
79
80
|
assert_equal(120, @track.events[12].time_from_start)
|
|
80
81
|
assert_equal(200, @track.events[13].time_from_start)
|
|
81
82
|
assert_equal(300, @track.events[14].time_from_start)
|
|
83
|
+
assert_equal(300, @track.events[15].time_from_start) # end of track meta event
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
def test_recalc_delta_from_times
|
|
@@ -140,4 +142,66 @@ class TrackTester < Test::Unit::TestCase
|
|
|
140
142
|
x = MIDI::NoteOff.new(0, 64, 64, 10)
|
|
141
143
|
assert(x.is_a?(MIDI::NoteOffEvent)) # old name
|
|
142
144
|
end
|
|
145
|
+
|
|
146
|
+
def test_delete_event
|
|
147
|
+
# Event is not in the track; nothing happens
|
|
148
|
+
@track.delete_event(MIDI::Controller.new(0, 64, 64, 200))
|
|
149
|
+
assert_equal(3, @track.events.length)
|
|
150
|
+
|
|
151
|
+
# Make sure we update delta times and that start times are preserved
|
|
152
|
+
e = @track.events[1]
|
|
153
|
+
@track.delete_event(e)
|
|
154
|
+
assert_equal(2, @track.events.length)
|
|
155
|
+
assert(@track.events.index(e).nil?)
|
|
156
|
+
assert_equal([100, 200], @track.events.map(&:delta_time))
|
|
157
|
+
assert_equal([100, 300], @track.events.map(&:time_from_start))
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_ensure_track_end_meta_event
|
|
161
|
+
@track.ensure_track_end_meta_event
|
|
162
|
+
assert_equal(4, @track.events.length)
|
|
163
|
+
e = @track.events.last
|
|
164
|
+
assert(e.is_a?(MIDI::MetaEvent))
|
|
165
|
+
assert_equal(MIDI::META_TRACK_END, e.meta_type)
|
|
166
|
+
assert_equal(0, e.delta_time)
|
|
167
|
+
assert_equal(@track.events[-2].time_from_start, e.time_from_start)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_ensure_track_end_meta_event_removes_duplicates
|
|
171
|
+
mte = MIDI::MetaEvent.new(MIDI::META_TRACK_END, nil, 0)
|
|
172
|
+
@track.events << mte
|
|
173
|
+
@track.events.unshift(mte.dup)
|
|
174
|
+
@track.events.unshift(mte.dup)
|
|
175
|
+
|
|
176
|
+
@track.ensure_track_end_meta_event
|
|
177
|
+
mtes = @track.events.select { |e| e.is_a?(MIDI::MetaEvent) && e.meta_type == MIDI::META_TRACK_END }
|
|
178
|
+
assert_equal(1, mtes.length)
|
|
179
|
+
assert(@track.events.last.is_a?(MIDI::MetaEvent) && @track.events.last.meta_type == MIDI::META_TRACK_END)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def test_ensure_track_end_with_dupes_does_not_shrink_track
|
|
183
|
+
mte = MIDI::MetaEvent.new(MIDI::META_TRACK_END, nil, 123)
|
|
184
|
+
@track.events.unshift(mte.dup)
|
|
185
|
+
@track.events << mte
|
|
186
|
+
@track.recalc_times
|
|
187
|
+
start_time = @track.events.last.time_from_start
|
|
188
|
+
|
|
189
|
+
@track.ensure_track_end_meta_event
|
|
190
|
+
mtes = @track.events.select { |e| e.is_a?(MIDI::MetaEvent) && e.meta_type == MIDI::META_TRACK_END }
|
|
191
|
+
assert_equal(1, mtes.length)
|
|
192
|
+
assert_equal(mte, mtes[0])
|
|
193
|
+
|
|
194
|
+
# As a side effect, ensure_track_end_meta_event calls recalc_times which
|
|
195
|
+
# in this case will modify the start time of mte.
|
|
196
|
+
assert_equal(start_time, mte.time_from_start)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def test_ensure_track_end_adds_to_empty_track
|
|
200
|
+
t = MIDI::Track.new(@seq)
|
|
201
|
+
t.ensure_track_end_meta_event
|
|
202
|
+
|
|
203
|
+
assert_equal(1, t.events.length)
|
|
204
|
+
mte = t.events.first
|
|
205
|
+
assert(mte.is_a?(MIDI::MetaEvent) && mte.meta_type == MIDI::META_TRACK_END)
|
|
206
|
+
end
|
|
143
207
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: midilib
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jim Menard
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-02-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
midilib is a pure Ruby MIDI library useful for reading and
|
|
@@ -35,90 +35,6 @@ files:
|
|
|
35
35
|
- examples/split.rb
|
|
36
36
|
- examples/strings.rb
|
|
37
37
|
- examples/transpose.rb
|
|
38
|
-
- html/MIDI.html
|
|
39
|
-
- html/MIDI/ActiveSense.html
|
|
40
|
-
- html/MIDI/ChannelEvent.html
|
|
41
|
-
- html/MIDI/ChannelPressure.html
|
|
42
|
-
- html/MIDI/Clock.html
|
|
43
|
-
- html/MIDI/Continue.html
|
|
44
|
-
- html/MIDI/Controller.html
|
|
45
|
-
- html/MIDI/Event.html
|
|
46
|
-
- html/MIDI/IO.html
|
|
47
|
-
- html/MIDI/IO/MIDIFile.html
|
|
48
|
-
- html/MIDI/IO/SeqReader.html
|
|
49
|
-
- html/MIDI/IO/SeqWriter.html
|
|
50
|
-
- html/MIDI/KeySig.html
|
|
51
|
-
- html/MIDI/Marker.html
|
|
52
|
-
- html/MIDI/Measure.html
|
|
53
|
-
- html/MIDI/Measures.html
|
|
54
|
-
- html/MIDI/MetaEvent.html
|
|
55
|
-
- html/MIDI/NoteEvent.html
|
|
56
|
-
- html/MIDI/NoteOff.html
|
|
57
|
-
- html/MIDI/NoteOn.html
|
|
58
|
-
- html/MIDI/PitchBend.html
|
|
59
|
-
- html/MIDI/PolyPressure.html
|
|
60
|
-
- html/MIDI/ProgramChange.html
|
|
61
|
-
- html/MIDI/Realtime.html
|
|
62
|
-
- html/MIDI/Sequence.html
|
|
63
|
-
- html/MIDI/SongPointer.html
|
|
64
|
-
- html/MIDI/SongSelect.html
|
|
65
|
-
- html/MIDI/Start.html
|
|
66
|
-
- html/MIDI/Stop.html
|
|
67
|
-
- html/MIDI/SystemCommon.html
|
|
68
|
-
- html/MIDI/SystemExclusive.html
|
|
69
|
-
- html/MIDI/SystemReset.html
|
|
70
|
-
- html/MIDI/Tempo.html
|
|
71
|
-
- html/MIDI/TimeSig.html
|
|
72
|
-
- html/MIDI/Track.html
|
|
73
|
-
- html/MIDI/TuneRequest.html
|
|
74
|
-
- html/MIDI/Utils.html
|
|
75
|
-
- html/Object.html
|
|
76
|
-
- html/README_rdoc.html
|
|
77
|
-
- html/TODO_rdoc.html
|
|
78
|
-
- html/created.rid
|
|
79
|
-
- html/css/fonts.css
|
|
80
|
-
- html/css/rdoc.css
|
|
81
|
-
- html/fonts/Lato-Light.ttf
|
|
82
|
-
- html/fonts/Lato-LightItalic.ttf
|
|
83
|
-
- html/fonts/Lato-Regular.ttf
|
|
84
|
-
- html/fonts/Lato-RegularItalic.ttf
|
|
85
|
-
- html/fonts/SourceCodePro-Bold.ttf
|
|
86
|
-
- html/fonts/SourceCodePro-Regular.ttf
|
|
87
|
-
- html/images/add.png
|
|
88
|
-
- html/images/arrow_up.png
|
|
89
|
-
- html/images/brick.png
|
|
90
|
-
- html/images/brick_link.png
|
|
91
|
-
- html/images/bug.png
|
|
92
|
-
- html/images/bullet_black.png
|
|
93
|
-
- html/images/bullet_toggle_minus.png
|
|
94
|
-
- html/images/bullet_toggle_plus.png
|
|
95
|
-
- html/images/date.png
|
|
96
|
-
- html/images/delete.png
|
|
97
|
-
- html/images/find.png
|
|
98
|
-
- html/images/loadingAnimation.gif
|
|
99
|
-
- html/images/macFFBgHack.png
|
|
100
|
-
- html/images/package.png
|
|
101
|
-
- html/images/page_green.png
|
|
102
|
-
- html/images/page_white_text.png
|
|
103
|
-
- html/images/page_white_width.png
|
|
104
|
-
- html/images/plugin.png
|
|
105
|
-
- html/images/ruby.png
|
|
106
|
-
- html/images/tag_blue.png
|
|
107
|
-
- html/images/tag_green.png
|
|
108
|
-
- html/images/transparent.png
|
|
109
|
-
- html/images/wrench.png
|
|
110
|
-
- html/images/wrench_orange.png
|
|
111
|
-
- html/images/zoom.png
|
|
112
|
-
- html/index.html
|
|
113
|
-
- html/js/darkfish.js
|
|
114
|
-
- html/js/navigation.js
|
|
115
|
-
- html/js/navigation.js.gz
|
|
116
|
-
- html/js/search.js
|
|
117
|
-
- html/js/search_index.js
|
|
118
|
-
- html/js/search_index.js.gz
|
|
119
|
-
- html/js/searcher.js
|
|
120
|
-
- html/js/searcher.js.gz
|
|
121
|
-
- html/table_of_contents.html
|
|
122
38
|
- install.rb
|
|
123
39
|
- lib/midilib.rb
|
|
124
40
|
- lib/midilib/consts.rb
|
|
@@ -163,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
163
79
|
version: '0'
|
|
164
80
|
requirements:
|
|
165
81
|
- none
|
|
166
|
-
rubygems_version: 3.3
|
|
82
|
+
rubygems_version: 3.4.3
|
|
167
83
|
signing_key:
|
|
168
84
|
specification_version: 4
|
|
169
85
|
summary: MIDI file and event manipulation library
|