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