midilib 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +9 -4
  3. data/Rakefile +2 -6
  4. data/examples/from_scratch.rb +3 -5
  5. data/examples/measures_mbt.rb +4 -4
  6. data/examples/print_program_changes.rb +9 -9
  7. data/examples/reader2text.rb +188 -188
  8. data/examples/seq2text.rb +17 -17
  9. data/examples/split.rb +19 -19
  10. data/examples/strings.rb +14 -14
  11. data/examples/transpose.rb +31 -31
  12. data/html/IO.html +65 -169
  13. data/html/MIDI.html +138 -256
  14. data/html/MIDI/ActiveSense.html +89 -178
  15. data/html/MIDI/ChannelEvent.html +95 -183
  16. data/html/MIDI/ChannelPressure.html +105 -190
  17. data/html/MIDI/Clock.html +89 -178
  18. data/html/MIDI/Continue.html +89 -178
  19. data/html/MIDI/Controller.html +107 -192
  20. data/html/MIDI/Event.html +138 -222
  21. data/html/MIDI/IO.html +45 -157
  22. data/html/MIDI/IO/MIDIFile.html +596 -568
  23. data/html/MIDI/IO/SeqReader.html +272 -314
  24. data/html/MIDI/IO/SeqWriter.html +229 -305
  25. data/html/MIDI/KeySig.html +129 -211
  26. data/html/MIDI/MIDI.html +45 -154
  27. data/html/MIDI/MIDI/MIDI.html +45 -154
  28. data/html/MIDI/MIDI/MIDI/Array.html +87 -185
  29. data/html/MIDI/Marker.html +71 -170
  30. data/html/MIDI/Measure.html +95 -190
  31. data/html/MIDI/Measures.html +103 -193
  32. data/html/MIDI/MetaEvent.html +180 -253
  33. data/html/MIDI/NoteEvent.html +118 -204
  34. data/html/MIDI/NoteOff.html +95 -183
  35. data/html/MIDI/NoteOn.html +95 -183
  36. data/html/MIDI/PitchBend.html +106 -191
  37. data/html/MIDI/PolyPressure.html +106 -189
  38. data/html/MIDI/ProgramChange.html +105 -190
  39. data/html/MIDI/Realtime.html +98 -184
  40. data/html/MIDI/Sequence.html +246 -311
  41. data/html/MIDI/SongPointer.html +106 -191
  42. data/html/MIDI/SongSelect.html +105 -190
  43. data/html/MIDI/Start.html +89 -178
  44. data/html/MIDI/Stop.html +89 -178
  45. data/html/MIDI/SystemCommon.html +71 -170
  46. data/html/MIDI/SystemExclusive.html +108 -193
  47. data/html/MIDI/SystemReset.html +89 -178
  48. data/html/MIDI/Tempo.html +135 -213
  49. data/html/MIDI/TimeSig.html +135 -214
  50. data/html/MIDI/Track.html +217 -291
  51. data/html/MIDI/TuneRequest.html +98 -184
  52. data/html/MIDI/Utils.html +89 -189
  53. data/html/README_rdoc.html +237 -257
  54. data/html/TODO_rdoc.html +64 -139
  55. data/html/created.rid +14 -14
  56. data/html/css/fonts.css +167 -0
  57. data/html/{rdoc.css → css/rdoc.css} +265 -218
  58. data/html/fonts/Lato-Light.ttf +0 -0
  59. data/html/fonts/Lato-LightItalic.ttf +0 -0
  60. data/html/fonts/Lato-Regular.ttf +0 -0
  61. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  62. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  63. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  64. data/html/images/add.png +0 -0
  65. data/html/images/arrow_up.png +0 -0
  66. data/html/images/delete.png +0 -0
  67. data/html/images/tag_blue.png +0 -0
  68. data/html/index.html +187 -169
  69. data/html/js/darkfish.js +41 -33
  70. data/html/js/jquery.js +4 -18
  71. data/html/js/navigation.js.gz +0 -0
  72. data/html/js/search.js +20 -5
  73. data/html/js/search_index.js +1 -1
  74. data/html/js/search_index.js.gz +0 -0
  75. data/html/js/searcher.js.gz +0 -0
  76. data/html/table_of_contents.html +1111 -498
  77. data/install.rb +43 -32
  78. data/lib/midilib/consts.rb +407 -407
  79. data/lib/midilib/event.rb +295 -294
  80. data/lib/midilib/info.rb +5 -5
  81. data/lib/midilib/io/midifile.rb +266 -267
  82. data/lib/midilib/io/seqreader.rb +106 -106
  83. data/lib/midilib/io/seqwriter.rb +59 -60
  84. data/lib/midilib/measure.rb +69 -69
  85. data/lib/midilib/sequence.rb +68 -70
  86. data/lib/midilib/track.rb +96 -102
  87. data/lib/midilib/utils.rb +15 -15
  88. data/test/event_equality.rb +50 -50
  89. data/test/test_event.rb +120 -122
  90. data/test/test_io.rb +35 -48
  91. data/test/test_sequence.rb +60 -60
  92. data/test/test_track.rb +154 -154
  93. data/test/test_varlen.rb +23 -25
  94. metadata +65 -57
