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
data/sample/play-oss2.rb
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
# play-oss2.rb: Written by Tadayoshi Funaba 1999-2006
|
4
|
+
# $Id: play-oss2.rb,v 1.4 2006-11-10 21:57:06+09 tadf Exp $
|
5
|
+
|
6
|
+
require 'smf'
|
7
|
+
require 'gopt'
|
8
|
+
include SMF
|
9
|
+
|
10
|
+
module SMF
|
11
|
+
|
12
|
+
class DevSeq < File
|
13
|
+
|
14
|
+
def putbuf(s)
|
15
|
+
@buf ||= ''
|
16
|
+
if @buf.size > 4096
|
17
|
+
dumpbuf
|
18
|
+
end
|
19
|
+
@buf << s
|
20
|
+
end
|
21
|
+
|
22
|
+
def dumpbuf
|
23
|
+
syswrite(@buf)
|
24
|
+
@buf = ''
|
25
|
+
end
|
26
|
+
|
27
|
+
EV_TIMING = 0x81
|
28
|
+
|
29
|
+
def timer_event(ev, parm)
|
30
|
+
putbuf([EV_TIMING, ev, 0, 0, parm].pack('C4I'))
|
31
|
+
end
|
32
|
+
|
33
|
+
private :timer_event
|
34
|
+
|
35
|
+
TMR_START = 4
|
36
|
+
TMR_STOP = 3
|
37
|
+
TMR_WAIT_ABS = 2
|
38
|
+
TMR_TEMPO = 6
|
39
|
+
TMR_TIMESIG = 11
|
40
|
+
|
41
|
+
def start_timer() timer_event(TMR_START, 0) end
|
42
|
+
def stop_timer() timer_event(TMR_STOP, 0) end
|
43
|
+
def wait_time(ticks) timer_event(TMR_WAIT_ABS, ticks) end
|
44
|
+
def settempo(value) timer_event(TMR_TEMPO, value) end
|
45
|
+
def timesignature(sig) timer_event(TMR_TIMESIG, sig) end
|
46
|
+
|
47
|
+
EV_CHN_COMMON = 0x92
|
48
|
+
EV_CHN_VOICE = 0x93
|
49
|
+
EV_SYSEX = 0x94
|
50
|
+
|
51
|
+
def chn_voice(dev, event, chn, note, parm)
|
52
|
+
putbuf([EV_CHN_VOICE, dev, event, chn, note, parm, 0, 0].pack('C8'))
|
53
|
+
end
|
54
|
+
|
55
|
+
def chn_common(dev, event, chn, p1, p2, w14)
|
56
|
+
putbuf([EV_CHN_COMMON, dev, event, chn, p1, p2, w14].pack('C6s'))
|
57
|
+
end
|
58
|
+
|
59
|
+
def sysex(dev, buf, len)
|
60
|
+
buf2 = buf
|
61
|
+
if len < 6
|
62
|
+
buf2 = buf2 + "\xff" * 6
|
63
|
+
end
|
64
|
+
putbuf([EV_SYSEX, dev].pack('C2') + buf2[0,6])
|
65
|
+
end
|
66
|
+
|
67
|
+
private :chn_voice, :chn_common
|
68
|
+
|
69
|
+
MIDI_NOTEOFF = 0x80
|
70
|
+
MIDI_NOTEON = 0x90
|
71
|
+
MIDI_KEY_PRESSURE = 0xa0
|
72
|
+
MIDI_CTL_CHANGE = 0xb0
|
73
|
+
MIDI_PGM_CHANGE = 0xc0
|
74
|
+
MIDI_CHN_PRESSURE = 0xd0
|
75
|
+
MIDI_PITCH_BEND = 0xe0
|
76
|
+
|
77
|
+
def noteoff(dev, ch, note, vel)
|
78
|
+
chn_voice(dev, MIDI_NOTEOFF, ch, note, vel)
|
79
|
+
end
|
80
|
+
|
81
|
+
def noteon(dev, ch, note, vel)
|
82
|
+
chn_voice(dev, MIDI_NOTEON, ch, note, vel)
|
83
|
+
end
|
84
|
+
|
85
|
+
def polyphonickeypressure(dev, ch, note, val)
|
86
|
+
chn_voice(dev, MIDI_KEY_PRESSURE, ch, note, val)
|
87
|
+
end
|
88
|
+
|
89
|
+
def controlchange(dev, ch, num, val)
|
90
|
+
chn_common(dev, MIDI_CTL_CHANGE, ch, num, 0, val)
|
91
|
+
end
|
92
|
+
|
93
|
+
def programchange(dev, ch, num)
|
94
|
+
chn_common(dev, MIDI_PGM_CHANGE, ch, num, 0, 0)
|
95
|
+
end
|
96
|
+
|
97
|
+
def channelpressure(dev, ch, val)
|
98
|
+
chn_common(dev, MIDI_CHN_PRESSURE, ch, val, 0, 0)
|
99
|
+
end
|
100
|
+
|
101
|
+
def pitchbendchange(dev, ch, val)
|
102
|
+
chn_common(dev, MIDI_PITCH_BEND, ch, 0, 0, val)
|
103
|
+
end
|
104
|
+
|
105
|
+
case RUBY_PLATFORM
|
106
|
+
when /freebsd/
|
107
|
+
SNDCTL_SEQ_NRSYNTHS = 0x4004510a
|
108
|
+
SNDCTL_SYNTH_INFO = 0xc08c5102
|
109
|
+
SNDCTL_TMR_TIMEBASE = 0xc0045401
|
110
|
+
SNDCTL_TMR_TEMPO = 0xc0045405
|
111
|
+
when /linux/
|
112
|
+
SNDCTL_SEQ_NRSYNTHS = 0x8004510a
|
113
|
+
SNDCTL_SYNTH_INFO = 0xc08c5102
|
114
|
+
SNDCTL_TMR_TIMEBASE = 0xc0045401
|
115
|
+
SNDCTL_TMR_TEMPO = 0xc0045405
|
116
|
+
else
|
117
|
+
raise 'unknown system'
|
118
|
+
end
|
119
|
+
|
120
|
+
def nrsynths
|
121
|
+
n = [0].pack('i')
|
122
|
+
ioctl(SNDCTL_SEQ_NRSYNTHS, n)
|
123
|
+
n.unpack('i')[0]
|
124
|
+
end
|
125
|
+
|
126
|
+
def synth_info(dev)
|
127
|
+
templ = 'A30x2i7Lix76'
|
128
|
+
a = [0] * 28
|
129
|
+
a[0] = ''
|
130
|
+
a[1] = dev
|
131
|
+
n = a.pack(templ)
|
132
|
+
ioctl(SNDCTL_SYNTH_INFO, n)
|
133
|
+
n.unpack(templ)
|
134
|
+
end
|
135
|
+
|
136
|
+
def timebase(div)
|
137
|
+
n = [div].pack('i')
|
138
|
+
ioctl(SNDCTL_TMR_TIMEBASE, n)
|
139
|
+
n.unpack('i')[0]
|
140
|
+
end
|
141
|
+
|
142
|
+
def tempo(tempo)
|
143
|
+
n = [tempo].pack('i')
|
144
|
+
ioctl(SNDCTL_TMR_TEMPO, n)
|
145
|
+
n.unpack('i')[0]
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
class Sequence
|
151
|
+
|
152
|
+
class Play < XSCallback
|
153
|
+
|
154
|
+
def initialize(num) @num = num end
|
155
|
+
|
156
|
+
def header(format, ntrks, division, tc)
|
157
|
+
@sq = DevSeq.open('/dev/sequencer2', 'w')
|
158
|
+
puts(@sq.synth_info(@num)[0]) if $VERBOSE
|
159
|
+
unless @num < @sq.nrsynths
|
160
|
+
raise 'device not available'
|
161
|
+
end
|
162
|
+
@sq.timebase(division)
|
163
|
+
@sq.tempo(120)
|
164
|
+
end
|
165
|
+
|
166
|
+
def track_start() @offset = 0 end
|
167
|
+
|
168
|
+
def delta(delta)
|
169
|
+
@start_timer ||= (@sq.start_timer; true)
|
170
|
+
prev = @offset
|
171
|
+
@offset += delta
|
172
|
+
if @offset > prev
|
173
|
+
@sq.wait_time(@offset)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def noteoff(ch, note, vel) @sq.noteoff(@num, ch, note, vel) end
|
178
|
+
def noteon(ch, note, vel) @sq.noteon(@num, ch, note, vel) end
|
179
|
+
|
180
|
+
def polyphonickeypressure(ch, note, val)
|
181
|
+
@sq.polyphonickeypressure(@num, ch, note, val)
|
182
|
+
end
|
183
|
+
|
184
|
+
def controlchange(ch, num, val) @sq.controlchange(@num, ch, num, val) end
|
185
|
+
def programchange(ch, num) @sq.programchange(@num, ch, num) end
|
186
|
+
def channelpressure(ch, val) @sq.channelpressure(@num, ch, val) end
|
187
|
+
|
188
|
+
def pitchbendchange(ch, val)
|
189
|
+
val += 0x2000
|
190
|
+
@sq.pitchbendchange(@num, ch, val)
|
191
|
+
end
|
192
|
+
|
193
|
+
def channelmodemessage(ch, num, val) controlchange(ch, num, val) end
|
194
|
+
|
195
|
+
private :channelmodemessage
|
196
|
+
|
197
|
+
def allsoundoff(ch) channelmodemessage(ch, 0x78, 0) end
|
198
|
+
def resetallcontrollers(ch) channelmodemessage(ch, 0x79, 0) end
|
199
|
+
def localcontrol(ch, val) channelmodemessage(ch, 0x7a, val) end
|
200
|
+
def allnotesoff(ch) channelmodemessage(ch, 0x7b, 0) end
|
201
|
+
def omnioff(ch) channelmodemessage(ch, 0x7c, 0) end
|
202
|
+
def omnion(ch) channelmodemessage(ch, 0x7d, 0) end
|
203
|
+
def monomode(ch, val) channelmodemessage(ch, 0x7e, val) end
|
204
|
+
def polymode(ch) channelmodemessage(ch, 0x7f, 0) end
|
205
|
+
|
206
|
+
def exclusivefx(data)
|
207
|
+
i = 0
|
208
|
+
while i < data.size
|
209
|
+
len = data.size - i
|
210
|
+
len = 6 if len > 6
|
211
|
+
@sq.sysex(@num, data[i,6], len)
|
212
|
+
i += 6
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
private :exclusivefx
|
217
|
+
|
218
|
+
def exclusivef0(data) exclusivefx("\xf0" + data) end
|
219
|
+
def exclusivef7(data) exclusivefx(data) end
|
220
|
+
def settempo(tempo) @sq.settempo(60000000 / tempo) end
|
221
|
+
|
222
|
+
def timesignature(nn, dd, cc, bb)
|
223
|
+
@sq.timesignature(nn << 24 | dd << 16 | cc << 8 | bb)
|
224
|
+
end
|
225
|
+
|
226
|
+
def result
|
227
|
+
@sq.dumpbuf
|
228
|
+
@sq.stop_timer
|
229
|
+
@sq.close
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
def play(num=0) WS.new(join, Play.new(num)).read end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
def usage
|
241
|
+
warn 'usage: play-oss2 [-d num] [input]'
|
242
|
+
exit 1
|
243
|
+
end
|
244
|
+
|
245
|
+
usage unless opt = Gopt.gopt('d:')
|
246
|
+
usage unless $*.size >= 0 && $*.size <= 1
|
247
|
+
file = $*.shift
|
248
|
+
file = nil if file == '-'
|
249
|
+
|
250
|
+
num = (opt[:d] || '0').to_i
|
251
|
+
|
252
|
+
sq = unless file then Sequence.read($stdin) else Sequence.load(file) end
|
253
|
+
sq.play(num)
|
data/sample/play-oss3.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
# play-oss3.rb: Written by Tadayoshi Funaba 1999-2006
|
4
|
+
# $Id: play-oss3.rb,v 1.4 2006-11-10 21:57:06+09 tadf Exp $
|
5
|
+
|
6
|
+
require 'smf'
|
7
|
+
require 'smf/toy/tempomap'
|
8
|
+
require 'gopt'
|
9
|
+
include SMF
|
10
|
+
|
11
|
+
module SMF
|
12
|
+
|
13
|
+
class Sequence
|
14
|
+
|
15
|
+
class Timer
|
16
|
+
|
17
|
+
def initialize() @start = Time.now end
|
18
|
+
def elapse() Time.now - @start end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class Play < XSCallback
|
23
|
+
|
24
|
+
def initialize(tm, num) @tm, @num = tm, num end
|
25
|
+
|
26
|
+
def header(format, ntrks, division, tc)
|
27
|
+
@mo = open("/dev/midi%02d" % @num, 'w')
|
28
|
+
end
|
29
|
+
|
30
|
+
def track_start() @offset = 0 end
|
31
|
+
|
32
|
+
def delta(delta)
|
33
|
+
@timer ||= Timer.new
|
34
|
+
if delta.nonzero?
|
35
|
+
@offset += delta
|
36
|
+
e = @tm.offset2elapse(@offset) - @timer.elapse
|
37
|
+
if e > 0
|
38
|
+
sleep(e.to_f)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def noteoff(ch, note, vel)
|
44
|
+
@mo.putc(ch | 0x80)
|
45
|
+
@mo.putc(note)
|
46
|
+
@mo.putc(vel)
|
47
|
+
@mo.flush
|
48
|
+
end
|
49
|
+
|
50
|
+
def noteon(ch, note, vel)
|
51
|
+
@mo.putc(ch | 0x90)
|
52
|
+
@mo.putc(note)
|
53
|
+
@mo.putc(vel)
|
54
|
+
@mo.flush
|
55
|
+
end
|
56
|
+
|
57
|
+
def polyphonickeypressure(ch, note, val)
|
58
|
+
@mo.putc(ch | 0xa0)
|
59
|
+
@mo.putc(note)
|
60
|
+
@mo.putc(val)
|
61
|
+
@mo.flush
|
62
|
+
end
|
63
|
+
|
64
|
+
def controlchange(ch, num, val)
|
65
|
+
@mo.putc(ch | 0xb0)
|
66
|
+
@mo.putc(num)
|
67
|
+
@mo.putc(val)
|
68
|
+
@mo.flush
|
69
|
+
end
|
70
|
+
|
71
|
+
def programchange(ch, num)
|
72
|
+
@mo.putc(ch | 0xc0)
|
73
|
+
@mo.putc(num)
|
74
|
+
@mo.flush
|
75
|
+
end
|
76
|
+
|
77
|
+
def channelpressure(ch, val)
|
78
|
+
@mo.putc(ch | 0xd0)
|
79
|
+
@mo.putc(val)
|
80
|
+
@mo.flush
|
81
|
+
end
|
82
|
+
|
83
|
+
def pitchbendchange(ch, val)
|
84
|
+
@mo.putc(ch | 0xe0)
|
85
|
+
val += 0x2000
|
86
|
+
lsb = val & 0x7f
|
87
|
+
msb = (val >> 7) & 0x7f
|
88
|
+
@mo.putc(lsb)
|
89
|
+
@mo.putc(msb)
|
90
|
+
@mo.flush
|
91
|
+
end
|
92
|
+
|
93
|
+
def channelmodemessage(ch, num, val) controlchange(ch, num, val) end
|
94
|
+
|
95
|
+
private :channelmodemessage
|
96
|
+
|
97
|
+
def allsoundoff(ch) channelmodemessage(ch, 0x78, 0) end
|
98
|
+
def resetallcontrollers(ch) channelmodemessage(ch, 0x79, 0) end
|
99
|
+
def localcontrol(ch, val) channelmodemessage(ch, 0x7a, val) end
|
100
|
+
def allnotesoff(ch) channelmodemessage(ch, 0x7b, 0) end
|
101
|
+
def omnioff(ch) channelmodemessage(ch, 0x7c, 0) end
|
102
|
+
def omnion(ch) channelmodemessage(ch, 0x7d, 0) end
|
103
|
+
def monomode(ch, val) channelmodemessage(ch, 0x7e, val) end
|
104
|
+
def polymode(ch) channelmodemessage(ch, 0x7f, 0) end
|
105
|
+
|
106
|
+
def exclusivefx(data)
|
107
|
+
data.each_byte do |x|
|
108
|
+
@mo.putc(x)
|
109
|
+
end
|
110
|
+
@mo.flush
|
111
|
+
end
|
112
|
+
|
113
|
+
private :exclusivefx
|
114
|
+
|
115
|
+
def exclusivef0(data)
|
116
|
+
@mo.putc(0xf0)
|
117
|
+
exclusivefx(data)
|
118
|
+
@mo.flush
|
119
|
+
end
|
120
|
+
|
121
|
+
def exclusivef7(data) exclusivefx(data) end
|
122
|
+
|
123
|
+
def result() @mo.close end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
def play(num=0)
|
128
|
+
j = join
|
129
|
+
tm = TempoMap.new(j)
|
130
|
+
WS.new(j, Play.new(tm, num)).read
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
def usage
|
138
|
+
warn 'usage: play-oss3 [-d num] [input]'
|
139
|
+
exit 1
|
140
|
+
end
|
141
|
+
|
142
|
+
usage unless opt = Gopt.gopt('d:')
|
143
|
+
usage unless $*.size >= 0 && $*.size <= 1
|
144
|
+
file = $*.shift
|
145
|
+
file = nil if file == '-'
|
146
|
+
|
147
|
+
num = (opt[:d] || '0').to_i
|
148
|
+
|
149
|
+
sq = unless file then Sequence.read($stdin) else Sequence.load(file) end
|
150
|
+
sq.play(num)
|
data/sample/play-spkr.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
# play-spkr.rb: Written by Tadayoshi Funaba 2005,2006
|
4
|
+
# $Id: play-spkr.rb,v 1.4 2006-11-10 21:57:06+09 tadf Exp $
|
5
|
+
|
6
|
+
require 'smf'
|
7
|
+
require 'smf/toy/tempomap'
|
8
|
+
require 'gopt'
|
9
|
+
include SMF
|
10
|
+
|
11
|
+
module SMF
|
12
|
+
|
13
|
+
class DevSpkr < File
|
14
|
+
|
15
|
+
case RUBY_PLATFORM
|
16
|
+
when /freebsd/
|
17
|
+
SPKRTONE = 0x80085301
|
18
|
+
else
|
19
|
+
raise 'unknown system'
|
20
|
+
end
|
21
|
+
|
22
|
+
def emit_tone(freq, duration)
|
23
|
+
ioctl(SPKRTONE, [freq, duration].pack('i*'))
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class Sequence
|
29
|
+
|
30
|
+
class PlaySpkr < XSCallback
|
31
|
+
|
32
|
+
FREQ = []
|
33
|
+
(0..127).each do |n|
|
34
|
+
FREQ << 440 * 2**((n-69.0)/12)
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(tm) @tm = tm end
|
38
|
+
|
39
|
+
def header(format, ntrks, division, tc)
|
40
|
+
@sp = DevSpkr.open('/dev/speaker', 'w')
|
41
|
+
end
|
42
|
+
|
43
|
+
def track_start
|
44
|
+
@loffset = 0
|
45
|
+
@offset = 0
|
46
|
+
@noteon = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def delta(delta) @offset += delta end
|
50
|
+
|
51
|
+
def noteoff(ch, note, vel)
|
52
|
+
return if ch == 9 # GM perc.
|
53
|
+
if @noteon && @noteon[0] == note
|
54
|
+
start = @noteon[1]
|
55
|
+
@noteon = nil
|
56
|
+
if start > @loffset
|
57
|
+
s = @tm.offset2elapse(@loffset)
|
58
|
+
e = @tm.offset2elapse(start)
|
59
|
+
@sp.emit_tone(0, ((e - s) * 100).round)
|
60
|
+
end
|
61
|
+
s = @tm.offset2elapse(start)
|
62
|
+
e = @tm.offset2elapse(@offset)
|
63
|
+
@sp.emit_tone(FREQ[note], ((e - s) * 100).round)
|
64
|
+
@loffset = @offset
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def noteon(ch, note, vel)
|
69
|
+
return if ch == 9 # GM perc.
|
70
|
+
@noteon ||= [note, @offset]
|
71
|
+
end
|
72
|
+
|
73
|
+
def result() @sp.close end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def play
|
78
|
+
j = join
|
79
|
+
tm = TempoMap.new(j)
|
80
|
+
WS.new(j, PlaySpkr.new(tm)).read
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def usage
|
88
|
+
warn 'usage: play-spkr [input]'
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
usage unless $*.size >= 0 && $*.size <= 1
|
93
|
+
file = $*.shift
|
94
|
+
file = nil if file == '-'
|
95
|
+
|
96
|
+
sq = unless file then Sequence.read($stdin) else Sequence.load(file) end
|
97
|
+
sq.play
|