smf 0.15.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/MANUAL +172 -0
  2. data/MANUAL.en +135 -0
  3. data/MANUAL.en.html +150 -0
  4. data/MANUAL.en.rd +144 -0
  5. data/MANUAL.html +201 -0
  6. data/MANUAL.rd +179 -0
  7. data/README +33 -0
  8. data/README.en +33 -0
  9. data/lib/smf.rb +736 -0
  10. data/lib/smf/divert.rb +21 -0
  11. data/lib/smf/io.rb +1278 -0
  12. data/lib/smf/toy/beatmap.rb +73 -0
  13. data/lib/smf/toy/gm.rb +327 -0
  14. data/lib/smf/toy/groove.rb +34 -0
  15. data/lib/smf/toy/macro.rb +282 -0
  16. data/lib/smf/toy/macro/mml.rb +34 -0
  17. data/lib/smf/toy/macro/mml/parser.rb +545 -0
  18. data/lib/smf/toy/macro/mml/parser.ry +239 -0
  19. data/lib/smf/toy/macro/stt.rb +33 -0
  20. data/lib/smf/toy/morse.rb +126 -0
  21. data/lib/smf/toy/quantize.rb +32 -0
  22. data/lib/smf/toy/rmi.rb +29 -0
  23. data/lib/smf/toy/searchsegment.rb +24 -0
  24. data/lib/smf/toy/shuffle.rb +39 -0
  25. data/lib/smf/toy/tempomap.rb +75 -0
  26. data/lib/smf/toy/text.rb +369 -0
  27. data/lib/smf/toy/velcomp.rb +42 -0
  28. data/lib/smf/toy/virtual.rb +118 -0
  29. data/lib/smf/toy/xml.rb +377 -0
  30. data/sample/Makefile +58 -0
  31. data/sample/bwv772.mid +0 -0
  32. data/sample/bwv772.mml +94 -0
  33. data/sample/bwv775.mid +0 -0
  34. data/sample/bwv775.mml +157 -0
  35. data/sample/bwv787.mid +0 -0
  36. data/sample/bwv787.mml +129 -0
  37. data/sample/groove.grv +33 -0
  38. data/sample/groove.rb +45 -0
  39. data/sample/ltvddpd2.mid +0 -0
  40. data/sample/ltvddpd2.stt +60 -0
  41. data/sample/merge.rb +38 -0
  42. data/sample/mml-samp.rb +19 -0
  43. data/sample/mml.rb +36 -0
  44. data/sample/morse-samp.rb +11 -0
  45. data/sample/morse.rb +31 -0
  46. data/sample/play-oss.rb +215 -0
  47. data/sample/play-oss2.rb +253 -0
  48. data/sample/play-oss3.rb +150 -0
  49. data/sample/play-spkr.rb +97 -0
  50. data/sample/play-win.rb +195 -0
  51. data/sample/quantize.rb +41 -0
  52. data/sample/rand1.rb +21 -0
  53. data/sample/rand2.rb +24 -0
  54. data/sample/rmi2smf.rb +26 -0
  55. data/sample/shuffle.rb +43 -0
  56. data/sample/smf2rmi.rb +26 -0
  57. data/sample/smf2smf.rb +26 -0
  58. data/sample/smf2text.rb +27 -0
  59. data/sample/smf2wav.rb +123 -0
  60. data/sample/smf2xml.rb +27 -0
  61. data/sample/split.rb +40 -0
  62. data/sample/stt-samp.rb +19 -0
  63. data/sample/stt.rb +36 -0
  64. data/sample/text2smf.rb +28 -0
  65. data/sample/velcomp.rb +45 -0
  66. data/sample/virtual-samp.rb +19 -0
  67. data/sample/xml2smf.rb +28 -0
  68. metadata +128 -0
