smf 0.15.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/MANUAL +172 -0
  2. data/MANUAL.en +135 -0
  3. data/MANUAL.en.html +150 -0
  4. data/MANUAL.en.rd +144 -0
  5. data/MANUAL.html +201 -0
  6. data/MANUAL.rd +179 -0
  7. data/README +33 -0
  8. data/README.en +33 -0
  9. data/lib/smf.rb +736 -0
  10. data/lib/smf/divert.rb +21 -0
  11. data/lib/smf/io.rb +1278 -0
  12. data/lib/smf/toy/beatmap.rb +73 -0
  13. data/lib/smf/toy/gm.rb +327 -0
  14. data/lib/smf/toy/groove.rb +34 -0
  15. data/lib/smf/toy/macro.rb +282 -0
  16. data/lib/smf/toy/macro/mml.rb +34 -0
  17. data/lib/smf/toy/macro/mml/parser.rb +545 -0
  18. data/lib/smf/toy/macro/mml/parser.ry +239 -0
  19. data/lib/smf/toy/macro/stt.rb +33 -0
  20. data/lib/smf/toy/morse.rb +126 -0
  21. data/lib/smf/toy/quantize.rb +32 -0
  22. data/lib/smf/toy/rmi.rb +29 -0
  23. data/lib/smf/toy/searchsegment.rb +24 -0
  24. data/lib/smf/toy/shuffle.rb +39 -0
  25. data/lib/smf/toy/tempomap.rb +75 -0
  26. data/lib/smf/toy/text.rb +369 -0
  27. data/lib/smf/toy/velcomp.rb +42 -0
  28. data/lib/smf/toy/virtual.rb +118 -0
  29. data/lib/smf/toy/xml.rb +377 -0
  30. data/sample/Makefile +58 -0
  31. data/sample/bwv772.mid +0 -0
  32. data/sample/bwv772.mml +94 -0
  33. data/sample/bwv775.mid +0 -0
  34. data/sample/bwv775.mml +157 -0
  35. data/sample/bwv787.mid +0 -0
  36. data/sample/bwv787.mml +129 -0
  37. data/sample/groove.grv +33 -0
  38. data/sample/groove.rb +45 -0
  39. data/sample/ltvddpd2.mid +0 -0
  40. data/sample/ltvddpd2.stt +60 -0
  41. data/sample/merge.rb +38 -0
  42. data/sample/mml-samp.rb +19 -0
  43. data/sample/mml.rb +36 -0
  44. data/sample/morse-samp.rb +11 -0
  45. data/sample/morse.rb +31 -0
  46. data/sample/play-oss.rb +215 -0
  47. data/sample/play-oss2.rb +253 -0
  48. data/sample/play-oss3.rb +150 -0
  49. data/sample/play-spkr.rb +97 -0
  50. data/sample/play-win.rb +195 -0
  51. data/sample/quantize.rb +41 -0
  52. data/sample/rand1.rb +21 -0
  53. data/sample/rand2.rb +24 -0
  54. data/sample/rmi2smf.rb +26 -0
  55. data/sample/shuffle.rb +43 -0
  56. data/sample/smf2rmi.rb +26 -0
  57. data/sample/smf2smf.rb +26 -0
  58. data/sample/smf2text.rb +27 -0
  59. data/sample/smf2wav.rb +123 -0
  60. data/sample/smf2xml.rb +27 -0
  61. data/sample/split.rb +40 -0
  62. data/sample/stt-samp.rb +19 -0
  63. data/sample/stt.rb +36 -0
  64. data/sample/text2smf.rb +28 -0
  65. data/sample/velcomp.rb +45 -0
  66. data/sample/virtual-samp.rb +19 -0
  67. data/sample/xml2smf.rb +28 -0
  68. metadata +128 -0
