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