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