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