@@ -4,54 +4,54 @@ require 'midilib/event'
4
4
 
5
5
  module MIDI
6
6
 
7
- module IO
8
-
9
- # Reads MIDI files. As a subclass of MIDIFile, this class implements
10
- # the callback methods for each MIDI event and use them to build Track
11
- # and Event objects and give the tracks to a Sequence.
12
- #
13
- # We append new events to the end of a track's event list, bypassing a call
14
- # to Track.#add. This means that we must call Track.recalc_times at the end
15
- # of the track so it can update each event with its time from the track's
16
- # start (see end_track below).
17
- #
18
- # META_TRACK_END events are not added to tracks. This way, we don't have to
19
- # worry about making sure the last event is always a track end event. We
20
- # rely on the SeqWriter to append a META_TRACK_END event to each track when
21
- # it is output.
22
-
23
- class SeqReader < MIDIFile
24
-
25
- # The optional proc block is called once at the start of the file
26
- # and again at the end of each track. There are three arguments
27
- # to the block: the track, the track number (1 through _n_), and
28
- # the total number of tracks.
29
- def initialize(seq, proc = nil) # :yields: track, num_tracks, index
7
+ module IO
8
+
9
+ # Reads MIDI files. As a subclass of MIDIFile, this class implements the
10
+ # callback methods for each MIDI event and use them to build Track and
11
+ # Event objects and give the tracks to a Sequence.
12
+ #
13
+ # We append new events to the end of a track's event list, bypassing a
14
+ # call to Track.#add. This means that we must call Track.recalc_times at
15
+ # the end of the track so it can update each event with its time from
16
+ # the track's start (see end_track below).
17
+ #
18
+ # META_TRACK_END events are not added to tracks. This way, we don't have
19
+ # to worry about making sure the last event is always a track end event.
20
+ # We rely on the SeqWriter to append a META_TRACK_END event to each
21
+ # track when it is output.
22
+
23
+ class SeqReader < MIDIFile
24
+
25
+ # The optional proc block is called once at the start of the file and
26
+ # again at the end of each track. There are three arguments to the
27
+ # block: the track, the track number (1 through _n_), and the total
28
+ # number of tracks.
29
+ def initialize(seq, proc = nil) # :yields: track, num_tracks, index
30
30
  super()
31
31
  @seq = seq
32
32
  @track = nil
33
33
  @chan_mask = 0
34
34
  @update_block = block_given?() ? Proc.new() : proc
35
- end
35
+ end
36
36
 
37
- def header(format, ntrks, division)
37
+ def header(format, ntrks, division)
38
38
  @seq.format = format
39
39
  @seq.ppqn = division
40
40
 
41
41
  @ntrks = ntrks
42
42
  @update_block.call(nil, @ntrks, 0) if @update_block
43
- end
43
+ end
44
44
 
45
- def start_track()
45
+ def start_track()
46
46
  @track = Track.new(@seq)
47
47
  @seq.tracks << @track
48
48
 
49
49
  @pending = []
50
- end
50
+ end
51
51
 
52
- def end_track()
52
+ def end_track()
53
53
  # Turn off any pending note on messages
54
- @pending.each { | on | make_note_off(on, 64) }
54
+ @pending.each { |on| make_note_off(on, 64) }
55
55
  @pending = nil
56
56
 
57
57
  # Don't bother adding the META_TRACK_END event to the track.
@@ -67,136 +67,136 @@ class SeqReader < MIDIFile
67
67
 
68
68
  # call update block
69
69
  @update_block.call(@track, @ntrks, @seq.tracks.length) if @update_block
70
- end
70
+ end
71
71
 
72
- def note_on(chan, note, vel)
72
+ def note_on(chan, note, vel)
73
73
  if vel == 0
74
- note_off(chan, note, 64)
75
- return
74
+ note_off(chan, note, 64)
75
+ return
76
76
  end
77
77
 
78
78
  on = NoteOn.new(chan, note, vel, @curr_ticks)
79
79
  @track.events << on
80
80
  @pending << on