@@ -0,0 +1,21 @@
1
+ # divert.rb: Written by Tadayoshi Funaba 2000, 2001
2
+ # $Id: divert.rb,v 1.3 2001-04-01 19:47:51+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ class Track
7
+
8
+ def divert(sq)
9
+ each do |ev|
10
+ n = yield ev
11
+ if n
12
+ sq[n] ||= Track.new
13
+ sq[n] << ev
14
+ end
15
+ end
16
+ self
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,1278 @@
1
+ # io.rb: Written by Tadayoshi Funaba 1998-2008
2
+ # $Id: io.rb,v 1.9 2008-11-12 19:24:09+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ class Sequence
7
+
8
+ class ReadError < StandardError; end
9
+
10
+ class RS
11
+
12
+ class PO
13
+
14
+ def self.u2s(u, w) u -= 2**w if u > 2**(w-1)-1; u end
15
+
16
+ def initialize(str) @str, @index = str, 0 end
17
+ def rem() @str.length - @index end
18
+ def eof? () rem <= 0 end
19
+ def skip(n) @index += n end
20
+
21
+ def getn(n)
22
+ raise EOFError if rem < n
23
+ s = @str[@index, n]
24
+ skip(n)
25
+ s
26
+ end
27
+
28
+ unless String === '0'[0]
29
+
30
+ def getc
31
+ raise EOFError if rem < 1
32
+ c = @str[@index]
33
+ skip(1)
34
+ c
35
+ end
36
+
37
+ else
38
+
39
+ def getc
40
+ raise EOFError if rem < 1
41
+ c = @str[@index].ord
42
+ skip(1)
43
+ c
44
+ end
45
+
46
+ end
47
+
48
+ def getl
49
+ v = 0
50
+ begin
51
+ v <<= 7
52
+ c = getc
53
+ v |= c & 0x7f
54
+ end until (c & 0x80).zero?
55
+ v
56
+ end
57
+
58
+ def geti(n)
59
+ u = 0
60
+ n.times do
61
+ u <<= 8
62
+ c = getc
63
+ u |= c
64
+ end
65
+ u
66
+ end
67
+
68
+ def geti16() geti(2) end
69
+ def geti24() geti(3) end
70
+ def geti32() geti(4) end
71
+
72
+ def to_s() @str.dup end
73
+
74
+ end
75
+
76
+ def initialize(s, cb) @s, @cb = s, cb end
77
+
78
+ def read_header(s)
79
+ rs = RS::PO.new(s)
80
+ format = rs.geti16
81
+ ntrks = rs.geti16
82
+ div1 = rs.getc
83
+ div2 = rs.getc
84
+ if (div1 & 0x80) == 0
85
+ tc = nil
86
+ division = div1 << 8 | div2
87
+ else
88
+ tc = 0x100 - div1
89
+ division = div2
90
+ end
91
+ @cb.header(format, ntrks, division, tc)
92
+ end
93
+
94
+ def read_meta(type, data)
95
+ case type
96
+ when 0x0
97
+ rs = RS::PO.new(data)
98
+ num = rs.geti16
99
+ @cb.sequencenumber(num)
100
+ when 0x1..0xf
101
+ case type
102
+ when 0x1; @cb.generalpurposetext(data)
103
+ when 0x2; @cb.copyrightnotice(data)
104
+ when 0x3; @cb.trackname(data)
105
+ when 0x4; @cb.instrumentname(data)
106
+ when 0x5; @cb.lyric(data)
107
+ when 0x6; @cb.marker(data)
108
+ when 0x7; @cb.cuepoint(data)
109
+ when 0x8; @cb.programname(data)
110
+ when 0x9; @cb.devicename(data)
111
+ when 0xa; @cb.text0a(data)
112
+ when 0xb; @cb.text0b(data)
113
+ when 0xc; @cb.text0c(data)
114
+ when 0xd; @cb.text0d(data)
115
+ when 0xe; @cb.text0e(data)
116
+ when 0xf; @cb.text0f(data)
117
+ end
118
+ when 0x20
119
+ rs = RS::PO.new(data)
120
+ ch = rs.getc
121
+ @cb.channelprefix(ch)
122
+ when 0x21
123
+ rs = RS::PO.new(data)
124
+ num = rs.getc
125
+ @cb.midiport(num)
126
+ when 0x2f
127
+ @cb.endoftrack
128
+ when 0x51
129
+ rs = RS::PO.new(data)
130
+ tempo = rs.geti24
131
+ @cb.settempo(tempo)
132
+ when 0x54
133
+ rs = RS::PO.new(data)
134
+ hr = rs.getc
135
+ tc = [24, 25, 29, 30][(hr >> 5) & 0x3]
136
+ hr &= 0x1f
137
+ mn = rs.getc
138
+ se = rs.getc
139
+ fr = rs.getc
140
+ ff = rs.getc
141
+ @cb.smpteoffset(hr, mn, se, fr, ff, tc)
142
+ when 0x58
143
+ rs = RS::PO.new(data)
144
+ nn = rs.getc
145
+ dd = rs.getc
146
+ cc = rs.getc
147
+ bb = rs.getc
148
+ @cb.timesignature(nn, dd, cc, bb)
149
+ when 0x59
150
+ rs = RS::PO.new(data)
151
+ sf = rs.getc
152
+ mi = rs.getc
153
+ sf = RS::PO.u2s(sf, 8)
154
+ @cb.keysignature(sf, mi)
155
+ when 0x7f
156
+ @cb.sequencerspecific(data)
157
+ else
158
+ @cb.unknownmeta(type, data)
159
+ end
160
+ end
161
+
162
+ def read_track(s)
163
+ @cb.track_start
164
+ rs = RS::PO.new(s)
165
+ running = 0
166
+ until rs.eof?
167
+ @cb.delta(rs.getl)
168
+ stat = rs.getc
169
+ if (stat & 0x80) == 0
170
+ rs.skip(-1)
171
+ stat = running
172
+ else
173
+ case stat
174
+ when 0x80..0xef; running = stat
175
+ when 0xf0..0xf7; running = 0
176
+ end
177
+ end
178
+ case stat
179
+ when 0x80..0x8f
180
+ @cb.noteoff(stat & 0xf, rs.getc, rs.getc)
181
+ when 0x90..0x9f
182
+ @cb.noteon(stat & 0xf, rs.getc, rs.getc)
183
+ when 0xa0..0xaf
184
+ @cb.polyphonickeypressure(stat & 0xf, rs.getc, rs.getc)
185
+ when 0xb0..0xbf
186
+ n = rs.getc
187
+ v = rs.getc
188
+ if n < 0x78
189
+ @cb.controlchange(stat & 0xf, n, v)
190
+ else
191
+ case n
192
+ when 0x78; @cb.allsoundoff(stat & 0xf)
193
+ when 0x79; @cb.resetallcontrollers(stat & 0xf)
194
+ when 0x7a; @cb.localcontrol(stat & 0xf, v)
195
+ when 0x7b; @cb.allnotesoff(stat & 0xf)
196
+ when 0x7c; @cb.omnioff(stat & 0xf)
197
+ when 0x7d; @cb.omnion(stat & 0xf)
198
+ when 0x7e; @cb.monomode(stat & 0xf, v)
199
+ when 0x7f; @cb.polymode(stat & 0xf)
200
+ end
201
+ end
202
+ when 0xc0..0xcf
203
+ @cb.programchange(stat & 0xf, rs.getc)
204
+ when 0xd0..0xdf
205
+ @cb.channelpressure(stat & 0xf, rs.getc)
206
+ when 0xe0..0xef
207
+ lsb = rs.getc
208
+ msb = rs.getc
209
+ val = (lsb | msb << 7) - 0x2000
210
+ @cb.pitchbendchange(stat & 0xf, val)
211
+ when 0xf0, 0xf7
212
+ len = rs.getl
213
+ data = rs.getn(len)
214
+ if stat == 0xf0
215
+ @cb.exclusivef0(data)
216
+ else
217
+ @cb.exclusivef7(data)
218
+ end
219
+ when 0xff
220
+ type = rs.getc
221
+ len = rs.getl
222
+ data = rs.getn(len)
223
+ read_meta(type, data)
224
+ else
225
+ until rs.eof?
226
+ unless (rs.getc & 0x80) == 0
227
+ rs.skip(-1)
228
+ break
229
+ end
230
+ end
231
+ end
232
+ end
233
+ @cb.track_end
234
+ end
235
+
236
+ private :read_header, :read_meta, :read_track
237
+
238
+ def get_from_macbin
239
+ begin
240
+ if @s[0, 1] == "\000" && @s[74,1] == "\000" &&
241
+ @s[82,1] == "\000" && @s[65,4] == 'Midi'
242
+ @s[128,@s[83,4].unpack('N')[0]]
243
+ end
244
+ rescue
245
+ end
246
+ end
247
+
248
+ def get_from_rmid
249
+ begin
250
+ if @s[0,4] == 'RIFF' && @s[8,4] == 'RMID'
251
+ @s[20,@s[16,4].unpack('V')[0]]
252
+ end
253
+ rescue
254
+ end
255
+ end
256
+
257
+ private :get_from_macbin, :get_from_rmid
258
+
259
+ def read
260
+ begin
261
+ rs = RS::PO.new(get_from_macbin || get_from_rmid || @s)
262
+ ckid = rs.getn(4)
263
+ unless ckid == 'MThd'
264
+ @cb.error('not an SMF')
265
+ end
266
+ rs.skip(-4)
267
+ until rs.eof?
268
+ ckid = rs.getn(4)
269
+ leng = rs.geti32
270
+ body = rs.getn(leng)
271
+ case ckid
272
+ when 'MThd'
273
+ read_header(body)
274
+ when 'MTrk'
275
+ read_track(body)
276
+ else
277
+ @cb.unknownchunk(ckid, body)
278
+ end
279
+ end
280
+ rescue EOFError
281
+ @cb.error('unexpected EOF')
282
+ end
283
+ @cb.result
284
+ end
285
+
286
+ end
287
+
288
+ class WS
289
+
290
+ class PO
291
+
292
+ def self.s2u(s, w) s += 2**w if s < 0; s end
293
+
294
+ # def initialize() @str = '' end
295
+ def initialize() @arr = [] end
296
+
297
+ # def puts(s) @str << s end
298
+ # def putc(c) @str << c end
299
+
300
+ unless String === '0'[0]
301
+
302
+ def puts(s) @arr << s end
303
+ def putc(c) @arr << c.chr end
304
+
305
+ def putl(v)
306
+ s = ''
307
+ begin
308
+ s << (v & 0x7f | 0x80)
309
+ v >>= 7
310
+ end until v.zero?
311
+ s[0] &= 0x7f
312
+ s.reverse!
313
+ puts(s)
314
+ end
315
+
316
+ else
317
+
318
+ def puts(s) @arr << s.dup.force_encoding('ascii-8bit') end
319
+ def putc(c) @arr << c.chr.force_encoding('ascii-8bit') end
320
+
321
+ def putl(v)
322
+ s = ''.force_encoding('ascii-8bit')
323
+ begin
324
+ s << (v & 0x7f | 0x80)
325
+ v >>= 7
326
+ end until v.zero?
327
+ s[0] = (s.ord & 0x7f).chr
328
+ s.reverse!
329
+ puts(s)
330
+ end
331
+
332
+ end
333
+
334
+ def puti(n, u)
335
+ n.times do |i|
336
+ putc((u >> (n - i - 1) * 8) & 0xff)
337
+ end
338
+ end
339
+
340
+ def puti16(u) puti(2, u) end
341
+ def puti24(u) puti(3, u) end
342
+ def puti32(u) puti(4, u) end
343
+
344
+ # def to_s() @str.dup end
345
+ def to_s() @arr.join end
346
+
347
+ end
348
+
349
+ def initialize(o, cb) @o, @cb = o, cb end
350
+
351
+ def read_meta(ev)
352
+ case ev
353
+ when SequenceNumber
354
+ @cb.sequencenumber(ev.num)
355
+ when Text
356
+ case ev
357
+ when GeneralPurposeText; @cb.generalpurposetext(ev.text)
358
+ when CopyrightNotice; @cb.copyrightnotice(ev.text)
359
+ when TrackName; @cb.trackname(ev.text)
360
+ when InstrumentName; @cb.instrumentname(ev.text)
361
+ when Lyric; @cb.lyric(ev.text)
362
+ when Marker; @cb.marker(ev.text)
363
+ when CuePoint; @cb.cuepoint(ev.text)
364
+ when ProgramName; @cb.programname(ev.text)
365
+ when DeviceName; @cb.devicename(ev.text)
366
+ when Text0A; @cb.text0a(ev.text)
367
+ when Text0B; @cb.text0b(ev.text)
368
+ when Text0C; @cb.text0c(ev.text)
369
+ when Text0D; @cb.text0d(ev.text)
370
+ when Text0E; @cb.text0e(ev.text)
371
+ when Text0F; @cb.text0f(ev.text)
372
+ end
373
+ when ChannelPrefix
374
+ @cb.channelprefix(ev.ch)
375
+ when MIDIPort
376
+ @cb.midiport(ev.num)
377
+ when EndOfTrack
378
+ @cb.endoftrack
379
+ when SetTempo
380
+ @cb.settempo(ev.tempo)
381
+ when SMPTEOffset
382
+ @cb.smpteoffset(ev.hr, ev.mn, ev.se, ev.fr, ev.ff, ev.tc)
383
+ when TimeSignature
384
+ @cb.timesignature(ev.nn, ev.dd, ev.cc, ev.bb)
385
+ when KeySignature
386
+ @cb.keysignature(ev.sf, ev.mi)
387
+ when SequencerSpecific
388
+ @cb.sequencerspecific(ev.data)
389
+ else
390
+ @cb.unknownmeta(ev.type, ev.data)
391
+ end
392
+ end
393
+
394
+ def read_track(tr)
395
+ @cb.track_start
396
+ offset = 0
397
+ tr.each do |ev|
398
+ @cb.delta(ev.offset - offset)
399
+ case ev
400
+ when NoteOff
401
+ if ev.fake?
402
+ @cb.noteon(ev.ch, ev.note, 0)
403
+ else
404
+ @cb.noteoff(ev.ch, ev.note, ev.vel)
405
+ end
406
+ when NoteOn
407
+ @cb.noteon(ev.ch, ev.note, ev.vel)
408
+ when PolyphonicKeyPressure
409
+ @cb.polyphonickeypressure(ev.ch, ev.note, ev.val)
410
+ when ControlChange
411
+ @cb.controlchange(ev.ch, ev.num, ev.val)
412
+ when ProgramChange
413
+ @cb.programchange(ev.ch, ev.num)
414
+ when ChannelPressure
415
+ @cb.channelpressure(ev.ch, ev.val)
416
+ when PitchBendChange
417
+ @cb.pitchbendchange(ev.ch, ev.val)
418
+ when AllSoundOff
419
+ @cb.allsoundoff(ev.ch)
420
+ when ResetAllControllers
421
+ @cb.resetallcontrollers(ev.ch)
422
+ when LocalControl
423
+ @cb.localcontrol(ev.ch, ev.val)
424
+ when AllNotesOff
425
+ @cb.allnotesoff(ev.ch)
426
+ when OmniOff
427
+ @cb.omnioff(ev.ch)
428
+ when OmniOn
429
+ @cb.omnion(ev.ch)
430
+ when MonoMode
431
+ @cb.monomode(ev.ch, ev.val)
432
+ when PolyMode
433
+ @cb.polymode(ev.ch)
434
+ when ExclusiveF0
435
+ @cb.exclusivef0(ev.data)
436
+ when ExclusiveF7
437
+ @cb.exclusivef7(ev.data)
438
+ when Meta
439
+ read_meta(ev)
440
+ end
441
+ offset = ev.offset
442
+ end
443
+ @cb.track_end
444
+ end
445
+
446
+ private :read_meta, :read_track
447
+
448
+ def read
449
+ @cb.header(@o.format, @o.ntrks, @o.division, @o.tc)
450
+ @o.each do |ck|
451
+ case ck
452
+ when Track
453
+ read_track(ck)
454
+ else
455
+ @cb.unknownchunk(ck.ckid, ck.body)
456
+ end
457
+ end
458
+ @cb.result
459
+ end
460
+
461
+ end
462
+
463
+ class XSCallback
464
+
465
+ def header(format, ntrks, division, tc) end
466
+
467
+ def track_start() end
468
+ def track_end() end
469
+
470
+ def unknownchunk(ckid, body) end
471
+ def delta(delta) end
472
+
473
+ def noteoff(ch, note, vel) end
474
+ def noteon(ch, note, vel) end
475
+ def polyphonickeypressure(ch, note, val) end
476
+ def controlchange(ch, num, val) end
477
+ def programchange(ch, num) end
478
+ def channelpressure(ch, val) end
479
+ def pitchbendchange(ch, val) end
480
+
481
+ def allsoundoff(ch) end
482
+ def resetallcontrollers(ch) end
483
+ def localcontrol(ch, val) end
484
+ def allnotesoff(ch) end
485
+ def omnioff(ch) end
486
+ def omnion(ch) end
487
+ def monomode(ch, val) end
488
+ def polymode(ch) end
489
+
490
+ def exclusivef0(data) end
491
+ def exclusivef7(data) end
492
+
493
+ def sequencenumber(num) end
494
+
495
+ def generalpurposetext(text) end
496
+ def copyrightnotice(text) end
497
+ def trackname(text) end
498
+ def instrumentname(text) end
499
+ def lyric(text) end
500
+ def marker(text) end
501
+ def cuepoint(text) end
502
+ def programname(text) end
503
+ def devicename(text) end
504
+ def text0a(text) end
505
+ def text0b(text) end
506
+ def text0c(text) end
507
+ def text0d(text) end
508
+ def text0e(text) end
509
+ def text0f(text) end
510
+
511
+ def channelprefix(ch) end
512
+ def midiport(num) end
513
+ def endoftrack() end
514
+ def settempo(tempo) end
515
+ def smpteoffset(hr, mn, se, fr, ff, tc) end
516
+ def timesignature(nn, dd, cc, bb) end
517
+ def keysignature(sf, mi) end
518
+ def sequencerspecific(data) end
519
+
520
+ def unknownmeta(type, data) end
521
+
522
+ def result() end
523
+
524
+ def error(mesg) end
525
+ def warn(mesg) end
526
+
527
+ end
528
+
529
+ module Checker
530
+
531
+ def cr(n, v, e, w=nil)
532
+ unless e === v
533
+ error("#{n}: out of range")
534
+ return
535
+ end
536
+ if w
537
+ unless w === v
538
+ warn("#{n}: out of range")
539
+ end
540
+ end
541
+ end
542
+
543
+ private :cr
544
+
545
+ def header(format, ntrks, division, tc)
546
+ cr('header/format', format, (0..2**16-1), (0..2))
547
+ if format == 0
548
+ cr('header/ntrks', ntrks, (0..2**16-1), (1..1))
549
+ else
550
+ cr('header/ntrks', ntrks, (0..2**16-1), (1..2**16-1))
551
+ end
552
+ unless tc
553
+ cr('header/division', division, (1..2**15-1))
554
+ else
555
+ cr('header/division', division, (1..2**8-1))
556
+ cr('header/tc', tc, (0..2**7))
557
+ unless [24, 25, 29, 30].include? tc
558
+ warn('header/tc: invalid format')
559
+ end
560
+ end
561
+ super
562
+ end
563
+
564
+ def chunk_body(body)
565
+ unless body.length <= 2**32-1
566
+ error('chunk size: too large')
567
+ end
568
+ end
569
+
570
+ private :chunk_body
571
+
572
+ def delta(delta)
573
+ cr('delta', delta, (0..2**28-1))
574
+ super
575
+ end
576
+
577
+ def noteoff(ch, note, vel)
578
+ cr('noteoff/ch', ch, (0..2**4-1))
579
+ cr('noteoff/note', note, (0..2**7-1))
580
+ cr('noteoff/vel', vel, (0..2**7-1))
581
+ super
582
+ end
583
+
584
+ def noteon(ch, note, vel)
585
+ cr('noteon/ch', ch, (0..2**4-1))
586
+ cr('noteon/note', note, (0..2**7-1))
587
+ cr('noteon/vel', vel, (0..2**7-1))
588
+ super
589
+ end
590
+
591
+ def polyphonickeypressure(ch, note, val)
592
+ cr('polyphonickeypressure/ch', ch, (0..2**4-1))
593
+ cr('polyphonickeypressure/note', note, (0..2**7-1))
594
+ cr('polyphonickeypressure/val', val, (0..2**7-1))
595
+ super
596
+ end
597
+
598
+ def controlchange(ch, num, val)
599
+ cr('controlchange/ch', ch, (0..2**4-1))
600
+ cr('controlchange/num', num, (0..0x77))
601
+ cr('controlchange/val', val, (0..2**7-1))
602
+ super
603
+ end
604
+
605
+ def programchange(ch, num)
606
+ cr('programchange/ch', ch, (0..2**4-1))
607
+ cr('programchange/num', num, (0..2**7-1))
608
+ super
609
+ end
610
+
611
+ def channelpressure(ch, val)
612
+ cr('channelpressure/ch', ch, (0..2**4-1))
613
+ cr('channelpressure/val', val, (0..2**7-1))
614
+ super
615
+ end
616
+
617
+ def pitchbendchange(ch, val)
618
+ cr('pitchbendchange/ch', ch, (0..2**4-1))
619
+ cr('pitchbendchange/val', val, (-2**13..2**13-1))
620
+ super
621
+ end
622
+
623
+ def no_channelmodemessage(ch, num, val)
624
+ cr('channelmodemessage/ch', ch, (0..2**4-1))
625
+ cr('channelmodemessage/num', num, (0x78..0x7f))
626
+ unless num == 0x7e
627
+ cr('channelmodemessage/val', val, (0..2**7-1))
628
+ else
629
+ cr('channelmodemessage/val', val, (0..2**7-1), (0..16))
630
+ end
631
+ end
632
+
633
+ private :no_channelmodemessage
634
+
635
+ def allsoundoff(ch) no_channelmodemessage(ch, 0x78, 0); super end
636
+ def resetallcontrollers(ch) no_channelmodemessage(ch, 0x79, 0); super end
637
+ def localcontrol(ch, val) no_channelmodemessage(ch, 0x7a, val); super end
638
+ def allnotesoff(ch) no_channelmodemessage(ch, 0x7b, 0); super end
639
+ def omnioff(ch) no_channelmodemessage(ch, 0x7c, 0); super end
640
+ def omnion(ch) no_channelmodemessage(ch, 0x7d, 0); super end
641
+ def monomode(ch, val) no_channelmodemessage(ch, 0x7e, val); super end
642
+ def polymode(ch) no_channelmodemessage(ch, 0x7f, 0); super end
643
+
644
+ def exclusivef0(data)
645
+ cr('exclusive size', data.length, (0..2**28-1), (1..2**28-1))
646
+ super
647
+ end
648
+
649
+ def exclusivef7(data)
650
+ cr('exclusive size', data.length, (0..2**28-1), (1..2**28-1))
651
+ super
652
+ end
653
+
654
+ def sequencenumber(num)
655
+ cr('sequencenumber/num', num, (0..2**16-1))
656
+ super
657
+ end
658
+
659
+ def no_text(type, text)
660
+ cr('text size', text.length, (0..2**28-1), (1..2**28-1))
661
+ end
662
+
663
+ private :no_text
664
+
665
+ def generalpurposetext(text) no_text(0x1, text); super end
666
+ def copyrightnotice(text) no_text(0x2, text); super end
667
+ def trackname(text) no_text(0x3, text); super end
668
+ def instrumentname(text) no_text(0x4, text); super end
669
+ def lyric(text) no_text(0x5, text); super end
670
+ def marker(text) no_text(0x6, text); super end
671
+ def cuepoint(text) no_text(0x7, text); super end
672
+ def programname(text) no_text(0x8, text); super end
673
+ def devicename(text) no_text(0x9, text); super end
674
+ def text0a(text) no_text(0xa, text); super end
675
+ def text0b(text) no_text(0xb, text); super end
676
+ def text0c(text) no_text(0xc, text); super end
677
+ def text0d(text) no_text(0xd, text); super end
678
+ def text0e(text) no_text(0xe, text); super end
679
+ def text0f(text) no_text(0xf, text); super end
680
+
681
+ def channelprefix(ch)
682
+ cr('channelprefix/ch', ch, (0..2**8-1), (0..2**4-1))
683
+ super
684
+ end
685
+
686
+ def midiport(num)
687
+ cr('midiport/num', num, (0..2**8-1))
688
+ super
689
+ end
690
+
691
+ def settempo(tempo)
692
+ cr('settempo/tempo', tempo, (1..2**24-1))
693
+ super
694
+ end
695
+
696
+ def smpteoffset(hr, mn, se, fr, ff, tc)
697
+ cr('smpteoffset/hr', hr, (0..2**8-1), (1..23))
698
+ cr('smpteoffset/mn', mn, (0..2**8-1), (1..59))
699
+ cr('smpteoffset/se', se, (0..2**8-1), (1..59))
700
+ cr('smpteoffset/fr', fr, (0..2**8-1), (1..29))
701
+ cr('smpteoffset/ff', ff, (0..2**8-1), (1..99))
702
+ cr('smpteoffset/tc', tc, (0..2**8-1))
703
+ unless [24, 25, 29, 30].include? tc
704
+ warn('smpteoffset/tc: invalid format')
705
+ end
706
+ super
707
+ end
708
+
709
+ def timesignature(nn, dd, cc, bb)
710
+ cr('timesignature/nn', nn, (1..2**8-1))
711
+ cr('timesignature/dd', dd, (0..2**8-1))
712
+ cr('timesignature/cc', cc, (1..2**8-1))
713
+ cr('timesignature/bb', bb, (1..2**8-1))
714
+ super
715
+ end
716
+
717
+ def keysignature(sf, mi)
718
+ cr('keysignature/sf', sf, (-2**7..2**7-1))
719
+ cr('keysignature/mi', mi, (0..1))
720
+ super
721
+ end
722
+
723
+ def sequencerspecific(data)
724
+ unless data.length <= 2**28-1
725
+ error('sequencerspecific: too large')
726
+ end
727
+ super
728
+ end
729
+
730
+ def unknownmeta(type, data)
731
+ unless data.length <= 2**28-1
732
+ error('unknownmeta: too large')
733
+ end
734
+ super
735
+ end
736
+
737
+ end
738
+
739
+ class Decode < XSCallback
740
+
741
+ # include Checker
742
+
743
+ def header(format, ntrks, division, tc)
744
+ @sq = Sequence.new(format, division, tc)
745
+ end
746
+
747
+ def track_start
748
+ @sq << (@tr = Track.new)
749
+ @offset = 0
750
+ end
751
+
752
+ def delta(delta) @offset += delta end
753
+
754
+ def noteoff(ch, note, vel)
755
+ @tr << NoteOff.new(@offset, ch, note, vel)
756
+ end
757
+
758
+ def noteon(ch, note, vel)
759
+ if vel == 0
760
+ @tr << NoteOff.new(@offset, ch, note, nil)
761
+ else
762
+ @tr << NoteOn.new(@offset, ch, note, vel)
763
+ end
764
+ end
765
+
766
+ def polyphonickeypressure(ch, note, val)
767
+ @tr << PolyphonicKeyPressure.new(@offset, ch, note, val)
768
+ end
769
+
770
+ def controlchange(ch, num, val)
771
+ @tr << ControlChange.new(@offset, ch, num, val)
772
+ end
773
+
774
+ def programchange(ch, num)
775
+ @tr << ProgramChange.new(@offset, ch, num)
776
+ end
777
+
778
+ def channelpressure(ch, val)
779
+ @tr << ChannelPressure.new(@offset, ch, val)
780
+ end
781
+
782
+ def pitchbendchange(ch, val)
783
+ @tr << PitchBendChange.new(@offset, ch, val)
784
+ end
785
+
786
+ def allsoundoff(ch)
787
+ @tr << AllSoundOff.new(@offset, ch)
788
+ end
789
+
790
+ def resetallcontrollers(ch)
791
+ @tr << ResetAllControllers.new(@offset, ch)
792
+ end
793
+
794
+ def localcontrol(ch, val)
795
+ @tr << LocalControl.new(@offset, ch, val)
796
+ end
797
+
798
+ def allnotesoff(ch)
799
+ @tr << AllNotesOff.new(@offset, ch)
800
+ end
801
+
802
+ def omnioff(ch)
803
+ @tr << OmniOff.new(@offset, ch)
804
+ end
805
+
806
+ def omnion(ch)
807
+ @tr << OmniOn.new(@offset, ch)
808
+ end
809
+
810
+ def monomode(ch, val)
811
+ @tr << MonoMode.new(@offset, ch, val)
812
+ end
813
+
814
+ def polymode(ch)
815
+ @tr << PolyMode.new(@offset, ch)
816
+ end
817
+
818
+ def exclusivef0(data)
819
+ @tr << ExclusiveF0.new(@offset, data)
820
+ end
821
+
822
+ def exclusivef7(data)
823
+ @tr << ExclusiveF7.new(@offset, data)
824
+ end
825
+
826
+ def sequencenumber(num)
827
+ @tr << SequenceNumber.new(@offset, num)
828
+ end
829
+
830
+ def generalpurposetext(text)
831
+ @tr << GeneralPurposeText.new(@offset, text)
832
+ end
833
+
834
+ def copyrightnotice(text)
835
+ @tr << CopyrightNotice.new(@offset, text)
836
+ end
837
+
838
+ def trackname(text)
839
+ @tr << TrackName.new(@offset, text)
840
+ end
841
+
842
+ def instrumentname(text)
843
+ @tr << InstrumentName.new(@offset, text)
844
+ end
845
+
846
+ def lyric(text)
847
+ @tr << Lyric.new(@offset, text)
848
+ end
849
+
850
+ def marker(text)
851
+ @tr << Marker.new(@offset, text)
852
+ end
853
+
854
+ def cuepoint(text)
855
+ @tr << CuePoint.new(@offset, text)
856
+ end
857
+
858
+ def programname(text)
859
+ @tr << ProgramName.new(@offset, text)
860
+ end
861
+
862
+ def devicename(text)
863
+ @tr << DeviceName.new(@offset, text)
864
+ end
865
+
866
+ def text0a(text)
867
+ @tr << Text0A.new(@offset, text)
868
+ end
869
+
870
+ def text0b(text)
871
+ @tr << Text0B.new(@offset, text)
872
+ end
873
+
874
+ def text0c(text)
875
+ @tr << Text0C.new(@offset, text)
876
+ end
877
+
878
+ def text0d(text)
879
+ @tr << Text0D.new(@offset, text)
880
+ end
881
+
882
+ def text0e(text)
883
+ @tr << Text0E.new(@offset, text)
884
+ end
885
+
886
+ def text0f(text)
887
+ @tr << Text0F.new(@offset, text)
888
+ end
889
+
890
+ def channelprefix(ch)
891
+ @tr << ChannelPrefix.new(@offset, ch)
892
+ end
893
+
894
+ def midiport(num)
895
+ @tr << MIDIPort.new(@offset, num)
896
+ end
897
+
898
+ def endoftrack
899
+ @tr << EndOfTrack.new(@offset)
900
+ end
901
+
902
+ def settempo(tempo)
903
+ @tr << SetTempo.new(@offset, tempo)
904
+ end
905
+
906
+ def smpteoffset(hr, mn, se, fr, ff, tc)
907
+ @tr << SMPTEOffset.new(@offset, hr, mn, se, fr, ff, tc)
908
+ end
909
+
910
+ def timesignature(nn, dd, cc, bb)
911
+ @tr << TimeSignature.new(@offset, nn, dd, cc, bb)
912
+ end
913
+
914
+ def keysignature(sf, mi)
915
+ @tr << KeySignature.new(@offset, sf, mi)
916
+ end
917
+
918
+ def sequencerspecific(data)
919
+ @tr << SequencerSpecific.new(@offset, data)
920
+ end
921
+
922
+ def result() @sq end
923
+
924
+ def error(mesg) raise ReadError, mesg end
925
+
926
+ end
927
+
928
+ class Encode < XSCallback
929
+
930
+ # include Checker
931
+
932
+ @@replace_noteoff = false
933
+
934
+ def header(format, ntrks, division, tc)
935
+ @ws = WS::PO.new
936
+ @ws.puts('MThd')
937
+ @ws.puti32(6)
938
+ @ws.puti16(format)
939
+ @ws.puti16(ntrks)
940
+ if tc
941
+ div1 = 0x100 - tc
942
+ div2 = division
943
+ else
944
+ div1 = division >> 8
945
+ div2 = division & 0xff
946
+ end
947
+ @ws.putc(div1)
948
+ @ws.putc(div2)
949
+ end
950
+
951
+ def track_start
952
+ @ev = WS::PO.new
953
+ @running = 0
954
+ @cieot = false
955
+ end
956
+
957
+ def chunk_body(body) end
958
+
959
+ private :chunk_body
960
+
961
+ def track_end
962
+ @ws.puts('MTrk')
963
+ unless @cieot
964
+ delta(0)
965
+ endoftrack
966
+ end
967
+ ev = @ev.to_s
968
+ chunk_body(ev)
969
+ @ws.puti32(ev.length)
970
+ @ws.puts(ev)
971
+ end
972
+
973
+ def unknownchunk(ckid, body)
974
+ @ws.puts(ckid)
975
+ chunk_body(ev)
976
+ @ws.puti32(body.length)
977
+ @ws.puts(body)
978
+ end
979
+
980
+ def de
981
+ @ev.putl(@delta)
982
+ end
983
+
984
+ def sb(stat)
985
+ @ev.putc(stat) unless stat == @running
986
+ case stat
987
+ when 0x80..0xef; @running = stat
988
+ when 0xf0..0xf7; @running = 0
989
+ end
990
+ end
991
+
992
+ def db(data)
993
+ @ev.putc(data & 0x7f)
994
+ end
995
+
996
+ private :de, :sb, :db
997
+
998
+ def delta(delta) @delta = delta end
999
+
1000
+ def noteoff(ch, note, vel)
1001
+ de
1002
+ if @@replace_noteoff
1003
+ sb(ch | 0x90)
1004
+ db(note)
1005
+ db(0)
1006
+ else
1007
+ sb(ch | 0x80)
1008
+ db(note)
1009
+ db(vel)
1010
+ end
1011
+ end
1012
+
1013
+ def noteon(ch, note, vel)
1014
+ de
1015
+ sb(ch | 0x90)
1016
+ db(note)
1017
+ db(vel)
1018
+ end
1019
+
1020
+ def polyphonickeypressure(ch, note, val)
1021
+ de
1022
+ sb(ch | 0xa0)
1023
+ db(note)
1024
+ db(val)
1025
+ end
1026
+
1027
+ def controlchange(ch, num, val)
1028
+ de
1029
+ sb(ch | 0xb0)
1030
+ db(num)
1031
+ db(val)
1032
+ end
1033
+
1034
+ def programchange(ch, num)
1035
+ de
1036
+ sb(ch | 0xc0)
1037
+ db(num)
1038
+ end
1039
+
1040
+ def channelpressure(ch, val)
1041
+ de
1042
+ sb(ch | 0xd0)
1043
+ db(val)
1044
+ end
1045
+
1046
+ def pitchbendchange(ch, val)
1047
+ de
1048
+ sb(ch | 0xe0)
1049
+ val += 0x2000
1050
+ lsb = val & 0x7f
1051
+ msb = (val >> 7) & 0x7f
1052
+ db(lsb)
1053
+ db(msb)
1054
+ end
1055
+
1056
+ def channelmodemessage(ch, num, val)
1057
+ de
1058
+ sb(ch | 0xb0)
1059
+ db(num)
1060
+ db(val)
1061
+ end
1062
+
1063
+ private :channelmodemessage
1064
+
1065
+ def allsoundoff(ch) channelmodemessage(ch, 0x78, 0) end
1066
+ def resetallcontrollers(ch) channelmodemessage(ch, 0x79, 0) end
1067
+ def localcontrol(ch, val) channelmodemessage(ch, 0x7a, val) end
1068
+ def allnotesoff(ch) channelmodemessage(ch, 0x7b, 0) end
1069
+ def omnioff(ch) channelmodemessage(ch, 0x7c, 0) end
1070
+ def omnion(ch) channelmodemessage(ch, 0x7d, 0) end
1071
+ def monomode(ch, val) channelmodemessage(ch, 0x7e, val) end
1072
+ def polymode(ch) channelmodemessage(ch, 0x7f, 0) end
1073
+
1074
+ def exclusivef0(data)
1075
+ de
1076
+ @ev.putc(0xf0)
1077
+ @ev.putl(data.length)
1078
+ @ev.puts(data)
1079
+ end
1080
+
1081
+ def exclusivef7(data)
1082
+ de
1083
+ @ev.putc(0xf7)
1084
+ @ev.putl(data.length)
1085
+ @ev.puts(data)
1086
+ end
1087
+
1088
+ def sequencenumber(num)
1089
+ de
1090
+ @ev.putc(0xff)
1091
+ @ev.putc(0x0)
1092
+ @ev.putl(2)
1093
+ @ev.puti16(num)
1094
+ end
1095
+
1096
+ def text(type, text)
1097
+ de
1098
+ @ev.putc(0xff)
1099
+ @ev.putc(type)
1100
+ @ev.putl(text.length)
1101
+ @ev.puts(text)
1102
+ end
1103
+
1104
+ private :text
1105
+
1106
+ def generalpurposetext(text) text(0x1, text) end
1107
+ def copyrightnotice(text) text(0x2, text) end
1108
+ def trackname(text) text(0x3, text) end
1109
+ def instrumentname(text) text(0x4, text) end
1110
+ def lyric(text) text(0x5, text) end
1111
+ def marker(text) text(0x6, text) end
1112
+ def cuepoint(text) text(0x7, text) end
1113
+ def programname(text) text(0x8, text) end
1114
+ def devicename(text) text(0x9, text) end
1115
+ def text0a(text) text(0xa, text) end
1116
+ def text0b(text) text(0xb, text) end
1117
+ def text0c(text) text(0xc, text) end
1118
+ def text0d(text) text(0xd, text) end
1119
+ def text0e(text) text(0xe, text) end
1120
+ def text0f(text) text(0xf, text) end
1121
+
1122
+ def channelprefix(ch)
1123
+ de
1124
+ @ev.putc(0xff)
1125
+ @ev.putc(0x20)
1126
+ @ev.putl(1)
1127
+ @ev.putc(ch)
1128
+ end
1129
+
1130
+ def midiport(num)
1131
+ de
1132
+ @ev.putc(0xff)
1133
+ @ev.putc(0x21)
1134
+ @ev.putl(1)
1135
+ @ev.putc(num)
1136
+ end
1137
+
1138
+ def endoftrack
1139
+ de
1140
+ @ev.putc(0xff)
1141
+ @ev.putc(0x2f)
1142
+ @ev.putl(0)
1143
+ @cieot = true
1144
+ end
1145
+
1146
+ def settempo(tempo)
1147
+ de
1148
+ @ev.putc(0xff)
1149
+ @ev.putc(0x51)
1150
+ @ev.putl(3)
1151
+ @ev.puti24(tempo)
1152
+ end
1153
+
1154
+ def smpteoffset(hr, mn, se, fr, ff, tc)
1155
+ unless [24, 25, 29, 30].include? tc
1156
+ warn('smpteoffset/tc: invalid format')
1157
+ end
1158
+ de
1159
+ @ev.putc(0xff)
1160
+ @ev.putc(0x54)
1161
+ @ev.putl(5)
1162
+ hr |= ({24=>0, 25=>1, 29=>2, 30=>3}[tc] || 0) << 5
1163
+ @ev.putc(hr)
1164
+ @ev.putc(mn)
1165
+ @ev.putc(se)
1166
+ @ev.putc(fr)
1167
+ @ev.putc(ff)
1168
+ end
1169
+
1170
+ def timesignature(nn, dd, cc, bb)
1171
+ de
1172
+ @ev.putc(0xff)
1173
+ @ev.putc(0x58)
1174
+ @ev.putl(4)
1175
+ @ev.putc(nn)
1176
+ @ev.putc(dd)
1177
+ @ev.putc(cc)
1178
+ @ev.putc(bb)
1179
+ end
1180
+
1181
+ def keysignature(sf, mi)
1182
+ sf = WS::PO.s2u(sf, 8)
1183
+ de
1184
+ @ev.putc(0xff)
1185
+ @ev.putc(0x59)
1186
+ @ev.putl(2)
1187
+ @ev.putc(sf)
1188
+ @ev.putc(mi)
1189
+ end
1190
+
1191
+ def sequencerspecific(data)
1192
+ de
1193
+ @ev.putc(0xff)
1194
+ @ev.putc(0x7f)
1195
+ @ev.putl(data.length)
1196
+ @ev.puts(data)
1197
+ end
1198
+
1199
+ def unknownmeta(type, data)
1200
+ de
1201
+ @ev.putc(0xff)
1202
+ @ev.putc(type)
1203
+ @ev.putl(data.length)
1204
+ @ev.puts(data)
1205
+ end
1206
+
1207
+ def result() @ws.to_s end
1208
+
1209
+ def error(mesg) raise ReadError, mesg end
1210
+
1211
+ end
1212
+
1213
+ class << self
1214
+
1215
+ unless String === '0'[0]
1216
+
1217
+ def decode(s)
1218
+ self::RS.new(s, self::Decode.new).read
1219
+ end
1220
+
1221
+ else
1222
+
1223
+ def decode(s)
1224
+ s = s.dup.force_encoding('ascii-8bit')
1225
+ self::RS.new(s, self::Decode.new).read
1226
+ end
1227
+
1228
+ end
1229
+
1230
+ def read(io)
1231
+ decode(io.binmode.read)
1232
+ end
1233
+
1234
+ def decoceio(io)
1235
+ warn('decodeio is deprecated; use read') if $VERBOSE
1236
+ read(io)
1237
+ end
1238
+
1239
+ def load(fn)
1240
+ open(fn) do |io|
1241
+ read(io)
1242
+ end
1243
+ end
1244
+
1245
+ def decodefile(fn)
1246
+ warn('decodefile is deprecated; use load') if $VERBOSE
1247
+ load(fn)
1248
+ end
1249
+
1250
+ end
1251
+
1252
+ def encode
1253
+ self.class::WS.new(self, self.class::Encode.new).read
1254
+ end
1255
+
1256
+ def write(io)
1257
+ io.binmode.write(encode)
1258
+ end
1259
+
1260
+ def encodeio(io)
1261
+ warn('encodeio is deprecated; use write') if $VERBOSE
1262
+ write(io)
1263
+ end
1264
+
1265
+ def save(fn)
1266
+ open(fn, 'w') do |io|
1267
+ write(io)
1268
+ end
1269
+ end
1270
+
1271
+ def encodefile(fn)
1272
+ warn('encodefile is deprecated; use save') if $VERBOSE
1273
+ save(fn)
1274
+ end
1275
+
1276
+ end
1277
+
1278
+ end