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
@@ -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