81
81
  track_uses_channel(chan)
82
- end
82
+ end
83
83
 
84
- def note_off(chan, note, vel)
84
+ def note_off(chan, note, vel)
85
85
  # Find note on, create note off, connect the two, and remove
86
86
  # note on from pending list.
87
- @pending.each_with_index { | on, i |
88
- if on.note == note && on.channel == chan
89
- make_note_off(on, vel)
90
- @pending.delete_at(i)
91
- return
92
- end
93
- }
87
+ @pending.each_with_index do |on, i|
88
+ if on.note == note && on.channel == chan
89
+ make_note_off(on, vel)
90
+ @pending.delete_at(i)
91
+ return
92
+ end
93
+ end
94
94
  $stderr.puts "note off with no earlier note on (ch #{chan}, note" +
95
- " #{note}, vel #{vel})" if $DEBUG
96
- end
95
+ " #{note}, vel #{vel})" if $DEBUG
96
+ end
97
97
 
98
- def make_note_off(on, vel)
98
+ def make_note_off(on, vel)
99
99
  off = NoteOff.new(on.channel, on.note, vel, @curr_ticks)
100
100
  @track.events << off
101
101
  on.off = off
102
102
  off.on = on
103
- end
103
+ end
104
104
 
105
- def pressure(chan, note, press)
105
+ def pressure(chan, note, press)
106
106
  @track.events << PolyPressure.new(chan, note, press, @curr_ticks)
107
107
  track_uses_channel(chan)
108
- end
108
+ end
109
109
 
110
- def controller(chan, control, value)
110
+ def controller(chan, control, value)
111
111
  @track.events << Controller.new(chan, control, value, @curr_ticks)
112
112
  track_uses_channel(chan)
113
- end
113
+ end
114
114
 
115
- def pitch_bend(chan, lsb, msb)
115
+ def pitch_bend(chan, lsb, msb)
116
116
  @track.events << PitchBend.new(chan, (msb << 7) + lsb, @curr_ticks)
117
117
  track_uses_channel(chan)
118
- end
118
+ end
119
119
 
120
- def program(chan, program)
120
+ def program(chan, program)
121
121
  @track.events << ProgramChange.new(chan, program, @curr_ticks)
122
122
  track_uses_channel(chan)
123
- end
123
+ end
124
124
 
125
- def chan_pressure(chan, press)
125
+ def chan_pressure(chan, press)
126
126
  @track.events << ChannelPressure.new(chan, press, @curr_ticks)
127
127
  track_uses_channel(chan)
128
- end
128
+ end
129
129
 
130
- def sysex(msg)
130
+ def sysex(msg)
131
131
  @track.events << SystemExclusive.new(msg, @curr_ticks)
132
- end
132
+ end
133
133
 
134
- def meta_misc(type, msg)
134
+ def meta_misc(type, msg)
135
135
  @track.events << MetaEvent.new(type, msg, @curr_ticks)
136
- end
136
+ end
137
137
 
138
- # --
139
- # def sequencer_specific(type, msg)
140
- # end
138
+ # --
139
+ # def sequencer_specific(type, msg)
140
+ # end
141
141
 
142
- # def sequence_number(num)
143
- # end
144
- # ++
142
+ # def sequence_number(num)
143
+ # end
144
+ # ++
145
145
 
146
- def text(type, msg)
146
+ def text(type, msg)
147
147
  case type
148
148
  when META_TEXT, META_LYRIC, META_CUE
149
- @track.events << MetaEvent.new(type, msg, @curr_ticks)
149
+ @track.events << MetaEvent.new(type, msg, @curr_ticks)
150
150
  when META_SEQ_NAME, META_COPYRIGHT
151
- @track.events << MetaEvent.new(type, msg, 0)
152
- when META_INSTRUMENT
153
- @track.instrument = msg
151
+ @track.events << MetaEvent.new(type, msg, 0)
152
+ when META_INSTRUMENT
153
+ @track.instrument = msg
154
154
  when META_MARKER
155
- @track.events << Marker.new(msg, @curr_ticks)
155
+ @track.events << Marker.new(msg, @curr_ticks)
156
156
  else
157
- $stderr.puts "text = #{msg}, type = #{type}" if $DEBUG
157
+ $stderr.puts "text = #{msg}, type = #{type}" if $DEBUG
158
158
  end
