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,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
|
data/lib/smf/toy/xml.rb
ADDED
@@ -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
|