midilib 2.0.5 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/ChangeLog +2 -1
- data/Credits +39 -2
- data/README.rdoc +5 -6
- data/Rakefile +36 -49
- data/TODO.rdoc +13 -2
- data/examples/from_scratch.rb +1 -1
- data/examples/measures_mbt.rb +11 -11
- data/examples/print_program_changes.rb +2 -2
- data/examples/reader2text.rb +47 -47
- data/examples/seq2text.rb +1 -1
- data/examples/split.rb +4 -3
- data/examples/strings.rb +4 -4
- data/examples/transpose.rb +19 -20
- data/install.rb +21 -13
- data/lib/midilib/consts.rb +237 -239
- data/lib/midilib/event.rb +128 -100
- data/lib/midilib/info.rb +3 -5
- data/lib/midilib/io/midifile.rb +155 -182
- data/lib/midilib/io/seqreader.rb +80 -85
- data/lib/midilib/io/seqwriter.rb +93 -88
- data/lib/midilib/measure.rb +78 -80
- data/lib/midilib/mergesort.rb +39 -0
- data/lib/midilib/sequence.rb +40 -32
- data/lib/midilib/track.rb +16 -57
- data/lib/midilib/utils.rb +4 -7
- data/lib/midilib.rb +5 -5
- data/test/event_equality.rb +28 -30
- data/test/test_event.rb +9 -11
- data/test/test_io.rb +83 -3
- data/test/test_mergesort.rb +37 -0
- data/test/test_midifile.rb +6 -19
- data/test/test_sequence.rb +5 -4
- data/test/test_track.rb +9 -38
- data/test/test_varlen.rb +1 -3
- metadata +8 -95
- data/html/IO.html +0 -155
- data/html/MIDI/ActiveSense.html +0 -206
- data/html/MIDI/ChannelEvent.html +0 -231
- data/html/MIDI/ChannelPressure.html +0 -265
- data/html/MIDI/Clock.html +0 -206
- data/html/MIDI/Continue.html +0 -206
- data/html/MIDI/Controller.html +0 -280
- data/html/MIDI/Event.html +0 -489
- data/html/MIDI/IO/MIDIFile.html +0 -2024
- data/html/MIDI/IO/SeqReader.html +0 -904
- data/html/MIDI/IO/SeqWriter.html +0 -572
- data/html/MIDI/IO.html +0 -95
- data/html/MIDI/KeySig.html +0 -353
- data/html/MIDI/MIDI/MIDI/Array.html +0 -255
- data/html/MIDI/MIDI/MIDI.html +0 -95
- data/html/MIDI/MIDI.html +0 -95
- data/html/MIDI/Marker.html +0 -158
- data/html/MIDI/Measure.html +0 -328
- data/html/MIDI/Measures.html +0 -285
- data/html/MIDI/MetaEvent.html +0 -461
- data/html/MIDI/NoteEvent.html +0 -331
- data/html/MIDI/NoteOff.html +0 -228
- data/html/MIDI/NoteOn.html +0 -228
- data/html/MIDI/PitchBend.html +0 -266
- data/html/MIDI/PolyPressure.html +0 -277
- data/html/MIDI/ProgramChange.html +0 -265
- data/html/MIDI/Realtime.html +0 -242
- data/html/MIDI/Sequence.html +0 -896
- data/html/MIDI/SongPointer.html +0 -266
- data/html/MIDI/SongSelect.html +0 -265
- data/html/MIDI/Start.html +0 -206
- data/html/MIDI/Stop.html +0 -206
- data/html/MIDI/SystemCommon.html +0 -158
- data/html/MIDI/SystemExclusive.html +0 -268
- data/html/MIDI/SystemReset.html +0 -206
- data/html/MIDI/Tempo.html +0 -396
- data/html/MIDI/TimeSig.html +0 -388
- data/html/MIDI/Track.html +0 -695
- data/html/MIDI/TuneRequest.html +0 -242
- data/html/MIDI/Utils.html +0 -220
- data/html/MIDI.html +0 -547
- data/html/README_rdoc.html +0 -731
- data/html/TODO_rdoc.html +0 -125
- data/html/created.rid +0 -14
- data/html/css/fonts.css +0 -167
- data/html/css/rdoc.css +0 -590
- 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 -768
- data/html/js/darkfish.js +0 -161
- data/html/js/jquery.js +0 -4
- data/html/js/navigation.js +0 -142
- data/html/js/navigation.js.gz +0 -0
- data/html/js/search.js +0 -109
- data/html/js/search_index.js +0 -1
- data/html/js/search_index.js.gz +0 -0
- data/html/js/searcher.js +0 -228
- data/html/js/searcher.js.gz +0 -0
- data/html/table_of_contents.html +0 -1265
data/lib/midilib/io/midifile.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
if RUBY_VERSION < '1.9'
|
4
|
-
class IO
|
5
|
-
def readbyte
|
6
|
-
c = getc()
|
7
|
-
raise 'unexpected EOF' unless c
|
8
|
-
c
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
1
|
+
require_relative '../consts'
|
12
2
|
|
13
3
|
module MIDI
|
14
|
-
|
15
4
|
module IO
|
16
|
-
|
17
5
|
# A MIDIFile parses a MIDI file and calls methods when it sees MIDI events.
|
18
6
|
# Most of the methods are stubs. To do anything interesting with the events,
|
19
7
|
# override these methods (those between the "The rest of these are NOPs by
|
@@ -22,7 +10,6 @@ module MIDI
|
|
22
10
|
# See SeqReader for a subclass that uses these methods to create Event
|
23
11
|
# objects.
|
24
12
|
class MIDIFile
|
25
|
-
|
26
13
|
MThd_BYTE_ARRAY = [77, 84, 104, 100] # "MThd"
|
27
14
|
MTrk_BYTE_ARRAY = [77, 84, 114, 107] # "MTrk"
|
28
15
|
|
@@ -30,60 +17,53 @@ module MIDI
|
|
30
17
|
# value is either the number of bytes needed (1 or 2) for a channel
|
31
18
|
# message, or 0 if it's not a channel message.
|
32
19
|
NUM_DATA_BYTES = [
|
33
|
-
|
34
|
-
|
20
|
+
0, 0, 0, 0, 0, 0, 0, 0, # 0x00 - 0x70
|
21
|
+
2, 2, 2, 2, 1, 1, 2, 0 # 0x80 - 0xf0
|
35
22
|
]
|
36
23
|
|
37
|
-
attr_accessor
|
38
|
-
attr_accessor :ticks_so_far # Number of delta-time ticks so far
|
39
|
-
attr_accessor :bytes_to_be_read # Counts number of bytes expected
|
40
|
-
|
41
|
-
attr_accessor :no_merge # true means continued sysex are not collapsed
|
42
|
-
attr_accessor :skip_init # true if initial garbage should be skipped
|
24
|
+
attr_accessor :curr_ticks, :ticks_so_far, :bytes_to_be_read, :no_merge, :skip_init, :raw_var_num_data, :raw_data # Current time, from delta-time in MIDI file # Number of delta-time ticks so far # Counts number of bytes expected # true means continued sysex are not collapsed # true if initial garbage should be skipped
|
43
25
|
|
44
26
|
# Raw data info
|
45
|
-
attr_accessor
|
46
|
-
attr_accessor :raw_var_num_data
|
47
|
-
attr_accessor :raw_data
|
27
|
+
attr_accessor :raw_time_stamp_data
|
48
28
|
|
49
29
|
def initialize
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
30
|
+
@no_merge = false
|
31
|
+
@skip_init = true
|
32
|
+
@io = nil
|
33
|
+
@bytes_to_be_read = 0
|
34
|
+
@msg_buf = nil
|
55
35
|
end
|
56
36
|
|
57
37
|
# The only public method. Each MIDI event in the file causes a
|
58
38
|
# method to be called.
|
59
39
|
def read_from(io)
|
60
|
-
|
61
|
-
|
40
|
+
error('must specify non-nil input stream') if io.nil?
|
41
|
+
@io = io
|
62
42
|
|
63
|
-
|
64
|
-
|
43
|
+
ntrks = read_header
|
44
|
+
error('No tracks!') if ntrks <= 0
|
65
45
|
|
66
|
-
|
46
|
+
ntrks.times { read_track }
|
67
47
|
end
|
68
48
|
|
69
49
|
# This default getc implementation tries to read a single byte
|
70
50
|
# from io and returns it as an integer.
|
71
51
|
def getc
|
72
52
|
@bytes_to_be_read -= 1
|
73
|
-
@io.readbyte
|
53
|
+
@io.readbyte
|
74
54
|
end
|
75
55
|
|
76
56
|
# Return the next +n+ bytes from @io as an array.
|
77
57
|
def get_bytes(n)
|
78
|
-
|
79
|
-
|
80
|
-
|
58
|
+
buf = []
|
59
|
+
n.times { buf << getc }
|
60
|
+
buf
|
81
61
|
end
|
82
62
|
|
83
63
|
# The default error handler.
|
84
64
|
def error(str)
|
85
|
-
|
86
|
-
|
65
|
+
loc = @io.tell - 1
|
66
|
+
raise "#{self.class.name} error at byte #{loc} (0x#{'%02x' % loc}): #{str}"
|
87
67
|
end
|
88
68
|
|
89
69
|
# The rest of these are NOPs by default.
|
@@ -95,7 +75,7 @@ module MIDI
|
|
95
75
|
def start_track(bytes_to_be_read)
|
96
76
|
end
|
97
77
|
|
98
|
-
def end_track
|
78
|
+
def end_track
|
99
79
|
end
|
100
80
|
|
101
81
|
def note_on(chan, note, vel)
|
@@ -134,7 +114,7 @@ module MIDI
|
|
134
114
|
def text(type, msg)
|
135
115
|
end
|
136
116
|
|
137
|
-
def eot
|
117
|
+
def eot
|
138
118
|
end
|
139
119
|
|
140
120
|
def time_signature(numer, denom, clocks, qnotes)
|
@@ -154,23 +134,20 @@ module MIDI
|
|
154
134
|
|
155
135
|
# End of NOPs.
|
156
136
|
|
157
|
-
|
158
137
|
# Read through 'MThd' or 'MTrk' header string. If skip is true, attempt
|
159
138
|
# to skip initial trash. If there is an error, #error is called.
|
160
139
|
def read_mt_header_string(bytes, skip)
|
161
|
-
|
162
|
-
|
163
|
-
|
140
|
+
b = []
|
141
|
+
bytes_to_read = 4
|
142
|
+
while true
|
164
143
|
data = get_bytes(bytes_to_read)
|
165
144
|
b += data
|
166
|
-
if b.length < 4
|
167
|
-
error("unexpected EOF while trying to read header string #{s}")
|
168
|
-
end
|
145
|
+
error("unexpected EOF while trying to read header string #{s}") if b.length < 4
|
169
146
|
|
170
147
|
# See if we found the bytes we're looking for
|
171
148
|
return if b == bytes
|
172
149
|
|
173
|
-
if skip
|
150
|
+
if skip # Try again with the next char
|
174
151
|
i = b[1..-1].index(bytes[0])
|
175
152
|
if i.nil?
|
176
153
|
b = []
|
@@ -180,59 +157,57 @@ module MIDI
|
|
180
157
|
bytes_to_read = 4 - i
|
181
158
|
end
|
182
159
|
else
|
183
|
-
error("header string #{bytes.collect{|b| b.chr}.join} not found")
|
160
|
+
error("header string #{bytes.collect { |b| b.chr }.join} not found")
|
184
161
|
end
|
185
|
-
|
162
|
+
end
|
186
163
|
end
|
187
164
|
|
188
165
|
# Read a header chunk.
|
189
166
|
def read_header
|
190
|
-
|
191
|
-
|
167
|
+
@bytes_to_be_read = 0
|
168
|
+
read_mt_header_string(MThd_BYTE_ARRAY, @skip_init) # "MThd"
|
192
169
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
170
|
+
@bytes_to_be_read = read32
|
171
|
+
format = read16
|
172
|
+
ntrks = read16
|
173
|
+
division = read16
|
197
174
|
|
198
|
-
|
175
|
+
header(format, ntrks, division)
|
199
176
|
|
200
|
-
|
201
|
-
|
177
|
+
# Flush any extra stuff, in case the length of the header is not 6
|
178
|
+
if @bytes_to_be_read > 0
|
202
179
|
get_bytes(@bytes_to_be_read)
|
203
180
|
@bytes_to_be_read = 0
|
204
|
-
|
181
|
+
end
|
205
182
|
|
206
|
-
|
183
|
+
ntrks
|
207
184
|
end
|
208
185
|
|
209
186
|
# Read a track chunk.
|
210
187
|
def read_track
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
188
|
+
c = c1 = type = needed = 0
|
189
|
+
sysex_continue = false # True if last msg was unfinished
|
190
|
+
running = false # True when running status used
|
191
|
+
status = 0 # (Possibly running) status byte
|
215
192
|
|
216
|
-
|
217
|
-
|
193
|
+
@bytes_to_be_read = 0
|
194
|
+
read_mt_header_string(MTrk_BYTE_ARRAY, false)
|
218
195
|
|
219
|
-
|
220
|
-
|
196
|
+
@bytes_to_be_read = read32
|
197
|
+
@curr_ticks = @ticks_so_far = 0
|
221
198
|
|
222
|
-
|
199
|
+
start_track
|
223
200
|
|
224
|
-
|
225
|
-
@curr_ticks = read_var_len
|
201
|
+
while @bytes_to_be_read > 0
|
202
|
+
@curr_ticks = read_var_len # Delta time
|
226
203
|
@ticks_so_far += @curr_ticks
|
227
204
|
|
228
205
|
# Copy raw var num data into raw time stamp data
|
229
|
-
@raw_time_stamp_data = @raw_var_num_data.dup
|
206
|
+
@raw_time_stamp_data = @raw_var_num_data.dup
|
230
207
|
|
231
|
-
c = getc
|
208
|
+
c = getc # Read first byte
|
232
209
|
|
233
|
-
if sysex_continue && c != EOX
|
234
|
-
error("didn't find expected continuation of a sysex")
|
235
|
-
end
|
210
|
+
error("didn't find expected continuation of a sysex") if sysex_continue && c != EOX
|
236
211
|
|
237
212
|
if (c & 0x80).zero? # Running status?
|
238
213
|
error('unexpected running status') if status.zero?
|
@@ -244,223 +219,221 @@ module MIDI
|
|
244
219
|
|
245
220
|
needed = NUM_DATA_BYTES[(status >> 4) & 0x0f]
|
246
221
|
|
247
|
-
if needed.nonzero?
|
248
|
-
c1 = running ? c : (getc
|
222
|
+
if needed.nonzero? # i.e., is it a channel message?
|
223
|
+
c1 = running ? c : (getc & 0x7f)
|
249
224
|
|
250
225
|
# The "& 0x7f" here may seem unnecessary, but I've seen
|
251
226
|
# "bad" MIDI files that had, for example, volume bytes
|
252
227
|
# with the upper bit set. This code should not harm
|
253
228
|
# proper data.
|
254
229
|
chan_message(running, status, c1,
|
255
|
-
|
230
|
+
needed > 1 ? (getc & 0x7f) : 0)
|
256
231
|
next
|
257
232
|
end
|
258
233
|
|
259
234
|
case c
|
260
|
-
when META_EVENT
|
261
|
-
type = getc
|
262
|
-
msg_init
|
263
|
-
msg_read(read_var_len
|
235
|
+
when META_EVENT # Meta event
|
236
|
+
type = getc
|
237
|
+
msg_init
|
238
|
+
msg_read(read_var_len)
|
264
239
|
meta_event(type)
|
265
|
-
when SYSEX
|
266
|
-
msg_init
|
240
|
+
when SYSEX # Start of system exclusive
|
241
|
+
msg_init
|
267
242
|
msg_add(SYSEX)
|
268
|
-
c = msg_read(read_var_len
|
243
|
+
c = msg_read(read_var_len)
|
269
244
|
|
270
245
|
if c == EOX || !@no_merge
|
271
|
-
handle_sysex(msg
|
246
|
+
handle_sysex(msg)
|
272
247
|
else
|
273
248
|
sysex_continue = true
|
274
249
|
end
|
275
|
-
when EOX
|
276
|
-
msg_init
|
277
|
-
c = msg_read(read_var_len
|
250
|
+
when EOX # Sysex continuation or arbitrary stuff
|
251
|
+
msg_init unless sysex_continue
|
252
|
+
c = msg_read(read_var_len)
|
278
253
|
|
279
254
|
if !sysex_continue
|
280
|
-
handle_arbitrary(msg
|
255
|
+
handle_arbitrary(msg)
|
281
256
|
elsif c == EOX
|
282
|
-
handle_sysex(msg
|
257
|
+
handle_sysex(msg)
|
283
258
|
sysex_continue = false
|
284
259
|
end
|
285
260
|
else
|
286
261
|
bad_byte(c)
|
287
262
|
end
|
288
|
-
|
289
|
-
|
263
|
+
end
|
264
|
+
end_track
|
290
265
|
end
|
291
266
|
|
292
267
|
# Handle an unexpected byte.
|
293
268
|
def bad_byte(c)
|
294
|
-
|
269
|
+
error(format('unexpected byte: 0x%02x', c))
|
295
270
|
end
|
296
271
|
|
297
272
|
# Handle a meta event.
|
298
273
|
def meta_event(type)
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
274
|
+
m = msg # Copy of internal message buffer
|
275
|
+
|
276
|
+
# Create raw data array
|
277
|
+
@raw_data = []
|
278
|
+
@raw_data << META_EVENT
|
279
|
+
@raw_data << type
|
280
|
+
@raw_data << @raw_var_num_data
|
281
|
+
@raw_data << m
|
282
|
+
@raw_data.flatten!
|
283
|
+
|
284
|
+
case type
|
285
|
+
when META_SEQ_NUM
|
311
286
|
sequence_number((m[0] << 8) + m[1])
|
312
|
-
|
313
|
-
|
314
|
-
|
287
|
+
when META_TEXT, META_COPYRIGHT, META_SEQ_NAME, META_INSTRUMENT,
|
288
|
+
META_LYRIC, META_MARKER, META_CUE, 0x08, 0x09, 0x0a,
|
289
|
+
0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
315
290
|
text(type, m)
|
316
|
-
|
317
|
-
eot
|
318
|
-
|
291
|
+
when META_TRACK_END
|
292
|
+
eot
|
293
|
+
when META_SET_TEMPO
|
319
294
|
tempo((m[0] << 16) + (m[1] << 8) + m[2])
|
320
|
-
|
295
|
+
when META_SMPTE
|
321
296
|
smpte(m[0], m[1], m[2], m[3], m[4])
|
322
|
-
|
297
|
+
when META_TIME_SIG
|
323
298
|
time_signature(m[0], m[1], m[2], m[3])
|
324
|
-
|
325
|
-
key_signature(m[0], m[1] == 0
|
326
|
-
|
299
|
+
when META_KEY_SIG
|
300
|
+
key_signature(m[0], !(m[1] == 0))
|
301
|
+
when META_SEQ_SPECIF
|
327
302
|
sequencer_specific(type, m)
|
328
|
-
|
303
|
+
else
|
329
304
|
meta_misc(type, m)
|
330
|
-
|
305
|
+
end
|
331
306
|
end
|
332
307
|
|
333
308
|
# Handle a channel message (note on, note off, etc.)
|
334
309
|
def chan_message(running, status, c1, c2)
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
310
|
+
@raw_data = []
|
311
|
+
@raw_data << status unless running
|
312
|
+
@raw_data << c1
|
313
|
+
@raw_data << c2
|
339
314
|
|
340
|
-
|
315
|
+
chan = status & 0x0f
|
341
316
|
|
342
|
-
|
343
|
-
|
317
|
+
case (status & 0xf0)
|
318
|
+
when NOTE_OFF
|
344
319
|
note_off(chan, c1, c2)
|
345
|
-
|
320
|
+
when NOTE_ON
|
346
321
|
note_on(chan, c1, c2)
|
347
|
-
|
322
|
+
when POLY_PRESSURE
|
348
323
|
pressure(chan, c1, c2)
|
349
|
-
|
324
|
+
when CONTROLLER
|
350
325
|
controller(chan, c1, c2)
|
351
|
-
|
326
|
+
when PITCH_BEND
|
352
327
|
pitch_bend(chan, c1, c2)
|
353
|
-
|
328
|
+
when PROGRAM_CHANGE
|
354
329
|
program(chan, c1)
|
355
|
-
|
330
|
+
when CHANNEL_PRESSURE
|
356
331
|
chan_pressure(chan, c1)
|
357
|
-
|
358
|
-
error("illegal chan message 0x#{'%02x'
|
359
|
-
|
332
|
+
else
|
333
|
+
error("illegal chan message 0x#{format('%02x', (status & 0xf0))}\n")
|
334
|
+
end
|
360
335
|
end
|
361
336
|
|
362
337
|
# Copy message into raw data array, then call sysex().
|
363
338
|
def handle_sysex(msg)
|
364
|
-
|
365
|
-
|
339
|
+
@raw_data = msg.dup
|
340
|
+
sysex(msg)
|
366
341
|
end
|
367
342
|
|
368
343
|
# Copy message into raw data array, then call arbitrary().
|
369
344
|
def handle_arbitrary(msg)
|
370
|
-
|
371
|
-
|
345
|
+
@raw_data = msg.dup
|
346
|
+
arbitrary(msg)
|
372
347
|
end
|
373
348
|
|
374
349
|
# Read and return a sixteen bit value.
|
375
350
|
def read16
|
376
|
-
|
377
|
-
|
378
|
-
|
351
|
+
val = (getc << 8) + getc
|
352
|
+
val = -(val & 0x7fff) if (val & 0x8000).nonzero?
|
353
|
+
val
|
379
354
|
end
|
380
355
|
|
381
356
|
# Read and return a 32-bit value.
|
382
357
|
def read32
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
358
|
+
val = (getc << 24) + (getc << 16) + (getc << 8) +
|
359
|
+
getc
|
360
|
+
val = -(val & 0x7fffffff) if (val & 0x80000000).nonzero?
|
361
|
+
val
|
387
362
|
end
|
388
363
|
|
389
364
|
# Read a varlen value.
|
390
365
|
def read_var_len
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
366
|
+
@raw_var_num_data = []
|
367
|
+
c = getc
|
368
|
+
@raw_var_num_data << c
|
369
|
+
val = c
|
370
|
+
if (val & 0x80).nonzero?
|
396
371
|
val &= 0x7f
|
397
372
|
while true
|
398
|
-
c = getc
|
373
|
+
c = getc
|
399
374
|
@raw_var_num_data << c
|
400
375
|
val = (val << 7) + (c & 0x7f)
|
401
376
|
break if (c & 0x80).zero?
|
402
377
|
end
|
403
|
-
|
404
|
-
|
378
|
+
end
|
379
|
+
val
|
405
380
|
end
|
406
381
|
|
407
382
|
# Write a sixteen-bit value.
|
408
383
|
def write16(val)
|
409
|
-
|
410
|
-
|
411
|
-
|
384
|
+
val = (-val) | 0x8000 if val < 0
|
385
|
+
putc((val >> 8) & 0xff)
|
386
|
+
putc(val & 0xff)
|
412
387
|
end
|
413
388
|
|
414
389
|
# Write a 32-bit value.
|
415
390
|
def write32(val)
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
391
|
+
val = (-val) | 0x80000000 if val < 0
|
392
|
+
putc((val >> 24) & 0xff)
|
393
|
+
putc((val >> 16) & 0xff)
|
394
|
+
putc((val >> 8) & 0xff)
|
395
|
+
putc(val & 0xff)
|
421
396
|
end
|
422
397
|
|
423
398
|
# Write a variable length value.
|
424
399
|
def write_var_len(val)
|
425
|
-
|
400
|
+
if val.zero?
|
426
401
|
putc(0)
|
427
402
|
return
|
428
|
-
|
403
|
+
end
|
429
404
|
|
430
|
-
|
405
|
+
buf = []
|
431
406
|
|
432
|
-
|
433
|
-
|
407
|
+
buf << (val & 0x7f)
|
408
|
+
while (value >>= 7) > 0
|
434
409
|
buf << (val & 0x7f) | 0x80
|
435
|
-
|
410
|
+
end
|
436
411
|
|
437
|
-
|
412
|
+
buf.reverse.each { |b| putc(b) }
|
438
413
|
end
|
439
414
|
|
440
415
|
# Add a byte to the current message buffer.
|
441
416
|
def msg_add(c)
|
442
|
-
|
417
|
+
@msg_buf << c
|
443
418
|
end
|
444
419
|
|
445
420
|
# Read and add a number of bytes to the message buffer. Return
|
446
421
|
# the last byte (so we can see if it's an EOX or not).
|
447
422
|
def msg_read(n_bytes)
|
448
|
-
|
449
|
-
|
450
|
-
|
423
|
+
@msg_buf += get_bytes(n_bytes)
|
424
|
+
@msg_buf.flatten!
|
425
|
+
@msg_buf[-1]
|
451
426
|
end
|
452
427
|
|
453
428
|
# Initialize the internal message buffer.
|
454
429
|
def msg_init
|
455
|
-
|
430
|
+
@msg_buf = []
|
456
431
|
end
|
457
432
|
|
458
433
|
# Return a copy of the internal message buffer.
|
459
434
|
def msg
|
460
|
-
|
435
|
+
@msg_buf.dup
|
461
436
|
end
|
462
|
-
|
463
437
|
end
|
464
|
-
|
465
438
|
end
|
466
439
|
end
|