159
- end
160
-
161
- # --
162
- # Don't bother adding the META_TRACK_END event to the track. This way,
163
- # we don't have to worry about always making sure the last event is
164
- # always a track end event. We just have to make sure to write one when
165
- # the track is output back to a file.
166
- # def eot()
167
- # @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
168
- # end
169
- # ++
170
-
171
- def time_signature(numer, denom, clocks, qnotes)
159
+ end
160
+
161
+ # --
162
+ # Don't bother adding the META_TRACK_END event to the track. This way,
163
+ # we don't have to worry about always making sure the last event is
164
+ # always a track end event. We just have to make sure to write one when
165
+ # the track is output back to a file.
166
+ # def eot()
167
+ # @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
168
+ # end
169
+ # ++
170
+
171
+ def time_signature(numer, denom, clocks, qnotes)
172
172
  @seq.time_signature(numer, denom, clocks, qnotes)
173
173
  @track.events << TimeSig.new(numer, denom, clocks, qnotes, @curr_ticks)
174
- end
174
+ end
175
175
 
176
- # --
177
- # def smpte(hour, min, sec, frame, fract)
178
- # end
179
- # ++
176
+ # --
177
+ # def smpte(hour, min, sec, frame, fract)
178
+ # end
179
+ # ++
180
180
 
181
- def tempo(microsecs)
181
+ def tempo(microsecs)
182
182
  @track.events << Tempo.new(microsecs, @curr_ticks)
183
- end
183
+ end
184
184
 
185
- def key_signature(sharpflat, is_minor)
186
- @track.events << KeySig.new(sharpflat, is_minor, @curr_ticks)
187
- end
185
+ def key_signature(sharpflat, is_minor)
186
+ @track.events << KeySig.new(sharpflat, is_minor, @curr_ticks)
187
+ end
188
188
 
189
- # --
190
- # def arbitrary(msg)
191
- # end
192
- # ++
189
+ # --
190
+ # def arbitrary(msg)
191
+ # end
192
+ # ++
193
193
 
194
- # Return true if the current track uses the specified channel.
195
- def track_uses_channel(chan)
194
+ # Return true if the current track uses the specified channel.
195
+ def track_uses_channel(chan)
196
196
  @chan_mask = @chan_mask | (1 << chan)
197
- end
197
+ end
198
198
 
199
- end
199
+ end
200
200
 
201
- end
201
+ end
202
202
  end
@@ -5,36 +5,36 @@ require 'midilib/utils'
5
5
 
6
6
  module MIDI
7
7
 
8
- module IO
8
+ module IO
9
9
 
10
- class SeqWriter
10
+ class SeqWriter
11
11
 
12
- def initialize(seq, proc = nil) # :yields: num_tracks, index
12
+ def initialize(seq, proc = nil) # :yields: num_tracks, index
13
13
  @seq = seq
14
14
  @update_block = block_given?() ? Proc.new() : proc
15
- end
15
+ end
16
16
 
17
- # Writes a MIDI format 1 file.
18
- def write_to(io)
17
+ # Writes a MIDI format 1 file.
18
+ def write_to(io)
19
19
  @io = io
20
20
  @bytes_written = 0
21
21
  write_header()
22
22
  @update_block.call(nil, @seq.tracks.length, 0) if @update_block
23
- @seq.tracks.each_with_index { | track, i |
24
- write_track(track)
25
- @update_block.call(track, @seq.tracks.length, i) if @update_block
26
- }
27
- end
23
+ @seq.tracks.each_with_index do |track, i|
24
+ write_track(track)
25
+ @update_block.call(track, @seq.tracks.length, i) if @update_block
26
+ end
27
+ end
28
28
 
29
- def write_header
29
+ def write_header
30
30
  @io.print 'MThd'
31
31
  write32(6)
32
32
  write16(1) # Ignore sequence format; write as format 1
33
33
  write16(@seq.tracks.length)
34
34
  write16(@seq.ppqn)
35
- end
35
+ end
36
36
 
37
- def write_track(track)
37
+ def write_track(track)
38
38
  @io.print 'MTrk'
39
39
  track_size_file_pos = @io.tell()
40
40
  write32(0) # Dummy byte count; overwritten later
@@ -44,23 +44,22 @@ class SeqWriter
44
44
 
45
45
  prev_event = nil
46
46
  prev_status = 0
47
- track.events.each { | event |
48
- if !event.kind_of?(Realtime)
49
- write_var_len(event.delta_time)
50
- end
47
+ track.events.each do |event|
48
+ if !event.kind_of?(Realtime)
49
+ write_var_len(event.delta_time)
50
+ end
51
51
 
52
- data = event.data_as_bytes()
53
- status = data[0] # status byte plus channel number, if any
52
+ data = event.data_as_bytes()
53
+ status = data[0] # status byte plus channel number, if any
54
54
 
55
- # running status byte
56
- status = possibly_munge_due_to_running_status_byte(data,
57
- prev_status)
55
+ # running status byte
56
+ status = possibly_munge_due_to_running_status_byte(data, prev_status)
58
57
 
59
- @bytes_written += write_bytes(data)
58
+ @bytes_written += write_bytes(data)
60
59
 
61
- prev_event = event
62
- prev_status = status
63
- }
60
+ prev_event = event
61
+ prev_status = status
62
+ end
64
63
 
