smf 0.15.12

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.
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
data/README ADDED
@@ -0,0 +1,33 @@
1
+ SMF �⥸�塼��
2
+ ==============
3
+
4
+ SMF �ϥ��֥������Ȼظ�������ץȸ��� Ruby �Τ���Ρ��֥����������MIDI��
5
+ ������ץ⥸�塼��Ǥ���
6
+
7
+
8
+ ���󥹥ȡ���
9
+ ------------
10
+
11
+ ������ץ� "install.rb" ��Ĥ����ޤ���
12
+
13
+ $ ruby install.rb config
14
+ $ ruby install.rb setup
15
+ ($ su)
16
+ # ruby install.rb install
17
+
18
+ ���路���ϡ�"ruby install.rb --help" �Ȥ��Ƥ���������
19
+
20
+
21
+ ����ʸ��
22
+ --------
23
+
24
+ MIDI ���ʶ��IJ��MIDI 1.0 ���ʡץ�åȡ��ߥ塼���å� 1989
25
+
26
+ �����Żһ��ȶ����MIDI 1.0 ���ʽ�ץ�åȡ��ߥ塼���å� 1998
27
+
28
+ JIS X 6054-1,2:1999 �Żҳڴ�ǥ������륤�󥿡��ե����� (MIDI)
29
+
30
+
31
+ ������� (�դʤФ����褷)
32
+ mailto:tadf@funaba.org
33
+ http://www.funaba.org/
@@ -0,0 +1,33 @@
1
+ An "SMF" module
2
+ ==============
3
+
4
+ SMF is a "Standard MIDI File" module for an object‐oriented
5
+ scripting language Ruby.
6
+
7
+
8
+ Install
9
+ ‐‐‐‐‐‐‐
10
+
11
+ Use the script "install.rb".
12
+
13
+ $ ruby install.rb config
14
+ $ ruby install.rb setup
15
+ ($ su)
16
+ # ruby install.rb install
17
+
18
+ For more information, type "ruby install.rb ‐‐help".
19
+
20
+
21
+ References
22
+ ‐‐‐‐‐‐‐‐‐‐
23
+
24
+ MIDI kikaku kyogi‐kai, MIDI 1.0 kikaku, rittor music 1989
25
+
26
+ ongaku denshi jigyo kyokai, MIDI 1.0 kikaku‐sho, rittor music 1998
27
+
28
+ JIS X 6054‐1,2:1999 Musical Instrument Digital Interface (MIDI)
29
+
30
+
31
+ Tadayoshi Funaba
32
+ mailto:tadf@funaba.org
33
+ http://www.funaba.org/en/
@@ -0,0 +1,736 @@
1
+ # smf.rb: Written by Tadayoshi Funaba 1998-2006,2008
2
+ # $Id: smf.rb,v 1.39 2008-07-06 00:00:43+09 tadf Exp $
3
+
4
+ require 'smf/io'
5
+ require 'forwardable'
6
+
7
+ module SMF
8
+
9
+ class Sequence
10
+
11
+ def initialize(format=1, division=96, tc=nil)
12
+ # format:0/2
13
+ # division:1/2**15-1(if tc=nil):1/2**8-1(otherwise)
14
+ # tc:nil,24,25,29,30
15
+ @format, @division, @tc, @arr = format, division, tc, []
16
+ end
17
+
18
+ attr_accessor :format, :division, :tc
19
+
20
+ def smpte()
21
+ warn('smpte is deprecated; use tc') if $VERBOSE
22
+ self.tc
23
+ end
24
+
25
+ def smpte=(v)
26
+ warn('smpte= is deprecated; use tc=') if $VERBOSE
27
+ self.tc = v
28
+ end
29
+
30
+ if [].respond_to?(:count)
31
+
32
+ def ntrks() @arr.count{|x| x} end
33
+
34
+ else
35
+
36
+ def ntrks() @arr.nitems end
37
+
38
+ end
39
+
40
+ def hash() @format.hash ^ @division.hash ^ @arr.hash end
41
+ def eql? (other) self == other end
42
+
43
+ def == (other)
44
+ self.class == other.class &&
45
+ format == other.format &&
46
+ division == other.division &&
47
+ tc == other.tc &&
48
+ to_a == other.to_a
49
+ end
50
+
51
+ def calc_set(a, b)
52
+ sq = self.class.new(format, division, tc)
53
+ a, b = a.to_a, b.to_a
54
+ n = yield(a, b)
55
+ sq.replace(n)
56
+ sq
57
+ end
58
+
59
+ private :calc_set
60
+
61
+ def + (other) calc_set(self, other){|a, b| a + b} end
62
+ def - (other) calc_set(self, other){|a, b| a - b} end
63
+ def & (other) calc_set(self, other){|a, b| a & b} end
64
+ def | (other) calc_set(self, other){|a, b| a | b} end
65
+
66
+ def * (times)
67
+ sq = self.class.new(format, division, tc)
68
+ sq.replace(self.to_a * times)
69
+ sq
70
+ end
71
+
72
+ def << (tr)
73
+ @arr << tr
74
+ self
75
+ end
76
+
77
+ def >> (tr)
78
+ @arr.reject!{|x| x.object_id == tr.object_id}
79
+ self
80
+ end
81
+
82
+ def concat(other) replace(self + other) end
83
+
84
+ def each
85
+ @arr.compact.each do |tr|
86
+ yield tr
87
+ end
88
+ self
89
+ end
90
+
91
+ def join
92
+ sq = self.class.new(format, division, tc)
93
+ tr = Track.new
94
+ sq << @arr.inject(tr){|t, x| t + x}
95
+ sq
96
+ end
97
+
98
+ def join!
99
+ @arr.replace(join)
100
+ self
101
+ end
102
+
103
+ def replace(another)
104
+ if Sequence === another
105
+ @format = another.format
106
+ @division = another.division
107
+ @tc = another.tc
108
+ end
109
+ @arr.replace(another.to_a)
110
+ self
111
+ end
112
+
113
+ extend Forwardable
114
+ include Enumerable
115
+
116
+ de = (Array.instance_methods - self.instance_methods)
117
+ de -= %w(assoc flatten flatten! pack rassoc transpose)
118
+ de += %w(include? sort to_a)
119
+
120
+ def_delegators(:@arr, *de)
121
+
122
+ undef_method :zip
123
+
124
+ end
125
+
126
+ class Track
127
+
128
+ def initialize() @arr = [] end
129
+
130
+ if [].respond_to?(:count)
131
+
132
+ def nevts() @arr.count{|x| x} end
133
+
134
+ else
135
+
136
+ def nevts() @arr.nitems end
137
+
138
+ end
139
+
140
+ def hash() @arr.hash end
141
+ def eql? (other) self == other end
142
+
143
+ def == (other)
144
+ self.class == other.class &&
145
+ to_a == other.to_a
146
+ end
147
+
148
+ def calc_set_sub(a, b, e)
149
+ tr = self.class.new
150
+ n = yield(a, b).reject{|x| EndOfTrack === x}
151
+ eot = e.select{|x| EndOfTrack === x}
152
+ n << eot.max unless eot.empty?
153
+ tr.replace(n)
154
+ tr
155
+ end
156
+
157
+ def calc_set_maxsize(a, b, &block)
158
+ a, b = a.to_a, b.to_a
159
+ calc_set_sub(a, b, a + b, &block)
160
+ end
161
+
162
+ def calc_set_selfsize(a, b, &block)
163
+ a, b = a.to_a, b.to_a
164
+ calc_set_sub(a, b, a, &block)
165
+ end
166
+
167
+ private :calc_set_sub, :calc_set_maxsize, :calc_set_selfsize
168
+
169
+ def + (other) calc_set_maxsize(self, other){|a, b| a + b} end
170
+ def - (other) calc_set_selfsize(self, other){|a, b| a - b} end
171
+ def & (other) calc_set_selfsize(self, other){|a, b| a & b} end
172
+ def | (other) calc_set_maxsize(self, other){|a, b| a | b} end
173
+
174
+ def * (times)
175
+ tr = self.class.new
176
+ size = self[-1].offset
177
+ eot, orig = partition{|x| EndOfTrack === x}
178
+ times.times do |i|
179
+ tr += orig.collect{|ev| ev = ev.dup; ev.offset += size * i; ev}
180
+ end
181
+ unless eot.empty?
182
+ x = eot.max
183
+ x.offset += size * times
184
+ tr << x
185
+ end
186
+ tr
187
+ end
188
+
189
+ def << (ev)
190
+ @arr << ev
191
+ self
192
+ end
193
+
194
+ def >> (ev)
195
+ @arr.reject!{|x| x.object_id == ev.object_id}
196
+ self
197
+ end
198
+
199
+ def concat!(other) replace(self + other) end
200
+
201
+ def each
202
+ i = 0
203
+ @arr.compact.sort_by{|x| [x, i += 1]}.
204
+ each do |ev|
205
+ yield ev
206
+ end
207
+ self
208
+ end
209
+
210
+ def _merge(a, b, &block)
211
+ c = []
212
+ until a.empty? || b.empty?
213
+ c << if yield(a[0], b[0]) <= 0 then a.shift else b.shift end
214
+ end
215
+ c + a + b
216
+ end
217
+
218
+ def _sort(xs, &block)
219
+ mid = (xs.size / 2).truncate
220
+ if mid < 1
221
+ xs
222
+ else
223
+ _merge(_sort(xs[0...mid], &block), _sort(xs[mid..-1], &block), &block)
224
+ end
225
+ end
226
+
227
+ def _sort_by(xs)
228
+ _sort(xs.collect{|x| [x, yield(x)]}){|a, b| a[1] <=> b[1]}.
229
+ collect!{|x| x[0]}
230
+ end
231
+
232
+ private :_merge, :_sort, :_sort_by
233
+
234
+ def sort(&block)
235
+ block ||= proc{|a, b| a <=> b}
236
+ _sort(@arr, &block)
237
+ end
238
+
239
+ def sort!(&block)
240
+ replace(sort(&block))
241
+ self
242
+ end
243
+
244
+ def sort_by(&block)
245
+ _sort_by(@arr, &block)
246
+ end
247
+
248
+ def replace(another)
249
+ @arr.replace(another.to_a)
250
+ self
251
+ end
252
+
253
+ extend Forwardable
254
+ include Enumerable
255
+
256
+ de = (Array.instance_methods - self.instance_methods)
257
+ de -= %w(assoc flatten flatten! pack rassoc transpose)
258
+ de += %w(include? to_a)
259
+
260
+ def_delegators(:@arr, *de)
261
+
262
+ undef_method :zip
263
+
264
+ end
265
+
266
+ class Event
267
+
268
+ include Comparable
269
+
270
+ def initialize(offset)
271
+ # offset:0/oo
272
+ @offset = offset
273
+ end
274
+
275
+ attr_accessor :offset
276
+
277
+ def <=>(other) self.offset <=> other.offset end
278
+
279
+ def hash() @offset.hash end
280
+ def eql? (other) self == other end
281
+
282
+ def == (other)
283
+ self.class == other.class &&
284
+ offset == other.offset
285
+ end
286
+
287
+ end
288
+
289
+ class MIDIMessage < Event; end
290
+
291
+ class ChannelMessage < MIDIMessage
292
+
293
+ def initialize(offset, ch)
294
+ # ch:0/2**4-1
295
+ super(offset)
296
+ @ch = ch
297
+ end
298
+
299
+ attr_accessor :ch
300
+
301
+ alias_method :channel, :ch
302
+ alias_method :channel=, :ch=
303
+
304
+ def == (other)
305
+ super && ch == other.ch
306
+ end
307
+
308
+ end
309
+
310
+ class VoiceMessage < ChannelMessage; end
311
+
312
+ class NoteOff < VoiceMessage
313
+
314
+ def initialize(offset, ch, note, vel)
315
+ # note:0/2**7-1, vel:0/2**7-1
316
+ super(offset, ch)
317
+ @note, @vel = note, vel
318
+ end
319
+
320
+ attr_accessor :note
321
+
322
+ def vel() @vel || 64 end
323
+ def vel=(vel) @vel = vel end
324
+ def fake?() @vel.nil? end
325
+
326
+ alias_method :velocity, :vel
327
+ alias_method :velocity=, :vel=
328
+
329
+ def == (other)
330
+ super && note == other.note && vel == other.vel
331
+ end
332
+
333
+ end
334
+
335
+ class NoteOn < VoiceMessage
336
+
337
+ def initialize(offset, ch, note, vel)
338
+ # note:0/2**7-1, vel:0/2**7-1
339
+ super(offset, ch)
340
+ @note, @vel = note, vel
341
+ end
342
+
343
+ attr_accessor :note, :vel
344
+
345
+ alias_method :velocity, :vel
346
+ alias_method :velocity=, :vel=
347
+
348
+ def == (other)
349
+ super && note == other.note && vel == other.vel
350
+ end
351
+
352
+ end
353
+
354
+ class PolyphonicKeyPressure < VoiceMessage
355
+
356
+ def initialize(offset, ch, note, val)
357
+ # note:0/2**7-1, val:0/2**7-1
358
+ super(offset, ch)
359
+ @note, @val = note, val
360
+ end
361
+
362
+ attr_accessor :note, :val
363
+
364
+ alias_method :value, :val
365
+ alias_method :value=, :val=
366
+
367
+ def == (other)
368
+ super && note == other.note && val == other.val
369
+ end
370
+
371
+ end
372
+
373
+ class ControlChange < VoiceMessage
374
+
375
+ def initialize(offset, ch, num, val)
376
+ # num:0/119, val:0/2**7-1
377
+ super(offset, ch)
378
+ @num, @val = num, val
379
+ end
380
+
381
+ attr_accessor :num, :val
382
+
383
+ alias_method :number, :num
384
+ alias_method :number=, :num=
385
+
386
+ alias_method :value, :val
387
+ alias_method :value=, :val=
388
+
389
+ def == (other)
390
+ super && num == other.num && val == other.val
391
+ end
392
+
393
+ end
394
+
395
+ class ProgramChange < VoiceMessage
396
+
397
+ def initialize(offset, ch, num)
398
+ # num:0/2**7-1
399
+ super(offset, ch)
400
+ @num = num
401
+ end
402
+
403
+ attr_accessor :num
404
+
405
+ alias_method :number, :num
406
+ alias_method :number=, :num=
407
+
408
+ def == (other)
409
+ super && num == other.num
410
+ end
411
+
412
+ end
413
+
414
+ class ChannelPressure < VoiceMessage
415
+
416
+ def initialize(offset, ch, val)
417
+ # val:0/2**7-1
418
+ super(offset, ch)
419
+ @val = val
420
+ end
421
+
422
+ attr_accessor :val
423
+
424
+ alias_method :value, :val
425
+ alias_method :value=, :val=
426
+
427
+ def == (other)
428
+ super && val == other.val
429
+ end
430
+
431
+ end
432
+
433
+ class PitchBendChange < VoiceMessage
434
+
435
+ def initialize(offset, ch, val)
436
+ # val:-2**13/2**13-1
437
+ super(offset, ch)
438
+ @val = val
439
+ end
440
+
441
+ attr_accessor :val
442
+
443
+ alias_method :value, :val
444
+ alias_method :value=, :val=
445
+
446
+ def == (other)
447
+ super && val == other.val
448
+ end
449
+
450
+ end
451
+
452
+ class ChannelModeMessage < ChannelMessage; end
453
+
454
+ [ 'AllSoundOff',
455
+ 'ResetAllControllers',
456
+ 'AllNotesOff',
457
+ 'OmniOff',
458
+ 'OmniOn',
459
+ 'PolyMode',
460
+ ].each do |name|
461
+ module_eval <<-"end;"
462
+ class #{name} < ChannelModeMessage
463
+
464
+ def initialize(offset, ch)
465
+ super(offset, ch)
466
+ end
467
+
468
+ end
469
+ end;
470
+ end
471
+
472
+ [ 'LocalControl', # val:0/127
473
+ 'MonoMode', # val:0/16
474
+ ].each do |name|
475
+ module_eval <<-"end;"
476
+ class #{name} < ChannelModeMessage
477
+
478
+ def initialize(offset, ch, val)
479
+ super(offset, ch)
480
+ @val = val
481
+ end
482
+
483
+ attr_accessor :val
484
+
485
+ alias_method :value, :val
486
+ alias_method :value=, :val=
487
+
488
+ def == (other)
489
+ super && val == other.val
490
+ end
491
+
492
+ end
493
+ end;
494
+ end
495
+
496
+ class SystemMessage < Event; end
497
+ class ExclusiveMessage < SystemMessage; end
498
+
499
+ class ExclusiveF0 < ExclusiveMessage
500
+
501
+ def initialize(offset, data)
502
+ # data.length:0/2**28-1
503
+ super(offset)
504
+ @data = data
505
+ end
506
+
507
+ attr_accessor :data
508
+
509
+ def == (other)
510
+ super && data == other.data
511
+ end
512
+
513
+ end
514
+
515
+ class ExclusiveF7 < ExclusiveMessage
516
+
517
+ def initialize(offset, data)
518
+ # data.length:0/2**28-1
519
+ super(offset)
520
+ @data = data
521
+ end
522
+
523
+ attr_accessor :data
524
+
525
+ def == (other)
526
+ super && data == other.data
527
+ end
528
+
529
+ end
530
+
531
+ class Meta < Event
532
+
533
+ def initialize(offset)
534
+ super(offset)
535
+ end
536
+
537
+ end
538
+
539
+ class SequenceNumber < Meta
540
+
541
+ def initialize(offset, num)
542
+ # num:0/2**16-1
543
+ super(offset)
544
+ @num = num
545
+ end
546
+
547
+ attr_accessor :num
548
+
549
+ alias_method :number, :num
550
+ alias_method :number=, :num=
551
+
552
+ def == (other)
553
+ super && num == other.num
554
+ end
555
+
556
+ end
557
+
558
+ class Text < Meta
559
+
560
+ def initialize(offset, text)
561
+ # text.length:0/2**28-1
562
+ super(offset)
563
+ @text = text
564
+ end
565
+
566
+ attr_accessor :text
567
+
568
+ def == (other)
569
+ super && text == other.text
570
+ end
571
+
572
+ end
573
+
574
+ %w(GeneralPurposeText CopyrightNotice TrackName
575
+ InstrumentName Lyric Marker CuePoint ProgramName
576
+ DeviceName Text0A Text0B Text0C Text0D Text0E Text0F).
577
+ each do |name|
578
+ module_eval <<-"end;"
579
+ class #{name} < Text
580
+
581
+ def initialize(offset, text)
582
+ super(offset, text)
583
+ end
584
+
585
+ end
586
+ end;
587
+ end
588
+
589
+ Text01 = GeneralPurposeText
590
+ Text02 = CopyrightNotice
591
+ SequenceName = TrackName
592
+ Text03 = TrackName
593
+ Text04 = InstrumentName
594
+ Display = Lyric
595
+ Text05 = Lyric
596
+ Text06 = Marker
597
+ Text07 = CuePoint
598
+ Text08 = ProgramName
599
+ Text09 = DeviceName
600
+
601
+ class ChannelPrefix < Meta
602
+
603
+ def initialize(offset, ch)
604
+ # ch:0/2**4-1
605
+ super(offset)
606
+ @ch = ch
607
+ end
608
+
609
+ attr_accessor :ch
610
+
611
+ alias_method :channel, :ch
612
+ alias_method :channel=, :ch=
613
+
614
+ def == (other)
615
+ super && ch == other.ch
616
+ end
617
+
618
+ end
619
+
620
+ class MIDIPort < Meta
621
+
622
+ def initialize(offset, num)
623
+ # num:0/2**8-1
624
+ super(offset)
625
+ @num = num
626
+ end
627
+
628
+ attr_accessor :num
629
+
630
+ alias_method :number, :num
631
+ alias_method :number=, :num=
632
+
633
+ def == (other)
634
+ super && num == other.num
635
+ end
636
+
637
+ end
638
+
639
+ class EndOfTrack < Meta
640
+
641
+ def initialize(offset)
642
+ super(offset)
643
+ end
644
+
645
+ end
646
+
647
+ class SetTempo < Meta
648
+
649
+ def initialize(offset, tempo)
650
+ # tempo:1/2**24-1
651
+ super(offset)
652
+ @tempo = tempo
653
+ end
654
+
655
+ attr_accessor :tempo
656
+
657
+ def == (other)
658
+ super && tempo == other.tempo
659
+ end
660
+
661
+ end
662
+
663
+ class SMPTEOffset < Meta
664
+
665
+ def initialize(offset, hr, mn, se, fr, ff, tc)
666
+ # hr:0/23, mn:0/59, se:0/59, fr:0/29, ff:0/99, tc:24|25|29|30
667
+ super(offset)
668
+ @hr, @mn, @se, @fr, @ff, @tc = hr, mn, se, fr, ff, tc
669
+ end
670
+
671
+ attr_accessor :hr, :mn, :se, :fr, :ff, :tc
672
+
673
+ def == (other)
674
+ super &&
675
+ hr == other.hr &&
676
+ mn == other.mn &&
677
+ se == other.se &&
678
+ fr == other.fr &&
679
+ ff == other.ff &&
680
+ tc == other.tc
681
+ end
682
+
683
+ end
684
+
685
+ class TimeSignature < Meta
686
+
687
+ def initialize(offset, nn, dd, cc, bb)
688
+ # nn,cc,bb:1/2**8-1, dd:0/2**8-1
689
+ super(offset)
690
+ @nn, @dd, @cc, @bb = nn, dd, cc, bb
691
+ end
692
+
693
+ attr_accessor :nn, :dd, :cc, :bb
694
+
695
+ def == (other)
696
+ super &&
697
+ nn == other.nn &&
698
+ dd == other.dd &&
699
+ cc == other.cc &&
700
+ bb == other.bb
701
+ end
702
+
703
+ end
704
+
705
+ class KeySignature < Meta
706
+
707
+ def initialize(offset, sf, mi)
708
+ # sf:-2**7/2**7-1, mi:0/1
709
+ super(offset)
710
+ @sf, @mi = sf, mi
711
+ end
712
+
713
+ attr_accessor :sf, :mi
714
+
715
+ def == (other)
716
+ super && sf == other.sf && mi == other.mi
717
+ end
718
+ end
719
+
720
+ class SequencerSpecific < Meta
721
+
722
+ def initialize(offset, data)
723
+ # data.length:0/2**28-1
724
+ super(offset)
725
+ @data = data
726
+ end
727
+
728
+ attr_accessor :data
729
+
730
+ def == (other)
731
+ super && data == other.data
732
+ end
733
+
734
+ end
735
+
736
+ end