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,24 @@
1
+ # searchsegment.rb: Written by Tadayoshi Funaba 2006
2
+ # $Id: searchsegment.rb,v 1.1 2006-06-20 22:24:14+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ module SearchSegment
7
+
8
+ def search_segment(a)
9
+ l = 0
10
+ u = a.size
11
+ while l < u
12
+ m = ((l + u) / 2).truncate
13
+ if (yield a[m]) <= 0
14
+ l = m + 1
15
+ else
16
+ u = m
17
+ end
18
+ end
19
+ l - 1
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,39 @@
1
+ # shuffle.rb: Written by Tadayoshi Funaba 2005,2006,2008
2
+ # $Id: shuffle.rb,v 1.4 2008-02-16 16:56:21+09 tadf Exp $
3
+
4
+ require 'gsl'
5
+
6
+ module SMF
7
+
8
+ class Shuffle
9
+
10
+ def initialize(div, unit=1.0/8)
11
+ @unit = unit * div * 4
12
+ self.amount = 0.5
13
+ end
14
+
15
+ def amount=(v)
16
+ =begin
17
+ shift = @unit / 2 * v
18
+ @x = GSL::Vector.alloc(0, @unit / 2, @unit)
19
+ @y = GSL::Vector.alloc(0, @unit / 2 + shift, @unit)
20
+ @interp = Interp.alloc('linear', 3)
21
+ =end
22
+ #=begin
23
+ qunit = @unit / 4
24
+ shift = @unit / 4 * v
25
+ @x = GSL::Vector.alloc(0, qunit, qunit*2, qunit*3, @unit)
26
+ @y = GSL::Vector.alloc(0, qunit, qunit*2 + shift, qunit*3 + shift/2, @unit)
27
+ @interp = GSL::Interp.alloc('linear', 5)
28
+ #=end
29
+ end
30
+
31
+ def shuffle(ev)
32
+ q, r = ev.offset.divmod(@unit)
33
+ r2 = @interp.eval(@x, @y, r)
34
+ ev.offset = (q * @unit + r2).round
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,75 @@
1
+ # tempomap.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: tempomap.rb,v 1.2 2006-06-20 22:24:14+09 tadf Exp $
3
+
4
+ require 'smf/toy/searchsegment'
5
+ require 'rational'
6
+
7
+ module SMF
8
+
9
+ class TempoMap
10
+
11
+ include SearchSegment
12
+
13
+ def o2e(div, offset, tempo)
14
+ offset * (60.to_r/tempo) / div
15
+ end
16
+
17
+ def e2o(div, elapse, tempo)
18
+ elapse * div / (60.to_r/tempo)
19
+ end
20
+
21
+ private :o2e, :e2o
22
+
23
+ def initialize(sq)
24
+ @div = sq.division
25
+ @map = [[0, 120, 0]] # [[offset, bpm, elapse]]
26
+ sq.each do |tr|
27
+ tr.each do |ev|
28
+ case ev
29
+ when SetTempo; @map << [ev.offset, 60000000.to_r / ev.tempo, 0]
30
+ end
31
+ end
32
+ end
33
+ i = 0
34
+ @map = @map.sort_by{|x| [x[0], i += 1]}
35
+ lx = nil
36
+ @map.each do |x|
37
+ if lx
38
+ s = o2e(@div, x[0] - lx[0], lx[1])
39
+ x[2] = lx[2] + s
40
+ end
41
+ lx = x
42
+ end
43
+ end
44
+
45
+ def offset2elapse(offset)
46
+ i = search_segment(@map){|x| x[0] <=> offset}
47
+ lx = @map[i]
48
+ elapse = lx[2] + o2e(@div, offset - lx[0], lx[1])
49
+ elapse
50
+ end
51
+
52
+ def elapse2offset(elapse)
53
+ i = search_segment(@map){|x| x[2] <=> elapse}
54
+ lx = @map[i]
55
+ offset = lx[0] + e2o(@div, elapse - lx[2], lx[1])
56
+ offset.round
57
+ end
58
+
59
+ def elapse2frame(elapse, tc=30)
60
+ hr, mod = elapse.divmod(3600.to_r)
61
+ mn, mod = mod.divmod(60.to_r)
62
+ se, mod = mod.divmod(1.to_r)
63
+ fr, mod = mod.divmod(1.to_r/tc)
64
+ ff, mod = mod.divmod(1.to_r/tc/100)
65
+ [hr, mn, se, fr, ff]
66
+ end
67
+
68
+ def frame2elapse(frame, tc=30)
69
+ frame[0] * 3600 + frame[1] * 60 + frame[2] +
70
+ frame[3].to_r / tc + frame[4].to_r / (100 * tc)
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,369 @@
1
+ # text.rb: Written by Tadayoshi Funaba 1999-2006
2
+ # $Id: text.rb,v 1.4 2006-11-10 21:58:21+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ class Sequence
7
+
8
+ class RSText
9
+
10
+ class PO
11
+
12
+ def initialize(str)
13
+ @arr = str.split(/\n+/).
14
+ collect{|x| x.strip}.
15
+ select{|x| !x.empty?}
16
+ end
17
+
18
+ def gets() @arr.shift end
19
+ def eof?() @arr.empty? end
20
+
21
+ end
22
+
23
+ def initialize(s, cb) @s, @cb = s, cb end
24
+
25
+ def get_offset(s)
26
+ s.sub!(/\A\s*(\d+)/, '')
27
+ return $1.to_i
28
+ end
29
+
30
+ def get_name(s)
31
+ s.sub!(/\A\s*(\S+)/, '')
32
+ return $1
33
+ end
34
+
35
+ def get_params(s)
36
+ s.scan(/\d+/).collect{|x| x.to_i}
37
+ end
38
+
39
+ def get_text(s)
40
+ eval(s)
41
+ end
42
+
43
+ private :get_offset, :get_name, :get_params, :get_text
44
+
45
+ def read_header(rs)
46
+ ln = rs.gets
47
+ name = get_name(ln)
48
+ case name
49
+ when /\AMThd/i
50
+ f, n, d, s = get_params(ln)
51
+ @cb.header(f, n, d, s)
52
+ else
53
+ @cb.error('not a text')
54
+ end
55
+ end
56
+
57
+ def read_track(rs)
58
+ ln = rs.gets
59
+ case ln
60
+ when /\AMTrk\z/i
61
+ @cb.track_start
62
+ else
63
+ @cb.error('track not found')
64
+ end
65
+ loffset = 0
66
+ until rs.eof?
67
+ ln = rs.gets
68
+ case ln
69
+ when /\AMTrkEnd\z/i
70
+ @cb.track_end
71
+ return
72
+ end
73
+ offset = get_offset(ln)
74
+ @cb.delta(offset - loffset)
75
+ loffset = offset
76
+ name = get_name(ln)
77
+ case name
78
+ when /\ANoteOff\z/i
79
+ @cb.noteoff(*get_params(ln)[0,3])
80
+ when /\ANoteOn\z/i
81
+ @cb.noteon(*get_params(ln)[0,3])
82
+ when /\APolyphonicKeyPressure\z/i
83
+ @cb.polyphonickeypressure(*get_params(ln)[0,3])
84
+ when /\AControlChange\z/i
85
+ @cb.controlchange(*get_params(ln)[0,3])
86
+ when /\AProgramChange\z/i
87
+ @cb.programchange(*get_params(ln)[0,2])
88
+ when /\AChannelPressure\z/i
89
+ @cb.channelpressure(*get_params(ln)[0,2])
90
+ when /\APitchBendChange\z/i
91
+ @cb.pitchbendchange(*get_params(ln)[0,2])
92
+ when /\AAllSoundOff\z/i
93
+ ch, = get_params(ln)
94
+ @cb.allsoundoff(ch)
95
+ when /\AResetAllControllers\z/i
96
+ ch, = get_params(ln)
97
+ @cb.resetallcontrollers(ch)
98
+ when /\ALocalControl\z/i
99
+ ch, val, = get_params(ln)
100
+ @cb.localcontrol(ch, val)
101
+ when /\AAllNotesOff\z/i
102
+ ch, = get_params(ln)
103
+ @cb.allnotesoff(ch)
104
+ when /\AOmniOff\z/i
105
+ ch, = get_params(ln)
106
+ @cb.omnioff(ch)
107
+ when /\AOmniOn\z/i
108
+ ch, = get_params(ln)
109
+ @cb.omnion(ch)
110
+ when /\AMonoMode\z/i
111
+ ch, val, = get_params(ln)
112
+ @cb.monomode(ch, val)
113
+ when /\APolyMode\z/i
114
+ ch, = get_params(ln)
115
+ @cb.polymode(ch)
116
+ when /\AExclusiveF0\z/i
117
+ @cb.exclusivef0(get_text(ln))
118
+ when /\AExclusiveF7\z/i
119
+ @cb.exclusivef7(get_text(ln))
120
+ when /\ASequenceNumber\z/i
121
+ @cb.sequencenumber(*get_params(ln)[0,1])
122
+ when /\A(GeneralPurposeText|Text01)\z/i
123
+ @cb.generalpurposetext(get_text(ln))
124
+ when /\A(CopyrightNotice|Text02)\z/i
125
+ @cb.copyrightnotice(get_text(ln))
126
+ when /\A(TrackName|SequenceName|Text03)\z/i
127
+ @cb.trackname(get_text(ln))
128
+ when /\A(InstrumentName|Text04)\z/i
129
+ @cb.instrumentname(get_text(ln))
130
+ when /\A(Lyric|Text05)\z/i
131
+ @cb.lyric(get_text(ln))
132
+ when /\A(Marker|Text06)\z/i
133
+ @cb.marker(get_text(ln))
134
+ when /\A(CuePoint|Text07)\z/i
135
+ @cb.cuepoint(get_text(ln))
136
+ when /\A(ProgramName|Text08)\z/i
137
+ @cb.programname(get_text(ln))
138
+ when /\A(DeviceName|Text09)\z/i
139
+ @cb.devicename(get_text(ln))
140
+ when /\AText0([A-F])\z/i
141
+ case $1
142
+ when 'A'; @cb.text0a(get_text(ln))
143
+ when 'B'; @cb.text0b(get_text(ln))
144
+ when 'C'; @cb.text0c(get_text(ln))
145
+ when 'D'; @cb.text0d(get_text(ln))
146
+ when 'E'; @cb.text0e(get_text(ln))
147
+ when 'F'; @cb.text0f(get_text(ln))
148
+ end
149
+ when /\AChannelPrefix\z/i
150
+ @cb.channelprefix(*get_params(ln)[0,1])
151
+ when /\AMIDIPort\z/i
152
+ @cb.midiport(*get_params(ln)[0,1])
153
+ when /\AEndOfTrack\z/i
154
+ @cb.endoftrack()
155
+ when /\ASetTempo\z/i
156
+ @cb.settempo(*get_params(ln)[0,1])
157
+ when /\ASMPTEOffset\z/i
158
+ @cb.smpteoffset(*get_params(ln)[0,6])
159
+ when /\ATimeSignature\z/i
160
+ @cb.timesignature(*get_params(ln)[0,4])
161
+ when /\AKeySignature\z/i
162
+ @cb.keysignature(*get_params(ln)[0,2])
163
+ when /\ASequencerSpecific\z/i
164
+ @cb.sequencerspecific(get_text(ln))
165
+ else
166
+ @cb.error('unknown event: ' + name)
167
+ end
168
+ end
169
+ @cb.track_end
170
+ end
171
+
172
+ private :read_header, :read_track
173
+
174
+ def read
175
+ rs = RSText::PO.new(@s)
176
+ read_header(rs)
177
+ until rs.eof?
178
+ read_track(rs)
179
+ end
180
+ @cb.result
181
+ end
182
+
183
+ end
184
+
185
+ class << self
186
+
187
+ def decode_text(s)
188
+ self::RSText.new(s, self::Decode.new).read
189
+ end
190
+
191
+ def read_text(io)
192
+ decode_text(io.binmode.read)
193
+ end
194
+
195
+ def load_text(fn)
196
+ open(fn) do |io|
197
+ read_text(io)
198
+ end
199
+ end
200
+
201
+ end
202
+
203
+ class EncodeText < XSCallback
204
+
205
+ def header(format, ntrks, division, tc)
206
+ if tc
207
+ @s = format("MThd %d %d %d %d\n", format, ntrks, division, tc)
208
+ else
209
+ @s = format("MThd %d %d %d\n", format, ntrks, division)
210
+ end
211
+ end
212
+
213
+ def track_start() @offset = 0; @s << "MTrk\n" end
214
+ def track_end() @offset = 0; @s << "MTrkEnd\n" end
215
+
216
+ def delta(delta) @offset += delta end
217
+
218
+ def noteoff(ch, note, vel)
219
+ @s << format("%d NoteOff %d %d %d\n", @offset, ch, note, vel)
220
+ end
221
+
222
+ def noteon(ch, note, vel)
223
+ @s << format("%d NoteOn %d %d %d\n", @offset, ch, note, vel)
224
+ end
225
+
226
+ def polyphonickeypressure(ch, note, val)
227
+ @s << format("%d PolyphonicKeyPressure %d %d %d\n",
228
+ @offset, ch, note, val)
229
+ end
230
+
231
+ def controlchange(ch, num, val)
232
+ @s << format("%d ControlChange %d %d %d\n", @offset, ch, num, val)
233
+ end
234
+
235
+ def programchange(ch, num)
236
+ @s << format("%d ProgramChange %d %d\n", @offset, ch, num)
237
+ end
238
+
239
+ def channelpressure(ch, val)
240
+ @s << format("%d ChannelPressure %d %d\n", @offset, ch, val)
241
+ end
242
+
243
+ def pitchbendchange(ch, val)
244
+ @s << format("%d PitchBendChange %d %d\n", @offset, ch, val)
245
+ end
246
+
247
+ def allsoundoff(ch)
248
+ @s << format("%d AllSoundOff %d\n", @offset, ch)
249
+ end
250
+
251
+ def resetallcontrollers(ch)
252
+ @s << format("%d ResetAllControllers %d\n", @offset, ch)
253
+ end
254
+
255
+ def localcontrol(ch, val)
256
+ @s << format("%d LocalControl %d %d\n", @offset, ch, val)
257
+ end
258
+
259
+ def allnotesoff(ch)
260
+ @s << format("%d AllNotesOff %d\n", @offset, ch)
261
+ end
262
+
263
+ def omnioff(ch)
264
+ @s << format("%d OmniOff %d\n", @offset, ch)
265
+ end
266
+
267
+ def omnion(ch)
268
+ @s << format("%d OmniOn %d\n", @offset, ch)
269
+ end
270
+
271
+ def monomode(ch, val)
272
+ @s << format("%d MonoMode %d %d\n", @offset, ch, val)
273
+ end
274
+
275
+ def polymode(ch)
276
+ @s << format("%d PolyMode %d\n", @offset, ch)
277
+ end
278
+
279
+ def put_binary(name, data)
280
+ @s << format('%d %s "', @offset, name)
281
+ data.each_byte do |c|
282
+ @s << format('\\%03o', c)
283
+ end
284
+ @s << "\"\n" # "
285
+ end
286
+
287
+ private :put_binary
288
+
289
+ def exclusivef0(data) put_binary('ExclusiveF0', data) end
290
+ def exclusivef7(data) put_binary('ExclusiveF7', data) end
291
+
292
+ def sequencenumber(num)
293
+ @s << format("%d SequenceNumber %d\n", @offset, num)
294
+ end
295
+
296
+ def text(name, text)
297
+ @s << format("%d %s %s\n", @offset, name, text.dump)
298
+ end
299
+
300
+ private :text
301
+
302
+ def generalpurposetext(text) text('GeneralPurposeText', text) end
303
+ def copyrightnotice(text) text('CopyrightNotice', text) end
304
+ def trackname(text) text('TrackName', text) end
305
+ def instrumentname(text) text('InstrumentName', text) end
306
+ def lyric(text) text('Lyric', text) end
307
+ def marker(text) text('Marker', text) end
308
+ def cuepoint(text) text('CuePoint', text) end
309
+ def programname(text) text('ProgramName', text) end
310
+ def devicename(text) text('DeviceName', text) end
311
+ def text0a(text) text('Text0A', text) end
312
+ def text0b(text) text('Text0B', text) end
313
+ def text0c(text) text('Text0C', text) end
314
+ def text0d(text) text('Text0D', text) end
315
+ def text0e(text) text('Text0E', text) end
316
+ def text0f(text) text('Text0F', text) end
317
+
318
+ def channelprefix(ch)
319
+ @s << format("%d ChannelPrefix %d\n", @offset, ch)
320
+ end
321
+
322
+ def midiport(num)
323
+ @s << format("%d MIDIPort %d\n", @offset, num)
324
+ end
325
+
326
+ def endoftrack
327
+ @s << format("%d EndOfTrack\n", @offset)
328
+ end
329
+
330
+ def settempo(tempo)
331
+ @s << format("%d SetTempo %d\n", @offset, tempo)
332
+ end
333
+
334
+ def smpteoffset(hr, mn, se, fr, ff, tc)
335
+ @s << format("%d SMPTEOffset %d %d %d %d %d %d\n",
336
+ @offset, hr, mn, se, fr, ff, tc)
337
+ end
338
+
339
+ def timesignature(nn, dd, cc, bb)
340
+ @s << format("%d TimeSignature %d %d %d %d\n", @offset, nn, dd, cc, bb)
341
+ end
342
+
343
+ def keysignature(sf, mi)
344
+ @s << format("%d KeySignature %d %d\n", @offset, sf, mi)
345
+ end
346
+
347
+ def sequencerspecific(data) put_binary('SequencerSpecific', data) end
348
+
349
+ def result() @s end
350
+
351
+ end
352
+
353
+ def encode_text
354
+ self.class::WS.new(self, self.class::EncodeText.new).read
355
+ end
356
+
357
+ def write_text(io)
358
+ io.write(encode_text)
359
+ end
360
+
361
+ def save_text(fn)
362
+ open(fn, 'w') do |io|
363
+ write_text(io)
364
+ end
365
+ end
366
+
367
+ end
368
+
369
+ end