smf 0.15.12
Sign up to get free protection for your applications and to get access to all the features.
- data/MANUAL +172 -0
- data/MANUAL.en +135 -0
- data/MANUAL.en.html +150 -0
- data/MANUAL.en.rd +144 -0
- data/MANUAL.html +201 -0
- data/MANUAL.rd +179 -0
- data/README +33 -0
- data/README.en +33 -0
- data/lib/smf.rb +736 -0
- data/lib/smf/divert.rb +21 -0
- data/lib/smf/io.rb +1278 -0
- data/lib/smf/toy/beatmap.rb +73 -0
- data/lib/smf/toy/gm.rb +327 -0
- data/lib/smf/toy/groove.rb +34 -0
- data/lib/smf/toy/macro.rb +282 -0
- data/lib/smf/toy/macro/mml.rb +34 -0
- data/lib/smf/toy/macro/mml/parser.rb +545 -0
- data/lib/smf/toy/macro/mml/parser.ry +239 -0
- data/lib/smf/toy/macro/stt.rb +33 -0
- data/lib/smf/toy/morse.rb +126 -0
- data/lib/smf/toy/quantize.rb +32 -0
- data/lib/smf/toy/rmi.rb +29 -0
- data/lib/smf/toy/searchsegment.rb +24 -0
- data/lib/smf/toy/shuffle.rb +39 -0
- data/lib/smf/toy/tempomap.rb +75 -0
- data/lib/smf/toy/text.rb +369 -0
- data/lib/smf/toy/velcomp.rb +42 -0
- data/lib/smf/toy/virtual.rb +118 -0
- data/lib/smf/toy/xml.rb +377 -0
- data/sample/Makefile +58 -0
- data/sample/bwv772.mid +0 -0
- data/sample/bwv772.mml +94 -0
- data/sample/bwv775.mid +0 -0
- data/sample/bwv775.mml +157 -0
- data/sample/bwv787.mid +0 -0
- data/sample/bwv787.mml +129 -0
- data/sample/groove.grv +33 -0
- data/sample/groove.rb +45 -0
- data/sample/ltvddpd2.mid +0 -0
- data/sample/ltvddpd2.stt +60 -0
- data/sample/merge.rb +38 -0
- data/sample/mml-samp.rb +19 -0
- data/sample/mml.rb +36 -0
- data/sample/morse-samp.rb +11 -0
- data/sample/morse.rb +31 -0
- data/sample/play-oss.rb +215 -0
- data/sample/play-oss2.rb +253 -0
- data/sample/play-oss3.rb +150 -0
- data/sample/play-spkr.rb +97 -0
- data/sample/play-win.rb +195 -0
- data/sample/quantize.rb +41 -0
- data/sample/rand1.rb +21 -0
- data/sample/rand2.rb +24 -0
- data/sample/rmi2smf.rb +26 -0
- data/sample/shuffle.rb +43 -0
- data/sample/smf2rmi.rb +26 -0
- data/sample/smf2smf.rb +26 -0
- data/sample/smf2text.rb +27 -0
- data/sample/smf2wav.rb +123 -0
- data/sample/smf2xml.rb +27 -0
- data/sample/split.rb +40 -0
- data/sample/stt-samp.rb +19 -0
- data/sample/stt.rb +36 -0
- data/sample/text2smf.rb +28 -0
- data/sample/velcomp.rb +45 -0
- data/sample/virtual-samp.rb +19 -0
- data/sample/xml2smf.rb +28 -0
- 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
|
data/lib/smf/toy/gm.rb
ADDED
@@ -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
|