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