@@ -0,0 +1,45 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # groove.rb: Written by Tadayoshi Funaba 2005,2006
4
+ # $Id: groove.rb,v 1.3 2006-11-10 21:57:06+09 tadf Exp $
5
+
6
+ require 'smf'
7
+ require 'smf/toy/groove'
8
+ require 'gopt'
9
+ include SMF
10
+
11
+ def usage
12
+ warn 'usage: groove [-o output] [-a amount] groove [input]'
13
+ exit 1
14
+ end
15
+
16
+ usage unless opt = Gopt.gopt('o:a:')
17
+ usage unless $*.size >= 1 && $*.size <= 2
18
+
19
+ pat = $*.shift
20
+
21
+ ifile = $*.shift
22
+ ifile = nil if ifile == '-'
23
+
24
+ ofile = opt[:o] if opt[:o]
25
+ ofile ||= File.basename(ifile, '.mid') + '-groove.mid' if ifile
26
+ ofile = nil if ofile == '-'
27
+
28
+ amount = (opt[:a] || '0.5').to_f
29
+
30
+ sq = unless ifile then Sequence.read($stdin) else Sequence.load(ifile) end
31
+
32
+ sp = IO.read(pat).scan(/\S+/).collect{|x| x.to_f}
33
+ gr = Groove.new(sq.division, sp)
34
+ gr.amount = amount
35
+
36
+ sq.each do |tr|
37
+ tr.pop
38
+ tr.each do |ev|
39
+ case ev
40
+ when NoteOff, NoteOn
41
+ gr.groove(ev)
42
+ end
43
+ end
44
+ end
45
+ unless ofile then sq.write($stdout) else sq.save(ofile) end
Binary file
@@ -0,0 +1,60 @@
1
+ "sq:Les trois valses distingu\351es du pr\351cieux d\351go\373t\351 \
2
+ II. Son binocle"
3
+
4
+ {
5
+ ti=1,4 te=240 gm=1
6
+
7
+ q r
8
+ }
9
+
10
+ {
11
+ ti=1,4 te=80 pr=0 co91=96 oc=4 du=1 ve=4/10
12
+
13
+ ��'��'���������饷���饷���饷��'��'����'��'����'��'����
14
+
15
+ ����'���������饽�����ե����������ե����������ե���������������������������
16
+
17
+ ��'�饷����'��'��'��'�����'��
18
+
19
+ �åå�,�ɡ��ߡ��ɡ��ߡ��ɡ��ߡ���
20
+
21
+ �ååߥ쥽�ߥ쥽�ߥ졼
22
+
23
+ ��'��'���������饷���饷���� te*=15/16 ve*=2/3
24
+ �ե���'��������& ��'��������& �ɡ�''��������& �ե���''��������
25
+ }&
26
+
27
+ {
28
+ oc=3 du=1 ve=3/10
29
+
30
+ ��
31
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
32
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
33
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
34
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
35
+
36
+ �� ����& ���'�� �� ����& ��'��
37
+ �� ����& ���'�� �� ����& ��'��
38
+ �� ����& ���'�� �� ����& ��'��
39
+ �� ����& ���'�� �� ����& ��'��
40
+
41
+ �ե� ��'��& ��'�� ���� ��'��& �ե�'��
42
+ �ե� ��'��& ��'�� ���� ��'��& �ե�'��
43
+
44
+ {ve*=8/10 ��, �ߡ�& ������ �� �ߡ�& �顼
45
+ ��, �ߡ�& ������ �� �ߡ�& �顼}
46
+
47
+ �ե�, �ɡ�& �ߡ� ����, �ɡ�& �ե���
48
+ �ե�, �ɡ�& �ߡ� ����, �ɡ�& �ե���
49
+
50
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
51
+ �� ��'��& �ե���'�� ��' ��'��& ��'��
52
+
53
+ ve*=2/3 ��'��������
54
+ }
55
+
56
+ {
57
+ ti=1,4 te=240
58
+
59
+ q r
60
+ }
@@ -0,0 +1,38 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # merge.rb: Written by Tadayoshi Funaba 1999-2006
4
+ # $Id: merge.rb,v 1.10 2006-11-10 21:57:06+09 tadf Exp $
5
+
6
+ require 'smf'
7
+ require 'smf/divert'
8
+ require 'gopt'
9
+ include SMF
10
+
11
+ def usage
12
+ warn 'usage: merge [-o output] [input]'
13
+ exit 1
14
+ end
15
+
16
+ usage unless opt = Gopt.gopt('o:')
17
+ usage unless $*.size >= 0 && $*.size <= 1
18
+
19
+ ifile = $*.shift
20
+ ifile = nil if ifile == '-'
21
+
22
+ ofile = opt[:o] if opt[:o]
23
+ ofile ||= File.basename(ifile, '.mid') + '-merge.mid' if ifile
24
+ ofile = nil if ofile == '-'
25
+
26
+ sq = unless ifile then Sequence.read($stdin) else Sequence.load(ifile) end
27
+ nsq = Sequence.new(0, sq.division, sq.tc)
28
+ eot = []
29
+ sq.each do |tr|
30
+ tr.divert(nsq) do |ev|
31
+ case ev
32
+ when EndOfTrack; eot << ev; nil
33
+ else; 0
34
+ end
35
+ end
36
+ end
37
+ nsq[0] << eot.max unless eot.empty?
38
+ unless ofile then nsq.write($stdout) else nsq.save(ofile) end
@@ -0,0 +1,19 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # mml-samp.rb: Written by Tadayoshi Funaba 2005
4
+ # $Id: mml-samp.rb,v 1.1 2005-07-17 17:16:18+09 tadf Exp $
5
+
6
+ require 'smf/toy/macro/mml'
7
+ include SMF
8
+
9
+ sq = Sequence.new
10
+ mm = MML.new(sq)
11
+ mm << 'gm=1 r ch=0 pr=0'
12
+ 12.times do
13
+ mm << "{q c# h c# q r}&"
14
+ mm << "{q d# h d# q r}&"
15
+ mm << "{q a h a q r}"
16
+ mm << "oc += 1/12"
17
+ end
18
+ mm.generate
19
+ sq.save('mml-samp.mid')
@@ -0,0 +1,36 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # mml.rb: Written by Tadayoshi Funaba 1999-2006
4
+ # $Id: mml.rb,v 1.4 2006-11-10 21:57:06+09 tadf Exp $
5
+
6
+ require 'smf/toy/macro/mml'
7
+ require 'gopt'
8
+ include SMF
9
+
10
+ def usage
11
+ warn 'usage: mml [-o output] [-e command] [input]'
12
+ exit 1
13
+ end
14
+
15
+ usage unless opt = Gopt.gopt('o:e:')
16
+ usage unless $*.size >= 0 && $*.size <= 1
17
+
18
+ ifile = $*.shift
19
+ ifile = nil if ifile == '-'
20
+
21
+ ofile = opt[:o] if opt[:o]
22
+ ofile ||= File.basename(ifile, '.mml') + '.mid' if ifile
23
+ ofile = nil if ofile == '-'
24
+
25
+ so = opt[:e] if opt[:e]
26
+ so ||= unless ifile then $stdin.read else IO.read(ifile) end
27
+ sq = Sequence.new(1, 480)
28
+ mm = MML.new(sq)
29
+ mm << so
30
+ begin
31
+ mm.generate
32
+ rescue ParseError
33
+ warn format('%s: %s', (opt[:e] && '-e') || ifile || '(stdin)', $!)
34
+ exit 1
35
+ end
36
+ unless ofile then sq.write($stdout) else sq.save(ofile) end
@@ -0,0 +1,11 @@
1
+ # morse-samp.rb: Written by Tadayoshi Funaba 2005
2
+ # $Id: morse-samp.rb,v 1.2 2005-07-17 17:16:18+09 tadf Exp $
3
+
4
+ require 'smf/toy/morse'
5
+ include SMF
6
+
7
+ sq = Sequence.new
8
+ mo = Morse.new(sq)
9
+ mo << 'hello world'
10
+ mo.generate
11
+ sq.save('morse-samp.mid')
@@ -0,0 +1,31 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # morse.rb: Written by Tadayoshi Funaba 2005,2006
4
+ # $Id
5
+
6
+ require 'smf/toy/morse'
7
+ require 'gopt'
8
+ include SMF
9
+
10
+ def usage
11
+ warn 'usage: morse [-o output] [-e message] [input]'
12
+ exit 1
13
+ end
14
+
15
+ usage unless opt = Gopt.gopt('o:e:')
16
+ usage unless $*.size >= 0 && $*.size <= 1
17
+
18
+ ifile = $*.shift
19
+ ifile = nil if ifile == '-'
20
+
21
+ ofile = opt[:o] if opt[:o]
22
+ ofile ||= File.basename(ifile, '.txt') + '.mid' if ifile
23
+ ofile = nil if ofile == '-'
24
+
25
+ so = opt[:e] if opt[:e]
26
+ so ||= unless ifile then $stdin.read else IO.read(ifile) end
27
+ sq = Sequence.new
28
+ mo = Morse.new(sq)
29
+ mo << so
30
+ mo.generate
31
+ unless ofile then sq.write($stdout) else sq.save(ofile) end
@@ -0,0 +1,215 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # play-oss.rb: Written by Tadayoshi Funaba 1999-2006
4
+ # $Id: play-oss.rb,v 1.23 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 DevSeq < File
14
+
15
+ def putbuf(s)
16
+ @buf ||= ''
17
+ if @buf.size > 4096
18
+ dumpbuf
19
+ end
20
+ @buf << s
21
+ end
22
+
23
+ def dumpbuf
24
+ syswrite(@buf)
25
+ @buf = ''
26
+ end
27
+
28
+ EV_TIMING = 0x81
29
+
30
+ def timer_event(ev, parm)
31
+ putbuf([EV_TIMING, ev, 0, 0, parm].pack('C4I'))
32
+ end
33
+
34
+ private :timer_event
35
+
36
+ TMR_START = 4
37
+ TMR_STOP = 3
38
+ TMR_WAIT_ABS = 2
39
+
40
+ def start_timer() timer_event(TMR_START, 0) end
41
+ def stop_timer() timer_event(TMR_STOP, 0) end
42
+ def wait_time(ticks) timer_event(TMR_WAIT_ABS, ticks) end
43
+
44
+ SEQ_MIDIPUTC = 5
45
+
46
+ def midiout(device, byte)
47
+ putbuf([SEQ_MIDIPUTC, byte, device, 0].pack('C4'))
48
+ end
49
+
50
+ case RUBY_PLATFORM
51
+ when /freebsd/
52
+ SNDCTL_SEQ_CTRLRATE = 0xc0045103
53
+ SNDCTL_SEQ_NRMIDIS = 0x4004510b
54
+ SNDCTL_MIDI_INFO = 0xc074510c
55
+ when /linux/
56
+ SNDCTL_SEQ_CTRLRATE = 0xc0045103
57
+ SNDCTL_SEQ_NRMIDIS = 0x8004510b
58
+ SNDCTL_MIDI_INFO = 0xc074510c
59
+ else
60
+ raise 'unknown system'
61
+ end
62
+
63
+ def ctrlrate
64
+ n = [0].pack('i')
65
+ ioctl(SNDCTL_SEQ_CTRLRATE, n)
66
+ n.unpack('i')[0]
67
+ end
68
+
69
+ def nrmidis
70
+ n = [0].pack('i')
71
+ ioctl(SNDCTL_SEQ_NRMIDIS, n)
72
+ n.unpack('i')[0]
73
+ end
74
+
75
+ def midi_info(dev)
76
+ templ = 'A30x2iLix72'
77
+ a = [0] * 22
78
+ a[0] = ''
79
+ a[1] = dev
80
+ n = a.pack(templ)
81
+ ioctl(SNDCTL_MIDI_INFO, n)
82
+ n.unpack(templ)
83
+ end
84
+
85
+ end
86
+
87
+ class Sequence
88
+
89
+ class Play < XSCallback
90
+
91
+ def initialize(tm, num) @tm, @num = tm, num end
92
+
93
+ def header(format, ntrks, division, tc)
94
+ @sq = DevSeq.open('/dev/sequencer', 'w')
95
+ puts(@sq.midi_info(@num)[0]) if $VERBOSE
96
+ unless @num < @sq.nrmidis
97
+ raise 'device not available'
98
+ end
99
+ @ctrlrate = @sq.ctrlrate
100
+ end
101
+
102
+ def track_start() @offset = 0 end
103
+
104
+ def delta(delta)
105
+ @start_timer ||= (@sq.start_timer; true)
106
+ if delta.nonzero?
107
+ @offset += delta
108
+ e = @tm.offset2elapse(@offset)
109
+ @sq.wait_time((e * @ctrlrate).to_i)
110
+ end
111
+ end
112
+
113
+ def noteoff(ch, note, vel)
114
+ @sq.midiout(@num, ch | 0x80)
115
+ @sq.midiout(@num, note)
116
+ @sq.midiout(@num, vel)
117
+ end
118
+
119
+ def noteon(ch, note, vel)
120
+ @sq.midiout(@num, ch | 0x90)
121
+ @sq.midiout(@num, note)
122
+ @sq.midiout(@num, vel)
123
+ end
124
+
125
+ def polyphonickeypressure(ch, note, val)
126
+ @sq.midiout(@num, ch | 0xa0)
127
+ @sq.midiout(@num, note)
128
+ @sq.midiout(@num, val)
129
+ end
130
+
131
+ def controlchange(ch, num, val)
132
+ @sq.midiout(@num, ch | 0xb0)
133
+ @sq.midiout(@num, num)
134
+ @sq.midiout(@num, val)
135
+ end
136
+
137
+ def programchange(ch, num)
138
+ @sq.midiout(@num, ch | 0xc0)
139
+ @sq.midiout(@num, num)
140
+ end
141
+
142
+ def channelpressure(ch, val)
143
+ @sq.midiout(@num, ch | 0xd0)
144
+ @sq.midiout(@num, val)
145
+ end
146
+
147
+ def pitchbendchange(ch, val)
148
+ @sq.midiout(@num, ch | 0xe0)
149
+ val += 0x2000
150
+ lsb = val & 0x7f
151
+ msb = (val >> 7) & 0x7f
152
+ @sq.midiout(@num, lsb)
153
+ @sq.midiout(@num, msb)
154
+ end
155
+
156
+ def channelmodemessage(ch, num, val) controlchange(ch, num, val) end
157
+
158
+ private :channelmodemessage
159
+
160
+ def allsoundoff(ch) channelmodemessage(ch, 0x78, 0) end
161
+ def resetallcontrollers(ch) channelmodemessage(ch, 0x79, 0) end
162
+ def localcontrol(ch, val) channelmodemessage(ch, 0x7a, val) end
163
+ def allnotesoff(ch) channelmodemessage(ch, 0x7b, 0) end
164
+ def omnioff(ch) channelmodemessage(ch, 0x7c, 0) end
165
+ def omnion(ch) channelmodemessage(ch, 0x7d, 0) end
166
+ def monomode(ch, val) channelmodemessage(ch, 0x7e, val) end
167
+ def polymode(ch) channelmodemessage(ch, 0x7f, 0) end
168
+
169
+ def exclusivefx(data)
170
+ data.each_byte do |x|
171
+ @sq.midiout(@num, x)
172
+ end
173
+ end
174
+
175
+ private :exclusivefx
176
+
177
+ def exclusivef0(data)
178
+ @sq.midiout(@num, 0xf0)
179
+ exclusivefx(data)
180
+ end
181
+
182
+ def exclusivef7(data) exclusivefx(data) end
183
+
184
+ def result
185
+ @sq.dumpbuf
186
+ @sq.stop_timer
187
+ @sq.close
188
+ end
189
+
190
+ end
191
+
192
+ def play(num=0)
193
+ j = join
194
+ tm = TempoMap.new(j)
195
+ WS.new(j, Play.new(tm, num)).read
196
+ end
197
+
198
+ end
199
+
200
+ end
201
+
202
+ def usage
203
+ warn 'usage: play-oss [-d num] [input]'
204
+ exit 1
205
+ end
206
+
207
+ usage unless opt = Gopt.gopt('d:')
208
+ usage unless $*.size >= 0 && $*.size <= 1
209
+ file = $*.shift
210
+ file = nil if file == '-'
211
+
212
+ num = (opt[:d] || '0').to_i
213
+
214
+ sq = unless file then Sequence.read($stdin) else Sequence.load(file) end
215
+ sq.play(num)