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,42 @@
1
+ # velcomp.rb: Written by Tadayoshi Funaba 2005,2006,2008
2
+ # $Id: velcomp.rb,v 1.3 2008-02-16 16:56:21+09 tadf Exp $
3
+
4
+ require 'gsl'
5
+
6
+ module SMF
7
+
8
+ class VelComp
9
+
10
+ def initialize
11
+ self.gain = 0
12
+ self.thresh = 80
13
+ self.ratio = 0.9
14
+ end
15
+
16
+ def init
17
+ max = @thresh + (127 - @thresh) * @ratio
18
+ @x = GSL::Vector.alloc(0, @thresh, 127)
19
+ @y = GSL::Vector.alloc(0, @thresh, max)
20
+ @interp = GSL::Interp.alloc('linear', 3)
21
+ end
22
+
23
+ private :init
24
+
25
+ def gain=(v) @gain = v end
26
+ def thresh=(v) @thresh = v; @interp = nil end
27
+ def ratio=(v) @ratio = v; @interp = nil end
28
+
29
+ def velcomp(ev)
30
+ init unless @interp
31
+ v = ev.vel + @gain
32
+ v = 127 if v > 127
33
+ v = 1 if v < 1
34
+ v2 = @interp.eval(@x, @y, v)
35
+ v2 = 127 if v > 127
36
+ v2 = 1 if v < 1
37
+ ev.vel = v2.round
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,118 @@
1
+ # virtual.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: virtual.rb,v 1.3 2006-11-10 21:58:21+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ class Sequence
7
+
8
+ def to_virtual
9
+ v = VirtualSequence.new(format, division, tc)
10
+ each do |tr|
11
+ v << tr.to_virtual
12
+ end
13
+ v
14
+ end
15
+
16
+ end
17
+
18
+ class Track
19
+
20
+ def to_virtual
21
+ v = VirtualTrack.new
22
+ xs = []
23
+ each do |ev|
24
+ case ev
25
+ when NoteOn
26
+ xs.push(ev)
27
+ when NoteOff
28
+ on = nil
29
+ i = 0
30
+ xs.each_with_index do |x, i|
31
+ if x.ch == ev.ch && x.note == ev.note
32
+ on = x
33
+ break
34
+ end
35
+ end
36
+ if on
37
+ v << VirtualNote.new(on.offset, on.ch, on.note,
38
+ on.vel, ev.vel, ev.offset - on.offset)
39
+ xs.delete_at(i)
40
+ end
41
+ else
42
+ v << ev
43
+ end
44
+ end
45
+ v
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ module SMF
53
+
54
+ class VirtualSequence < Sequence
55
+
56
+ class RS < Sequence::RS; end
57
+ class WS < Sequence::WS
58
+
59
+ def initialize(o, cb) super(o.to_real, cb) end
60
+
61
+ end
62
+
63
+ class Decode < Sequence::Decode
64
+
65
+ def result() super().to_virtual end
66
+
67
+ end
68
+
69
+ class Encode < Sequence::Encode; end
70
+
71
+ def initialize(format, division, tc)
72
+ super(format, division, tc)
73
+ end
74
+
75
+ def to_real
76
+ r = Sequence.new(format, division, tc)
77
+ each do |tr|
78
+ r << tr.to_real
79
+ end
80
+ r
81
+ end
82
+
83
+ end
84
+
85
+ class VirtualTrack < Track
86
+
87
+ def initialize()
88
+ super()
89
+ end
90
+
91
+ def to_real
92
+ r = Track.new
93
+ each do |ev|
94
+ case ev
95
+ when VirtualNote
96
+ r << NoteOn.new(ev.offset, ev.ch, ev.note, ev.vel)
97
+ r << NoteOff.new(ev.offset + ev.length, ev.ch, ev.note, ev.offvel)
98
+ else
99
+ r << ev
100
+ end
101
+ end
102
+ r
103
+ end
104
+
105
+ end
106
+
107
+ class VirtualNote < VoiceMessage
108
+
109
+ def initialize(offset, ch, note, vel, offvel, length)
110
+ super(offset, ch)
111
+ @note, @vel, @offvel, @length = note, vel, offvel, length
112
+ end
113
+
114
+ attr_accessor :note, :vel, :offvel, :length
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,377 @@
1
+ # xml.rb: Written by Tadayoshi Funaba 2004-2007
2
+ # $Id: xml.rb,v 1.4 2007-12-26 20:33:25+09 tadf Exp $
3
+
4
+ require 'rexml/document'
5
+ require 'rexml/streamlistener'
6
+
7
+ begin require 'rexml/formatters/pretty'; rescue LoadError; end
8
+
9
+ module SMF
10
+
11
+ class Sequence
12
+
13
+ class RSXML
14
+
15
+ def initialize(s, cb) @s, @cb = s, cb end
16
+
17
+ include REXML::StreamListener
18
+
19
+ def get_params(attrs, keys)
20
+ attrs.values_at(*keys).collect{|x| x.to_i}
21
+ end
22
+
23
+ def get_text(attrs, key)
24
+ s = attrs[key]
25
+ eval('"%s"' % s)
26
+ end
27
+
28
+ def tag_start(name, attrs)
29
+ if attrs['offset']
30
+ offset = attrs['offset'].to_i
31
+ @cb.delta(offset - @loffset)
32
+ @loffset = offset
33
+ end
34
+ case name
35
+ when /\AMThd\z/i
36
+ f, n, d, s = get_params(attrs, %w(format ntrks division tc))
37
+ s = nil if attrs['tc']
38
+ @cb.header(f, n, d, s)
39
+ when /\AMTrk\z/i
40
+ @loffset = 0
41
+ @cb.track_start
42
+ when /\ANoteOff\z/i
43
+ @cb.noteoff(*get_params(attrs, %w(ch note vel)))
44
+ when /\ANoteOn\z/i
45
+ @cb.noteon(*get_params(attrs, %w(ch note vel)))
46
+ when /\APolyphonicKeyPressure\z/i
47
+ @cb.polyphonickeypressure(*get_params(attrs, %w(ch note val)))
48
+ when /\AControlChange\z/i
49
+ @cb.controlchange(*get_params(attrs, %w(ch num val)))
50
+ when /\AProgramChange\z/i
51
+ @cb.programchange(*get_params(attrs, %w(ch num)))
52
+ when /\AChannelPressure\z/i
53
+ @cb.channelpressure(*get_params(attrs, %w(ch val)))
54
+ when /\APitchBendChange\z/i
55
+ @cb.pitchbendchange(*get_params(attrs, %w(ch val)))
56
+ when /\AAllSoundOff\z/i
57
+ ch, = get_params(attrs, %w(ch))
58
+ @cb.allsoundoff(ch)
59
+ when /\AResetAllControllers\z/i
60
+ ch, = get_params(attrs, %w(ch))
61
+ @cb.resetallcontrollers(ch)
62
+ when /\ALocalControl\z/i
63
+ ch, val, = get_params(attrs, %w(ch, val))
64
+ @cb.localcontrol(ch, val)
65
+ when /\AAllNotesOff\z/i
66
+ ch, = get_params(attrs, %w(ch))
67
+ @cb.allnotesoff(ch)
68
+ when /\AOmniOff\z/i
69
+ ch, = get_params(attrs, %w(ch))
70
+ @cb.omnioff(ch)
71
+ when /\AOmniOn\z/i
72
+ ch, = get_params(attrs, %w(ch))
73
+ @cb.omnion(ch)
74
+ when /\AMonoMode\z/i
75
+ ch, val, = get_params(attrs, %w(ch val))
76
+ @cb.monomode(ch, val)
77
+ when /\APolyMode\z/i
78
+ ch, = get_params(attrs, %w(ch))
79
+ @cb.polymode(ch)
80
+ when /\AExclusiveF0\z/i
81
+ @cb.exclusivef0(get_text(attrs, 'data'))
82
+ when /\AExclusiveF7\z/i
83
+ @cb.exclusivef7(get_text(attrs, 'data'))
84
+ when /\ASequenceNumber\z/i
85
+ @cb.sequencenumber(*get_params(attrs, %w(num)))
86
+ when /\A(GeneralPurposeText|Text01)\z/i
87
+ @cb.generalpurposetext(get_text(attrs, 'text'))
88
+ when /\A(CopyrightNotice|Text02)\z/i
89
+ @cb.copyrightnotice(get_text(attrs, 'text'))
90
+ when /\A(TrackName|SequenceName|Text03)\z/i
91
+ @cb.trackname(get_text(attrs, 'text'))
92
+ when /\A(InstrumentName|Text04)\z/i
93
+ @cb.instrumentname(get_text(attrs, 'text'))
94
+ when /\A(Lyric|Text05)\z/i
95
+ @cb.lyric(get_text(attrs, 'text'))
96
+ when /\A(Marker|Text06)\z/i
97
+ @cb.marker(get_text(attrs, 'text'))
98
+ when /\A(CuePoint|Text07)\z/i
99
+ @cb.cuepoint(get_text(attrs, 'text'))
100
+ when /\A(ProgramName|Text08)\z/i
101
+ @cb.programname(get_text(attrs, 'text'))
102
+ when /\A(DeviceName|Text09)\z/i
103
+ @cb.devicename(get_text(attrs, 'text'))
104
+ when /\AText0([A-F])\z/i
105
+ case $1
106
+ when 'A'; @cb.text0a(get_text(attrs, 'text'))
107
+ when 'B'; @cb.text0b(get_text(attrs, 'text'))
108
+ when 'C'; @cb.text0c(get_text(attrs, 'text'))
109
+ when 'D'; @cb.text0d(get_text(attrs, 'text'))
110
+ when 'E'; @cb.text0e(get_text(attrs, 'text'))
111
+ when 'F'; @cb.text0f(get_text(attrs, 'text'))
112
+ end
113
+ when /\AChannelPrefix\z/i
114
+ @cb.channelprefix(*get_params(attrs, %w(ch)))
115
+ when /\AMIDIPort\z/i
116
+ @cb.midiport(*get_params(attrs, %w(num)))
117
+ when /\AEndOfTrack\z/i
118
+ @cb.endoftrack()
119
+ when /\ASetTempo\z/i
120
+ @cb.settempo(*get_params(attrs, %w(tempo)))
121
+ when /\ASMPTEOffset\z/i
122
+ @cb.smpteoffset(*get_params(attrs, %w(hr mn se fr ff tc)))
123
+ when /\ATimeSignature\z/i
124
+ @cb.timesignature(*get_params(attrs, %w(nn dd cc bb)))
125
+ when /\AKeySignature\z/i
126
+ @cb.keysignature(*get_params(attrs, %w(sf mi)))
127
+ when /\ASequencerSpecific\z/i
128
+ @cb.sequencerspecific(get_text(attrs, 'data'))
129
+ else
130
+ @cb.error('unknown event: ' + name)
131
+ end
132
+ end
133
+
134
+ def read
135
+ REXML::Document.parse_stream(@s, self)
136
+ @cb.result
137
+ end
138
+
139
+ end
140
+
141
+ class << self
142
+
143
+ def decode_xml(s)
144
+ self::RSXML.new(s, self::Decode.new).read
145
+ end
146
+
147
+ def read_xml(io)
148
+ decode_xml(io.binmode.read)
149
+ end
150
+
151
+ def load_xml(fn)
152
+ open(fn) do |io|
153
+ read_xml(io)
154
+ end
155
+ end
156
+
157
+ end
158
+
159
+ class EncodeXML < XSCallback
160
+
161
+ def header(format, ntrks, division, tc)
162
+ @doc = REXML::Document.new
163
+ @doc << REXML::XMLDecl.new
164
+ @docsq = REXML::Element.new('MThd', @doc)
165
+ @docsq.attributes['format'] = format.to_s
166
+ @docsq.attributes['division'] = division.to_s
167
+ @docsq.attributes['tc'] = tc.to_s
168
+ end
169
+
170
+ def track_start()
171
+ @offset = 0
172
+ @doctr = REXML::Element.new('MTrk', @docsq)
173
+ end
174
+
175
+ def delta(delta) @offset += delta end
176
+
177
+ def noteoff(ch, note, vel)
178
+ e = REXML::Element.new('NoteOff', @doctr)
179
+ e.attributes['offset'] = @offset.to_s
180
+ e.attributes['ch'] = ch.to_s
181
+ e.attributes['note'] = note.to_s
182
+ e.attributes['vel'] = vel.to_s
183
+ end
184
+
185
+ def noteon(ch, note, vel)
186
+ e = REXML::Element.new('NoteOn', @doctr)
187
+ e.attributes['offset'] = @offset.to_s
188
+ e.attributes['ch'] = ch.to_s
189
+ e.attributes['note'] = note.to_s
190
+ e.attributes['vel'] = vel.to_s
191
+ end
192
+
193
+ def polyphonickeypressure(ch, note, val)
194
+ e = REXML::Element.new('PolyphonicKeyPressure', @doctr)
195
+ e.attributes['offset'] = @offset.to_s
196
+ e.attributes['ch'] = ch.to_s
197
+ e.attributes['note'] = note.to_s
198
+ e.attributes['val'] = val.to_s
199
+ end
200
+
201
+ def controlchange(ch, num, val)
202
+ e = REXML::Element.new('ControlChange', @doctr)
203
+ e.attributes['offset'] = @offset.to_s
204
+ e.attributes['ch'] = ch.to_s
205
+ e.attributes['num'] = num.to_s
206
+ e.attributes['val'] = val.to_s
207
+ end
208
+
209
+ def programchange(ch, num)
210
+ e = REXML::Element.new('ProgramChange', @doctr)
211
+ e.attributes['offset'] = @offset.to_s
212
+ e.attributes['ch'] = ch.to_s
213
+ e.attributes['num'] = num.to_s
214
+ end
215
+
216
+ def channelpressure(ch, val)
217
+ e = REXML::Element.new('ChannelPressure', @doctr)
218
+ e.attributes['offset'] = @offset.to_s
219
+ e.attributes['ch'] = ch.to_s
220
+ e.attributes['val'] = val.to_s
221
+ end
222
+
223
+ def pitchbendchange(ch, val)
224
+ e = REXML::Element.new('PitchBendChange', @doctr)
225
+ e.attributes['offset'] = @offset.to_s
226
+ e.attributes['ch'] = ch.to_s
227
+ e.attributes['val'] = val.to_s
228
+ end
229
+
230
+ def channelmodemessage(name, ch, val=nil)
231
+ e = REXML::Element.new(name, @doctr)
232
+ e.attributes['offset'] = @offset.to_s
233
+ e.attributes['ch'] = ch.to_s
234
+ e.attributes['val'] = val.to_s if val
235
+ end
236
+
237
+ private :channelmodemessage
238
+
239
+ def allsoundoff(ch) channelmodemessage('AllSoundOff', ch) end
240
+ def resetallcontrollers(ch) channelmodemessage('ResetAllControllers', ch) end
241
+ def localcontrol(ch, val) channelmodemessage('LocalControl', ch, val) end
242
+ def allnotesoff(ch) channelmodemessage('AllNotesOff', ch) end
243
+ def omnioff(ch) channelmodemessage('OmniOff', ch) end
244
+ def omnion(ch) channelmodemessage('OmniOn', ch) end
245
+ def monomode(ch, val) channelmodemessage('MonoMode', ch, val) end
246
+ def polymode(ch) channelmodemessage('PolyMode', ch) end
247
+
248
+ def put_binary(name, data)
249
+ e = REXML::Element.new(name, @doctr)
250
+ e.attributes['offset'] = @offset.to_s
251
+ s = ''
252
+ data.each_byte do |c|
253
+ s << format('\\%03o', c)
254
+ end
255
+ e.attributes['data'] = s
256
+ end
257
+
258
+ private :put_binary
259
+
260
+ def exclusivef0(data) put_binary('ExclusiveF0', data) end
261
+ def exclusivef7(data) put_binary('ExclusiveF7', data) end
262
+
263
+ def sequencenumber(num)
264
+ e = REXML::Element.new('SequenceNumber', @doctr)
265
+ e.attributes['offset'] = @offset.to_s
266
+ e.attributes['num'] = num.to_s
267
+ end
268
+
269
+ def text(name, text)
270
+ e = REXML::Element.new(name, @doctr)
271
+ e.attributes['offset'] = @offset.to_s
272
+ e.attributes['text'] = text.dump[1..-2]
273
+ end
274
+
275
+ private :text
276
+
277
+ def generalpurposetext(text) text('GeneralPurposeText', text) end
278
+ def copyrightnotice(text) text('CopyrightNotice', text) end
279
+ def trackname(text) text('TrackName', text) end
280
+ def instrumentname(text) text('InstrumentName', text) end
281
+ def lyric(text) text('Lyric', text) end
282
+ def marker(text) text('Marker', text) end
283
+ def cuepoint(text) text('CuePoint', text) end
284
+ def programname(text) text('ProgramName', text) end
285
+ def devicename(text) text('DeviceName', text) end
286
+ def text0a(text) text('Text0A', text) end
287
+ def text0b(text) text('Text0B', text) end
288
+ def text0c(text) text('Text0C', text) end
289
+ def text0d(text) text('Text0D', text) end
290
+ def text0e(text) text('Text0E', text) end
291
+ def text0f(text) text('Text0F', text) end
292
+
293
+ def channelprefix(ch)
294
+ e = REXML::Element.new('ChannelPrefix', @doctr)
295
+ e.attributes['offset'] = @offset.to_s
296
+ e.attributes['ch'] = ch.to_s
297
+ end
298
+
299
+ def midiport(num)
300
+ e = REXML::Element.new('MIDIPort', @doctr)
301
+ e.attributes['offset'] = @offset.to_s
302
+ e.attributes['num'] = num.to_s
303
+ end
304
+
305
+ def endoftrack
306
+ e = REXML::Element.new('EndOfTrack', @doctr)
307
+ e.attributes['offset'] = @offset.to_s
308
+ end
309
+
310
+ def settempo(tempo)
311
+ e = REXML::Element.new('SetTempo', @doctr)
312
+ e.attributes['offset'] = @offset.to_s
313
+ e.attributes['tempo'] = tempo.to_s
314
+ end
315
+
316
+ def smpteoffset(hr, mn, se, fr, ff, tc)
317
+ e = REXML::Element.new('SMPTEOffset', @doctr)
318
+ e.attributes['offset'] = @offset.to_s
319
+ e.attributes['hr'] = hr.to_s
320
+ e.attributes['mn'] = mn.to_s
321
+ e.attributes['se'] = se.to_s
322
+ e.attributes['fr'] = fr.to_s
323
+ e.attributes['ff'] = ff.to_s
324
+ e.attributes['tc'] = tc.to_s
325
+ end
326
+
327
+ def timesignature(nn, dd, cc, bb)
328
+ e = REXML::Element.new('TimeSignature', @doctr)
329
+ e.attributes['offset'] = @offset.to_s
330
+ e.attributes['nn'] = nn.to_s
331
+ e.attributes['dd'] = dd.to_s
332
+ e.attributes['cc'] = cc.to_s
333
+ e.attributes['bb'] = bb.to_s
334
+ end
335
+
336
+ def keysignature(sf, mi)
337
+ e = REXML::Element.new('KeySignature', @doctr)
338
+ e.attributes['offset'] = @offset.to_s
339
+ e.attributes['sf'] = sf.to_s
340
+ e.attributes['mi'] = mi.to_s
341
+ end
342
+
343
+ def sequencerspecific(data) put_binary('SequencerSpecific', data) end
344
+
345
+ unless defined? REXML::Formatters::Pretty
346
+
347
+ def result() @doc.to_s(0) end
348
+
349
+ else
350
+
351
+ def result
352
+ f = REXML::Formatters::Pretty.new(2)
353
+ f.write(@doc, r = "")
354
+ r
355
+ end
356
+
357
+ end
358
+
359
+ end
360
+
361
+ def encode_xml
362
+ self.class::WS.new(self, self.class::EncodeXML.new).read
363
+ end
364
+
365
+ def write_xml(io)
366
+ io.write(encode_xml)
367
+ end
368
+
369
+ def save_xml(fn)
370
+ open(fn, 'w') do |io|
371
+ write_xml(io)
372
+ end
373
+ end
374
+
375
+ end
376
+
377
+ end