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,73 @@
1
+ # beatmap.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: beatmap.rb,v 1.3 2006-11-10 21:58:21+09 tadf Exp $
3
+
4
+ require 'smf/toy/searchsegment'
5
+ require 'rational'
6
+
7
+ module SMF
8
+
9
+ class BeatMap
10
+
11
+ include SearchSegment
12
+
13
+ def o2b(div, offset, sig)
14
+ bl = (div * 4).to_r / sig[1]
15
+ bar, mod = offset.divmod(bl * sig[0])
16
+ beat, tick = mod.divmod(bl)
17
+ [bar, beat, tick]
18
+ end
19
+
20
+ def b2o(div, bar, sig)
21
+ bl = (div * 4).to_r / sig[1]
22
+ bar[0] * (bl * sig[0]) + bar[1] * bl + bar[2]
23
+ end
24
+
25
+ private :o2b, :b2o
26
+
27
+ def initialize(sq)
28
+ @div = sq.division
29
+ @map = [[0, [4, 4], 1]] # [[offset, [n, d], bar]]
30
+ sq.each do |tr|
31
+ tr.each do |ev|
32
+ case ev
33
+ when TimeSignature
34
+ offset = (ev.offset + @div / 2) / @div * @div
35
+ @map << [offset, [ev.nn, 1 << ev.dd], 0]
36
+ end
37
+ end
38
+ end
39
+ i = 0
40
+ @map = @map.sort_by{|x| [x[0], i += 1]}
41
+ lx = nil
42
+ @map.each do |x|
43
+ if lx
44
+ bar, beat, tick = o2b(@div, x[0] - lx[0], lx[1])
45
+ if bar == 0 && beat == 0 && tick == 0
46
+ x[2] = lx[2]
47
+ else
48
+ x[2] = lx[2] + bar
49
+ end
50
+ end
51
+ lx = x
52
+ end
53
+ end
54
+
55
+ def offset2beat(offset)
56
+ i = search_segment(@map){|x| x[0] <=> offset}
57
+ lx = @map[i]
58
+ bar, beat, tick = o2b(@div, offset - lx[0], lx[1])
59
+ bar += lx[2]
60
+ [bar, beat + 1, tick.round]
61
+ end
62
+
63
+ def beat2offset(bar)
64
+ i = search_segment(@map){|x| x[2] <=> bar[0]}
65
+ lx = @map[i]
66
+ bar2 = [bar[0] - lx[2], bar[1] - 1, bar[2]]
67
+ offset = lx[0] + b2o(@div, bar2, lx[1])
68
+ offset.round
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,327 @@
1
+ # gm.rb: Written by Tadayoshi Funaba 2005
2
+ # $Id: gm.rb,v 1.2 2005-07-17 17:07:37+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ [ ['BankSelectMSB', 0],
7
+ ['ModulationDepthMSB', 1],
8
+ ['PortamentoTimeMSB', 5],
9
+ ['DataEntryMSB', 6],
10
+ ['ChannelVolumeMSB', 7],
11
+ ['PanMSB', 10],
12
+ ['ExpressioMSB', 11],
13
+ ['BankSelectLSB', 32 + 0],
14
+ ['ModulationDepthLSB', 32 + 1],
15
+ ['PortamentoTimeLSB', 32 + 5],
16
+ ['DataEntryLSB', 32 + 6],
17
+ ['ChannelVolumeLSB', 32 + 7],
18
+ ['PanLSB', 32 + 10],
19
+ ['ExpressioLSB', 32 + 11],
20
+ ['Hold1', 64],
21
+ ['PortamentoOnOff', 65],
22
+ ['Sostenuto', 66],
23
+ ['Soft', 67],
24
+ ['FilterResonance', 71],
25
+ ['ReleaseTime', 72],
26
+ ['AttackTime', 73],
27
+ ['Brightness', 74],
28
+ ['DecayTime', 75],
29
+ ['VibratoRate', 76],
30
+ ['VibratoDepth', 77],
31
+ ['VibratoDelay', 78],
32
+ ['ReverbSendLevel', 91],
33
+ ['ChorusSendLevel', 93],
34
+ ['RPNLSB', 100],
35
+ ['RPNMSB', 101]
36
+ ].each do |name, num|
37
+ module_eval <<-"end;"
38
+ class #{name} < ControlChange
39
+
40
+ def initialize(offset, ch, val)
41
+ # val:0/2**7-1
42
+ super(offset, ch, #{num}, val)
43
+ end
44
+
45
+ end
46
+ end;
47
+ end
48
+
49
+ [ ['PitchBendSensitivity', 0, 0],
50
+ ['ChannelFineTune', 1, 0],
51
+ ['ChannelCoarseTune', 2, 0],
52
+ ['ModulationDepthRange', 5, 0],
53
+ ['RPNNULL', 0x7f, 0x7f]
54
+ ].each do |name, lsb, msb|
55
+ module_eval <<-"end;"
56
+ class #{name}LSB < RPNLSB
57
+
58
+ def initialize(offset, ch)
59
+ super(offset, ch, #{lsb})
60
+ end
61
+
62
+ end
63
+
64
+ class #{name}MSB < RPNMSB
65
+
66
+ def initialize(offset, ch)
67
+ super(offset, ch, #{msb})
68
+ end
69
+
70
+ end
71
+ end;
72
+ end
73
+
74
+ class MasterVolume < ExclusiveF0
75
+
76
+ def initialize(offset, vol, dev=0x7f)
77
+ # vol:0/2**14-1
78
+ vl = vol & 0x7f
79
+ vm = (vol >> 7) & 0x7f
80
+ super(offset, [0x7f, dev, 0x04, 0x01, vl, vm, 0xf7].pack('C*'))
81
+ end
82
+
83
+ end
84
+
85
+ class MasterFineTuning < ExclusiveF0
86
+
87
+ def initialize(offset, val, dev=0x7f)
88
+ # val:-2**13/2**13-1
89
+ val += 0x2000
90
+ fl = val & 0x7f
91
+ fm = (val >> 7) & 0x7f
92
+ super(offset, [0x7f, dev, 0x04, 0x03, fl, fm, 0xf7].pack('C*'))
93
+ end
94
+
95
+ end
96
+
97
+ class MasterCoarseTuning < ExclusiveF0
98
+
99
+ def initialize(offset, cc, dev=0x7f)
100
+ # cc:0/2**7-1
101
+ super(offset, [0x7f, dev, 0x04, 0x04, 0, cc, 0xf7].pack('C*'))
102
+ end
103
+
104
+ end
105
+
106
+ class ReverbParameter < ExclusiveF0
107
+
108
+ def initialize(offset, pp, vv, dev=0x7f)
109
+ # pp:0/1, vv:0/8
110
+ super(offset, [0x7f, dev, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
111
+ pp, vv, 0xf7].pack('C*'))
112
+ end
113
+
114
+ end
115
+
116
+ class ReverbType < ReverbParameter
117
+
118
+ def initialize(offset, vv, dev=0x7f)
119
+ # vv:0/8
120
+ super(offset, 0, vv, dev)
121
+ end
122
+
123
+ end
124
+
125
+ class ReverbTime < ReverbParameter
126
+
127
+ def initialize(offset, vv, dev=0x7f)
128
+ # vv:0/8
129
+ super(offset, 1, vv, dev)
130
+ end
131
+
132
+ end
133
+
134
+ class ChorusParameter < ExclusiveF0
135
+
136
+ def initialize(offset, pp, vv, dev=0x7f)
137
+ # pp:0/4, vv:0/2**7-1
138
+ super(offset, [0x7f, dev, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x02,
139
+ pp, vv, 0xf7].pack('C*'))
140
+ end
141
+
142
+ end
143
+
144
+ class ChorusType < ChorusParameter
145
+
146
+ def initialize(offset, vv, dev=0x7f)
147
+ # vv:0/5
148
+ super(offset, 0, vv, dev)
149
+ end
150
+
151
+ end
152
+
153
+ class ChorusModRate < ChorusParameter
154
+
155
+ def initialize(offset, vv, dev=0x7f)
156
+ super(offset, 1, vv, dev)
157
+ end
158
+
159
+ end
160
+
161
+ class ChorusModDepth < ChorusParameter
162
+
163
+ def initialize(offset, vv, dev=0x7f)
164
+ # vv:0/2**7-1
165
+ super(offset, 2, vv, dev)
166
+ end
167
+
168
+ end
169
+
170
+ class ChorusFeedback < ChorusParameter
171
+
172
+ def initialize(offset, vv, dev=0x7f)
173
+ # vv:0/2**7-1
174
+ super(offset, 3, vv, dev)
175
+ end
176
+
177
+ end
178
+
179
+ class ChorusSendToReverb < ChorusParameter
180
+
181
+ def initialize(offset, vv, dev=0x7f)
182
+ # vv:0/2**7-1
183
+ super(offset, 4, vv, dev)
184
+ end
185
+
186
+ end
187
+
188
+ class ControllerDestinationSetting < ExclusiveF0
189
+
190
+ def initialize(offset, id2, ch, pp_rr, dev=0x7f)
191
+ # id2:1|3, ch:0/15, pp:0/5, rr:0/2**7-1
192
+ super(offset, [0x7f, dev, 0x09, id2, ch, pp_rr, 0xf7].
193
+ flatten.pack('C*'))
194
+ end
195
+
196
+ end
197
+
198
+ class CDSChannelPressure < ControllerDestinationSetting
199
+
200
+ def initialize(offset, ch, pp_rr, dev=0x7f)
201
+ # pp:0/5, rr:0/2**7-1
202
+ super(0x01, ch, pp_rr, dev)
203
+ end
204
+
205
+ end
206
+
207
+ class CDSControlChange < ControllerDestinationSetting
208
+
209
+ def initialize(offset, ch, pp_rr, dev=0x7f)
210
+ # pp:0/5, rr:0/2**7-1
211
+ super(0x03, ch, pp_rr, dev)
212
+ end
213
+
214
+ end
215
+
216
+ class ScaleTuningAdjust1ByteFormRealTime < ExclusiveF0
217
+
218
+ def initialize(offset, ch, ss, dev=0x7f)
219
+ # ch:0/2**16-1, ss:-2**6/2**6-1
220
+ ff = ch & 0x3
221
+ gg = (ch >> 2) & 0x7f
222
+ hh = (ch >> 9) & 0x7f
223
+ ss.collect! do |x|
224
+ x + 0x40
225
+ end
226
+ super(offset, [0x7f, dev, 0x08, 0x08, ff, gg, hh, ss, 0xf7].
227
+ flatten.pack('C*'))
228
+ end
229
+
230
+ end
231
+
232
+ class ScaleTuningAdjust1ByteFormNonRealTime < ExclusiveF0
233
+
234
+ def initialize(offset, ch, ss, dev=0x7f)
235
+ # ch:0/2**16-1, ss:-2**6/2**6-1
236
+ ff = ch & 0x3
237
+ gg = (ch >> 2) & 0x7f
238
+ hh = (ch >> 9) & 0x7f
239
+ ss.collect! do |x|
240
+ x + 0x40
241
+ end
242
+ super(offset, [0x7e, dev, 0x08, 0x08, ff, gg, hh, ss, 0xf7].
243
+ flatten.pack('C*'))
244
+ end
245
+
246
+ end
247
+
248
+ class ScaleTuningAdjust2ByteFormRealTime < ExclusiveF0
249
+
250
+ def initialize(offset, ch, ss_tt, dev=0x7f)
251
+ # ch:0/2**16-1, ss_tt:-2**13/2**13-1
252
+ ff = ch & 0x3
253
+ gg = (ch >> 2) & 0x7f
254
+ hh = (ch >> 9) & 0x7f
255
+ ss_tt.collect! do |x|
256
+ x += 0x2000
257
+ ss = x & 0x7f
258
+ tt = (x >> 7) & 0x7f
259
+ [ss, tt]
260
+ end
261
+ super(offset, [0x7f, dev, 0x08, 0x09, ff, gg, hh, ss_tt, 0xf7].
262
+ flatten.pack('C*'))
263
+ end
264
+
265
+ end
266
+
267
+ class ScaleTuningAdjust2ByteFormNonRealTime < ExclusiveF0
268
+
269
+ def initialize(offset, ch, ss_tt, dev=0x7f)
270
+ # ch:0/2**16-1, ss_tt:-2**13/2**13-1
271
+ ff = ch & 0x3
272
+ gg = (ch >> 2) & 0x7f
273
+ hh = (ch >> 9) & 0x7f
274
+ ss_tt.collect! do |x|
275
+ x += 0x2000
276
+ ss = x & 0x7f
277
+ tt = (x >> 7) & 0x7f
278
+ [ss, tt]
279
+ end
280
+ super(offset, [0x7e, dev, 0x08, 0x09, ff, gg, hh, ss_tt, 0xf7].
281
+ flatten.pack('C*'))
282
+ end
283
+
284
+ end
285
+
286
+ OctaveTuningAdjust1ByteFormRealTime = ScaleTuningAdjust1ByteFormRealTime
287
+ OctaveTuningAdjust1ByteFormNonRealTime = ScaleTuningAdjust1ByteFormNonRealTime
288
+ OctaveTuningAdjust2ByteFormRealTime = ScaleTuningAdjust2ByteFormRealTime
289
+ OctaveTuningAdjust2ByteFormNonRealTime = ScaleTuningAdjust2ByteFormNonRealTime
290
+
291
+ class KeyBasedInstrumentControllers < ExclusiveF0
292
+
293
+ def initialize(offset, ch, kk, nn_vv, dev=0x7f)
294
+ # kk:0/2**7-1, nn:7|10|91|93, vv:0/2**7-1
295
+ super(offset, [0x7f, dev, 0x0a, 0x01, ch, kk, nn_vv, 0xf7].
296
+ flatten.pack('C*'))
297
+ end
298
+
299
+ end
300
+
301
+ class GM1SystemOn < ExclusiveF0
302
+
303
+ def initialize(offset, dev=0x7f)
304
+ super(offset, [0x7e, dev, 0x09, 0x01, 0xf7].pack('C*'))
305
+ end
306
+
307
+ end
308
+
309
+ GMSystemOn = GM1SystemOn
310
+
311
+ class GMSystemOff < ExclusiveF0
312
+
313
+ def initialize(offset, dev=0x7f)
314
+ super(offset, [0x7e, dev, 0x09, 0x02, 0xf7].pack('C*'))
315
+ end
316
+
317
+ end
318
+
319
+ class GM2SystemOn < ExclusiveF0
320
+
321
+ def initialize(offset, dev=0x7f)
322
+ super(offset, [0x7e, dev, 0x09, 0x03, 0xf7].pack('C*'))
323
+ end
324
+
325
+ end
326
+
327
+ end
@@ -0,0 +1,34 @@
1
+ # groove.rb: Written by Tadayoshi Funaba 2005,2006,2008
2
+ # $Id: groove.rb,v 1.3 2008-02-16 16:56:21+09 tadf Exp $
3
+
4
+ require 'gsl'
5
+
6
+ module SMF
7
+
8
+ class Groove
9
+
10
+ def initialize(div, pat)
11
+ @unit = pat[-1] * div * 4
12
+ x = []; y = []
13
+ pat.each_with_index do |p, i|
14
+ x << @unit / (pat.size - 1) * i
15
+ y << p * div * 4
16
+ end
17
+ @x = GSL::Vector.alloc(x)
18
+ @y = GSL::Vector.alloc(y)
19
+ @interp = GSL::Interp.alloc('linear', pat.size)
20
+ self.amount = 0.5
21
+ end
22
+
23
+ def amount=(v) @amount = v end
24
+
25
+ def groove(ev)
26
+ q, r = ev.offset.divmod(@unit)
27
+ r2 = @interp.eval(@x, @y, r)
28
+ r3 = r + (r2 - r) * @amount
29
+ ev.offset = (q * @unit + r3).round
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,282 @@
1
+ # macro.rb: Written by Tadayoshi Funaba 1999-2006
2
+ # $Id: macro.rb,v 1.5 2006-11-10 21:58:21+09 tadf Exp $
3
+
4
+ require 'smf'
5
+ require 'smf/toy/gm'
6
+ require 'rational'
7
+
8
+ module SMF
9
+
10
+ class Sheet
11
+
12
+ def initialize(sq)
13
+ @sq = sq
14
+ @co = []
15
+ gt(0)
16
+ end
17
+
18
+ def snap(ev)
19
+ @co << ev
20
+ end
21
+
22
+ def gt(n) @sq[n] ||= Track.new end
23
+
24
+ private :gt
25
+
26
+ def re(v, l, h=nil)
27
+ if v && l && v < l then v = l end
28
+ if v && h && v > h then v = h end
29
+ v
30
+ end
31
+
32
+ private :re
33
+
34
+ def generate
35
+ i = 0
36
+ @co = @co.sort_by{|x| [x[:of], i += 1]}
37
+
38
+ i = 0
39
+ lev = {}
40
+ uniq = {}
41
+ @co.each do |ev|
42
+
43
+ ev.each_key do |key|
44
+
45
+ if ev[key] == nil || ev[key] == lev[key]
46
+ next
47
+ end
48
+
49
+ case key.to_s
50
+ when /\A_(no|tx|ke)/
51
+ k = format('%d:%s', i, key)
52
+ uniq[k] = [i, key, ev]
53
+ when /\A(te|ti|pp|co|mo|pr|cp|pi|gm)/
54
+ k = format('%s:%s', ev[:of], key)
55
+ if uniq[k]
56
+ uniq[k] = [uniq[k][0], key, ev]
57
+ else
58
+ uniq[k] = [i, key, ev]
59
+ end
60
+ lev[key] = ev[key]
61
+ end
62
+
63
+ i += 1
64
+
65
+ end
66
+
67
+ end
68
+
69
+ co2 = uniq.values.sort_by{|x| x[0]}
70
+
71
+ wh = @sq.division * 4
72
+
73
+ ke = {}
74
+
75
+ co2.each do |_, key, ev|
76
+ tr = ev[:tr].to_i; tr = re(tr, 0, 65535) # 0/2**16-1
77
+ ch = ev[:ch].to_i; ch = re(ch, 0, 15) # 0/2**4-1
78
+ of = ev[:of]; of = re(of, 0)
79
+ oc = ev[:oc]
80
+ le = ev[:le]; le = re(le, 0.to_r)
81
+ du = ev[:du]; du = re(du, 0.to_r)
82
+ ve = ev[:ve]; ve = re(ve, 0.to_r, 1.to_r)
83
+ sf, = ev[:ke]; sf ||= 0
84
+ v = ev[key]
85
+
86
+ case key.to_s
87
+
88
+ when '_no'
89
+ t = gt(tr)
90
+ o = (of * wh).round
91
+ p = ((of + le * du) * wh).round
92
+ na, s1, s12 = v
93
+ unless s1
94
+ unless ke[sf]
95
+ ke[sf] = [0] * 12
96
+ d = if sf < 0 then -1 else +1 end
97
+ b = if d == 1 then 5 else 11 end
98
+ sf.to_i.abs.times do |i|
99
+ n = (b + 7 * i * d) % 12
100
+ ke[sf][n] += d
101
+ end
102
+ end
103
+ s1 = ke[sf][na]
104
+ end
105
+ s1 ||=0
106
+ s12 ||=0
107
+ n = (na + s1 + s12 + oc * 12 + 12).to_i
108
+ if n < 0 then n = n % 12 end
109
+ if n > 127 then n = 116 + (n - 116) % 12 end
110
+ w = (ve * 127).round
111
+ if w != 0
112
+ t << NoteOn.new(o, ch, n, w)
113
+ t << NoteOff.new(p, ch, n, 64)
114
+ end
115
+
116
+ when '_tx'
117
+ n = if /\A(co|sq):/ =~ v then 0 else tr end
118
+ t = gt(n)
119
+ o = (of * wh).round
120
+ case v
121
+ when /\Ate:/; t << GeneralPurposeText.new(o, $')
122
+ when /\Aco:/; t << CopyrightNotice.new(o, $')
123
+ when /\Asq:/; t << SequenceName.new(o, $')
124
+ when /\Atr:/; t << TrackName.new(o, $')
125
+ when /\Ain:/; t << InstrumentName.new(o, $')
126
+ when /\Aly:/; t << Lyric.new(o, $')
127
+ when /\Ama:/; t << Marker.new(o, $')
128
+ when /\Acu:/; t << CuePoint.new(o, $')
129
+ when /\Apr:/; t << ProgramName.new(o, $')
130
+ when /\Ade:/; t << DeviceName.new(o, $')
131
+ else; t << GeneralPurposeText.new(o, v)
132
+ end
133
+
134
+ when '_ke'
135
+ s, m = v
136
+ m ||= 0
137
+ s = re(s, -128, 127) # -2**7/2**7-1
138
+ m = re(m, 0, 1) # 0/1
139
+ t = gt(tr)
140
+ o = (of * wh).round
141
+ t << KeySignature.new(o, s.to_i, m.to_i)
142
+
143
+ when 'te'
144
+ v = re(v, 1, 16777215) # 1/2**24-1
145
+ t = gt(0)
146
+ o = (of * wh).round
147
+ t << SetTempo.new(o, (60000000 / v).round)
148
+
149
+ when 'ti'
150
+ n, d = v
151
+ d ||= 4
152
+ n = re(n, 1, 255) # 1/2**8-1
153
+ d = re(d, 0, 255) # 0/2**8-1
154
+ t = gt(0)
155
+ o = (of * wh).round
156
+ n, d = n.to_i, d.to_i
157
+ dd = -1
158
+ while d != 0
159
+ d >>= 1
160
+ dd += 1
161
+ end
162
+ c = 96 >> dd
163
+ t << TimeSignature.new(o, n, dd, c, 8)
164
+
165
+ when /\App(\d+)\/\d+\z/
166
+ n = $1
167
+ v = re(v, 0, 127) # 0/2**7-1
168
+ t = gt(tr)
169
+ o = (of * wh).round
170
+ t << PolyphonicKeyPressure.new(o, ch, n.to_i, v.to_i)
171
+
172
+ when /\Aco(\d+)\/\d+\z/
173
+ n = $1
174
+ v = re(v, 0, 127) # 0/2**7-1
175
+ t = gt(tr)
176
+ o = (of * wh).round
177
+ t << ControlChange.new(o, ch, n.to_i, v.to_i)
178
+
179
+ when /\Amo(\d+)\/\d+\z/
180
+ n = $1
181
+ v = re(v, 0, 127) # 0/2**7-1
182
+ t = gt(tr)
183
+ o = (of * wh).round
184
+ case n.to_i
185
+ when 0x78; t << AllSoundOff.new(o, ch)
186
+ when 0x79; t << ResetAllControllers.new(o, ch)
187
+ when 0x7a; t << LocalControl.new(o, ch, v)
188
+ when 0x7b; t << AllNotesOff.new(o, ch)
189
+ when 0x7c; t << OmniOff.new(o, ch)
190
+ when 0x7d; t << OmniOn.new(o, ch)
191
+ when 0x7e; t << MonoMode.new(o, ch, v)
192
+ when 0x7f; t << PolyMode.new(o, ch)
193
+ end
194
+
195
+ when /\Apr\/\d+\z/
196
+ v = re(v, 0, 127) # 0/2**7-1
197
+ t = gt(tr)
198
+ o = (of * wh).round
199
+ t << ProgramChange.new(o, ch, v.to_i)
200
+
201
+ when /\Acp\/\d+\z/
202
+ v = re(v, 0, 127) # 0/2**7-1
203
+ t = gt(tr)
204
+ o = (of * wh).round
205
+ t << ChannelPressure.new(o, ch, v.to_i)
206
+
207
+ when /\Api\/\d+\z/
208
+ v = re(v, -8192, 8191) # -2**13/2**13-1
209
+ t = gt(tr)
210
+ o = (of * wh).round
211
+ t << PitchBendChange.new(o, ch, v.to_i)
212
+
213
+ when 'gm'
214
+ v = re(v, 0, 2) # 0/2
215
+ t = gt(0)
216
+ o = (of * wh).round
217
+ case v
218
+ when 0; t << GMSystemOff.new(o)
219
+ when 1; t << GMSystemOn.new(o)
220
+ when 2; t << GM2SystemOn.new(o)
221
+ end
222
+
223
+ end
224
+
225
+ end
226
+
227
+ ev = @co[-1]
228
+ max_of = (if ev then ev[:of] else 0 end)
229
+ o = (max_of * wh).round
230
+ @sq.each do |tr| tr << EndOfTrack.new(o) end
231
+
232
+ end
233
+
234
+ end
235
+
236
+ class Descripter
237
+
238
+ def initialize(sh)
239
+ @sh = sh
240
+ @es = []
241
+ @es << {}
242
+ @es[-1][:tr] = 1
243
+ @es[-1][:ch] = 0
244
+ @es[-1][:of] = 0
245
+ @es[-1][:oc] = 4.to_r/1
246
+ @es[-1][:le] = 1.to_r/4
247
+ @es[-1][:du] = 9.to_r/10
248
+ @es[-1][:ve] = 3.to_r/4
249
+ end
250
+
251
+ def push() @es.push(@es[-1].dup) end
252
+ def pop() @es.pop end
253
+
254
+ def rv(k, ch)
255
+ k = k.to_s
256
+ k.gsub!(/0+(\d)/, '\1')
257
+ case k
258
+ when /\A(pp|co|mo)(\d+)\z/; k += format('/%d', ch)
259
+ when /\A(pr|cp|pi)\z/ ; k += format('/%d', ch)
260
+ end
261
+ k = k.intern
262
+ end
263
+
264
+ private :rv
265
+
266
+ def [] (k)
267
+ ch = @es[-1][:ch]
268
+ k = rv(k, ch.to_i)
269
+ @es[-1][k]
270
+ end
271
+
272
+ def []=(k, v)
273
+ ch = @es[-1][:ch]
274
+ k = rv(k, ch.to_i)
275
+ @es[-1][k] = v
276
+ end
277
+
278
+ def snap() @sh.snap(@es[-1].dup) end
279
+
280
+ end
281
+
282
+ end