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,239 @@
1
+ # parser.ry: Written by Tadayoshi Funaba 1999-2005,2008
2
+ # $Id: parser.ry,v 1.3 2008-02-16 16:56:21+09 tadf Exp $
3
+
4
+ class SMF::MMLParser
5
+
6
+ prechigh
7
+ nonassoc UMINUS
8
+ left '*' '/'
9
+ left '+' '-'
10
+ preclow
11
+
12
+ rule
13
+
14
+ prog : list { result = val[0] } ;
15
+
16
+ list : { result = [:list, []] }
17
+ | list stmt { val[0][1] << val[1]; result = val[0] }
18
+ ;
19
+
20
+ stmt : expr { result = [:stmt, val[0]] }
21
+ | expr '&' { result = [:stmt, val[0], val[1]] }
22
+ ;
23
+
24
+ expr : step { result = [:step, val[0]] }
25
+ | note | text | asgn
26
+ | '{' list '}' { result = val[1] }
27
+ ;
28
+
29
+ note : NOTE { result = [:note, val[0]] } ;
30
+ text : TEXT { result = [:text, val[0]] } ;
31
+
32
+ asgn : VAR AOP num
33
+ { result = [:asgn, val[0], val[1], val[2]] }
34
+ | VAR AOP num ',' num
35
+ { result = [:asgn, val[0], val[1], val[2], val[4]] }
36
+ ;
37
+
38
+ step : step '+' step { result = [:add, val[0], val[2]] }
39
+ | step '-' step { result = [:sub, val[0], val[2]] }
40
+ | step '*' num { result = [:mul, val[0], val[2]] }
41
+ | step '/' num { result = [:div, val[0], val[2]] }
42
+ | '(' step ')' { result = val[1] }
43
+ | STEP { result = [:imm, val[0]] }
44
+ ;
45
+
46
+ num : num '+' num { result = [:add, val[0], val[2]] }
47
+ | num '-' num { result = [:sub, val[0], val[2]] }
48
+ | num '*' num { result = [:mul, val[0], val[2]] }
49
+ | num '/' num { result = [:div, val[0], val[2]] }
50
+ | '-' num = UMINUS { result = [:negate, val[1]] }
51
+ | '(' num ')' { result = val[1] }
52
+ | NUM { result = [:imm, val[0]] }
53
+ ;
54
+
55
+ end
56
+
57
+ ---- header ----
58
+
59
+ require 'smf'
60
+ require 'smf/toy/macro'
61
+ require 'rational'
62
+
63
+ class SemanticError < StandardError; end
64
+
65
+ ---- inner ----
66
+
67
+ STEPTAB = { 'w'=>1.to_r/1, 'h'=>1.to_r/2,
68
+ 'q'=>1.to_r/4, 'i'=>1.to_r/8,
69
+ 's'=>1.to_r/16,'z'=>1.to_r/32,
70
+ 'u'=>1.to_r/1920 }
71
+
72
+ NOTETAB = { 'a'=>9, 'b'=>11, 'c'=>0, 'd'=>2, 'e'=>4, 'f'=>5, 'g'=>7 }
73
+
74
+ def lineno() @co end
75
+
76
+ def parse(str)
77
+ @co = 1
78
+ @str = str
79
+ do_parse
80
+ end
81
+
82
+ def next_token
83
+ loop do
84
+ @str = @str.sub(/\A([\s\v]+)/, '')
85
+ if $1
86
+ @co += $1.count("\n")
87
+ end
88
+ @str = @str.sub(%r|\A(//.*)$|, '')
89
+ break unless $1
90
+ end
91
+ return [false, false] if @str.size == 0
92
+
93
+ if /\A([whqiszu])\b(\.+)?/i =~ @str
94
+ @str = $'
95
+ n = STEPTAB[$1.downcase]
96
+ i = if $2 then $2.size else 0 end
97
+ p = 1
98
+ i.times do |j|
99
+ p += Rational(1, 2 ** (j + 1))
100
+ end
101
+ s = n * p
102
+ return [:STEP, s]
103
+ end
104
+
105
+ if /\Ar\b/i =~ @str
106
+ @str = $'
107
+ return [:NOTE, nil]
108
+ end
109
+
110
+ if /\A([abcdefg])\b([$%#]+)?([,']+)?/i =~ @str
111
+ @str = $'
112
+ na = NOTETAB[$1.downcase]
113
+ if $2
114
+ s1 = 0
115
+ s1 -= $2.count('$')
116
+ s1 += $2.count('#')
117
+ end
118
+ if $3
119
+ s12 = 0
120
+ s12 -= $3.count(",") * 12
121
+ s12 += $3.count("'") * 12
122
+ end
123
+ return [:NOTE, [na, s1, s12]]
124
+ end
125
+
126
+ if /\A"/ =~ @str
127
+ @str = $'
128
+ s = '"'
129
+ until /\A"/ =~ @str
130
+ case @str
131
+ when /\A(\\.|.)/m; s << $1
132
+ end
133
+ @co += $1.count("\n")
134
+ @str = $'
135
+ end
136
+ s << '"'
137
+ @str = $'
138
+ return [:TEXT, eval(s)]
139
+ end
140
+
141
+ if /\A([a-z][a-z0-9]*)/i =~ @str
142
+ @str = $'
143
+ return [:VAR, $1]
144
+ end
145
+
146
+ if %r|\A([-+*/]?=)| =~ @str
147
+ @str = $'
148
+ return [:AOP, $1[0]]
149
+ end
150
+
151
+ if /\A(\d+)/ =~ @str
152
+ @str = $'
153
+ return [:NUM, Rational($1.to_i)]
154
+ end
155
+
156
+ if /\A(.)/ =~ @str
157
+ @str = $'
158
+ return [$1, $1]
159
+ end
160
+ end
161
+
162
+ ---- footer ----
163
+
164
+ module SMF
165
+
166
+ class MMLEvaluator
167
+
168
+ def initialize(de) @de = de end
169
+
170
+ def evaluate(st)
171
+ case st[0]
172
+ when :list
173
+ @de.push
174
+ st[1].each do |st2|
175
+ evaluate(st2)
176
+ end
177
+ of = @de[:of]
178
+ @de.pop
179
+ @de[:of] = of
180
+ @de.snap
181
+ when :stmt
182
+ of = @de[:of]
183
+ evaluate(st[1])
184
+ if st[2]
185
+ @de[:of] = of
186
+ end
187
+ when :step
188
+ @de[:le] = evaluate(st[1])
189
+ when :add
190
+ return evaluate(st[1]) + evaluate(st[2])
191
+ when :sub
192
+ return evaluate(st[1]) - evaluate(st[2])
193
+ when :mul
194
+ return evaluate(st[1]) * evaluate(st[2])
195
+ when :div
196
+ return evaluate(st[1]) / evaluate(st[2])
197
+ when :negate
198
+ return - evaluate(st[1])
199
+ when :imm
200
+ return st[1]
201
+ when :note
202
+ @de[:_no] = st[1]
203
+ @de.snap
204
+ @de[:_no] = nil
205
+ @de[:of] += @de[:le]
206
+ when :text
207
+ @de[:_tx] = st[1]
208
+ @de.snap
209
+ @de[:_tx] = nil
210
+ when :asgn
211
+ va = st[1]
212
+ op = st[2]
213
+ ob = evaluate(st[3])
214
+ if st[4]
215
+ ob2 = evaluate(st[4])
216
+ ob = [ob, ob2]
217
+ end
218
+ va = va.intern
219
+ v = @de[va]
220
+ case op
221
+ when ?+; v += ob
222
+ when ?-; v -= ob
223
+ when ?*; v *= ob
224
+ when ?/; v /= ob
225
+ when ?=; v = ob
226
+ end
227
+ if va == :ke
228
+ @de[:_ke] = v
229
+ @de.snap
230
+ @de[:_ke] = nil
231
+ end
232
+ @de[va] = v
233
+ @de.snap
234
+ end
235
+ end
236
+
237
+ end
238
+
239
+ end
@@ -0,0 +1,33 @@
1
+ # stt.rb: Written by Tadayoshi Funaba 2005
2
+ # $Id: stt.rb,v 1.2 2005-07-17 17:08:20+09 tadf Exp $
3
+
4
+ $KCODE = 'e'
5
+
6
+ require 'smf/toy/macro/mml'
7
+ require 'kconv'
8
+ require 'jcode'
9
+
10
+ module SMF
11
+
12
+ class STT < MML
13
+
14
+ NOTETAB = { '��'=>'a', '��' =>'b', '��'=>'c', '��'=>'d',
15
+ '��'=>'e', '�ե�'=>'f', '��'=>'g', '��'=>'r' }
16
+
17
+ def << (s)
18
+ s2 = s.toeuc.
19
+ gsub(/(��|��|��|��|��|�ե�|��|��)([$%#�����]+)?([,'����]+)?(��+)?/) do
20
+ n, s, o, x = $1, $2, $3, $4
21
+ no = NOTETAB[n]
22
+ no += s.tr('�����', '$%#') if s
23
+ no += o.tr('����', ",'") if o
24
+ le = 1
25
+ le += x.jsize if x
26
+ format('{le*=%d %s}', le, no)
27
+ end
28
+ super(s2)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,126 @@
1
+ # morse.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: morse.rb,v 1.4 2006-11-10 21:58:21+09 tadf Exp $
3
+
4
+ require 'smf'
5
+ require 'smf/toy/gm'
6
+
7
+ module SMF
8
+
9
+ class Morse
10
+
11
+ PLAIN = {
12
+ # '!' => 'exclamation mark',
13
+ # '"' => 'quotation mark',
14
+ '#' => 'number sign',
15
+ # '$' => 'dollar sign',
16
+ '%' => 'percent sign',
17
+ # '&' => 'ampersand',
18
+ # "'" => 'apostrophe',
19
+ # '(' => 'left parenthesis',
20
+ # ')' => 'right parenthesis',
21
+ '*' => 'asterisk',
22
+ '+' => 'plus sign',
23
+ # ',' => 'comma',
24
+ # '-' => 'hyphen', # -minus
25
+ # '.' => 'full stop',
26
+ # '/' => 'solidus',
27
+ # ':' => 'colon',
28
+ # ';' => 'semicolon',
29
+ '<' => 'less than sign',
30
+ # '=' => 'equals sign',
31
+ '>' => 'greater than sign',
32
+ # '?' => 'question mark',
33
+ # '@' => 'commercial at',
34
+ '[' => 'left square bracket',
35
+ '\\' => 'reverse solidus',
36
+ ']' => 'right square bracket',
37
+ '^' => 'circumflex accent',
38
+ # '_' => 'low line',
39
+ '`' => 'grave accent',
40
+ '{' => 'left curly bracket',
41
+ '|' => 'vertical line',
42
+ '}' => 'right curly bracket',
43
+ '~' => 'tilde'
44
+ }
45
+
46
+ CODE = {
47
+ ?! => '-.-.--', ?" => '.-..-.', ?$ => '...-..-',
48
+ ?& => '. ...', ?' => '.----.', ?( => '-.--.-', # '
49
+ ?) => '-.--.-', ?* => '-..-', ?+ => '.-.-.',
50
+ ?, => '--..--', ?- => '-....-', ?. => '.-.-.-',
51
+ ?/ => '-..-.',
52
+
53
+ ?0 => '-----', ?1 => '.----', ?2 => '..---',
54
+ ?3 => '...--', ?4 => '....-', ?5 => '.....',
55
+ ?6 => '-....', ?7 => '--...', ?8 => '---..',
56
+ ?9 => '----.',
57
+
58
+ ?: => '---...', ?; => '-.-.-', ?= => '-...-',
59
+ ?? => '..--..', ?@ => '.--.-.',
60
+
61
+ ?a => '.-', ?b => '-...', ?c => '-.-.',
62
+ ?d => '-..', ?e => '.', ?f => '..-.',
63
+ ?g => '--.', ?h => '....', ?i => '..',
64
+ ?j => '.---', ?k => '-.-', ?l => '.-..',
65
+ ?m => '--', ?n => '-.', ?o => '---',
66
+ ?p => '.--.', ?q => '--.-', ?r => '.-.',
67
+ ?s => '...', ?t => '-', ?u => '..-',
68
+ ?v => '...-', ?w => '.--', ?x => '-..-',
69
+ ?y => '-.--', ?z => '--..',
70
+
71
+ ?_ => '..--.-'
72
+ }
73
+
74
+ def initialize(sq, te=120)
75
+ @sq = sq << Track.new
76
+ @te = te
77
+ @mesg = []
78
+ end
79
+
80
+ def << (s) @mesg << s end
81
+
82
+ def plain(s)
83
+ s = s.dup
84
+ PLAIN.each_pair{|k, v| s.gsub!(k, ' %s ' % v)}
85
+ s
86
+ end
87
+
88
+ def encode(s)
89
+ s.downcase.scan(/\S+/).collect {|w|
90
+ w.scan(/./).collect{|c|
91
+ (CODE[c[0]] || '').scan(/./).join("\s")
92
+ }.join("\s"*3)
93
+ }.join("\s"*7) + "\s"*15
94
+ end
95
+
96
+ private :plain, :encode
97
+
98
+ def generate
99
+ of = 0
100
+ @sq[0] << SetTempo.new(of, 60000000 / 240)
101
+ @sq[0] << GMSystemOn.new(of)
102
+ of += @sq.division / 2
103
+ @sq[0] << ProgramChange.new(of, 0, 81)
104
+ of += @sq.division / 2
105
+ @sq[0] << SetTempo.new(of, 60000000 / @te)
106
+ @mesg.each do |s|
107
+ @sq[0] << Marker.new(of, s)
108
+ encode(plain(s)).each_byte do |c|
109
+ case c
110
+ when ?.; le = (@sq.division / 8) * 1
111
+ when ?-; le = (@sq.division / 8) * 3
112
+ else; le = (@sq.division / 8) * 1
113
+ end
114
+ if c == ?. || c == ?-
115
+ @sq[0] << NoteOn .new(of, 0, 69, 96)
116
+ @sq[0] << NoteOff.new(of + le, 0, 69, 64)
117
+ end
118
+ of += le
119
+ end
120
+ end
121
+ @sq[0] << EndOfTrack.new(of)
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -0,0 +1,32 @@
1
+ # quantize.rb: Written by Tadayoshi Funaba 1999-2005
2
+ # $Id: quantize.rb,v 1.1 2005-07-09 07:36:31+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ class Quantize
7
+
8
+ def initialize(div, unit=1.0/8)
9
+ @unit = unit * div * 4
10
+ self.min = 0.0
11
+ self.max = 1.0
12
+ self.rand = 0.0
13
+ end
14
+
15
+ def min=(v) @min = @unit * v end
16
+ def max=(v) @max = @unit * v end
17
+ def rand=(v) @rand = @unit * v end
18
+
19
+ def quantize(ev)
20
+ offset = (ev.offset + @unit / 2) / @unit * @unit
21
+ if @rand != 0
22
+ offset += rand(@rand) - @rand / 2
23
+ end
24
+ offset = offset.round
25
+ if (@min..@max) === (ev.offset - offset).abs
26
+ ev.offset = offset
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,29 @@
1
+ # rmi.rb: Written by Tadayoshi Funaba 2001-2005
2
+ # $Id: rmi.rb,v 1.1 2005-07-09 07:36:31+09 tadf Exp $
3
+
4
+ module SMF
5
+
6
+ module RMI
7
+
8
+ def smf2rmi(s)
9
+ pad = s.size % 2
10
+ o = 'RIFF'
11
+ o << [12 + s.size + pad].pack('V')
12
+ o << 'RMID'
13
+ o << 'data'
14
+ o << [s.size].pack('V')
15
+ o << s
16
+ pad.times do o << "\000" end
17
+ o
18
+ end
19
+
20
+ def rmi2smf(s)
21
+ x, = s[16,4].unpack('V')
22
+ s[20,x]
23
+ end
24
+
25
+ module_function :smf2rmi, :rmi2smf
26
+
27
+ end
28
+
29
+ end