65
64
  # Write track end event.
66
65
  event = MetaEvent.new(META_TRACK_END)
@@ -72,12 +71,12 @@ class SeqWriter
72
71
  @io.seek(track_size_file_pos)
73
72
  write32(@bytes_written)
74
73
  @io.seek(0, ::IO::SEEK_END)
75
- end
74
+ end
76
75
 
77
- # If we can use a running status byte, delete the status byte from
78
- # the given data. Return the status to remember for next time as the
79
- # running status byte for this event.
80
- def possibly_munge_due_to_running_status_byte(data, prev_status)
76
+ # If we can use a running status byte, delete the status byte from
77
+ # the given data. Return the status to remember for next time as the
78
+ # running status byte for this event.
79
+ def possibly_munge_due_to_running_status_byte(data, prev_status)
81
80
  status = data[0]
82
81
  return status if status >= 0xf0 || prev_status >= 0xf0
83
82
 
@@ -91,49 +90,49 @@ class SeqWriter
91
90
  # exactly the same, the rest is trivial. If it's note on/note off,
92
91
  # we can combine those further.
93
92
  if status == prev_status
94
- data[0,1] = [] # delete status byte from data
95
- return status + chan
93
+ data[0,1] = [] # delete status byte from data
94
+ return status + chan
96
95
  elsif status == NOTE_OFF && data[2] == 64
97
- # If we see a note off and the velocity is 64, we can store
98
- # a note on with a velocity of 0. If the velocity isn't 64
99
- # then storing a note on would be bad because the would be
100
- # changed to 64 when reading the file back in.
101
- data[2] = 0 # set vel to 0; do before possible shrinking
102
- status = NOTE_ON + chan
103
- if prev_status == NOTE_ON
104
- data[0,1] = [] # delete status byte
105
- else
106
- data[0] = status
107
- end
108
- return status
96
+ # If we see a note off and the velocity is 64, we can store
97
+ # a note on with a velocity of 0. If the velocity isn't 64
98
+ # then storing a note on would be bad because the would be
99
+ # changed to 64 when reading the file back in.
100
+ data[2] = 0 # set vel to 0; do before possible shrinking
101
+ status = NOTE_ON + chan
102
+ if prev_status == NOTE_ON
103
+ data[0,1] = [] # delete status byte
104
+ else
105
+ data[0] = status
106
+ end
107
+ return status
109
108
  else
110
- # Can't compress data
111
- return status + chan
109
+ # Can't compress data
110
+ return status + chan
112
111
  end
113
- end
112
+ end
114
113
 
115
- def write_instrument(instrument)
114
+ def write_instrument(instrument)
116
115
  event = MetaEvent.new(META_INSTRUMENT, instrument)
117
116
  write_var_len(0)
118
117
  data = event.data_as_bytes()
119
118
  @bytes_written += write_bytes(data)
120
- end
119
+ end
121
120
 
122
- def write_var_len(val)
121
+ def write_var_len(val)
123
122
  buffer = Utils.as_var_len(val)
124
123
  @bytes_written += write_bytes(buffer)
125
- end
124
+ end
126
125
 
127
- def write16(val)
126
+ def write16(val)
128
127
  val = (-val | 0x8000) if val < 0
129
128
 
130
129
  buffer = []
131
130
  @io.putc((val >> 8) & 0xff)
132
131
  @io.putc(val & 0xff)
133
132
  @bytes_written += 2
134
- end
133
+ end
135
134
 
136
- def write32(val)
135
+ def write32(val)
137
136
  val = (-val | 0x80000000) if val < 0
138
137
 
139
138
  @io.putc((val >> 24) & 0xff)
@@ -141,13 +140,13 @@ class SeqWriter
141
140
  @io.putc((val >> 8) & 0xff)
142
141
  @io.putc(val & 0xff)
143
142
  @bytes_written += 4
144
- end
143
+ end
145
144
 
146
- def write_bytes(bytes)
145
+ def write_bytes(bytes)
147
146
  bytes.each { |b| @io.putc(b) }
148
147
  bytes.length
148
+ end
149
149
  end
150
- end
151
150
 
152
- end
151
+ end
153
152
  end