razyk 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +54 -0
- data/Rakefile +7 -55
- data/bin/razyk +1 -67
- data/examples/air_on_the_g_string.lazy +489 -0
- data/examples/air_on_the_g_string.score +14 -0
- data/examples/encoder.rb +62 -0
- data/examples/hello_world.lazy +39 -0
- data/examples/major_scale.lazy +20 -0
- data/examples/minor_scale.lazy +20 -0
- data/examples/score2lazy.rb +38 -0
- data/lib/razyk.rb +7 -2
- data/lib/razyk/application.rb +108 -0
- data/lib/razyk/audio.rb +8 -0
- data/lib/razyk/audio/player.rb +68 -0
- data/lib/razyk/audio/port.rb +36 -0
- data/lib/razyk/node.rb +49 -1
- data/lib/razyk/parser.rb +16 -20
- data/lib/razyk/parser.y +15 -19
- data/lib/razyk/version.rb +3 -0
- data/lib/razyk/vm.rb +52 -54
- data/lib/razyk/webapp.rb +61 -108
- data/lib/razyk/webapp/templates/main.html +216 -49
- data/razyk.gemspec +27 -66
- metadata +163 -86
- data/spec/node_spec.rb +0 -58
- data/spec/spec_helper.rb +0 -5
- data/spec/vm_spec.rb +0 -128
@@ -0,0 +1,14 @@
|
|
1
|
+
2
|
2
|
+
4A0
|
3
|
+
36E5 2A5 2F5 2D5 2C5 2B4 2C5 7B4 A4 8G4
|
4
|
+
18G5 2E5 2B4- 2A4 2D5 2C5+ 2G5 2F5 18F5 2D5 2A4 2G4 2C5 2B4 2F5 2E5
|
5
|
+
12E5 2F5+ 2G5 4C5 C5 D5 2E5 2E5 4D5 2C5 2B4 2A4 A4 B4 2C5 4C5 2B4 2A4 16G4
|
6
|
+
36E5 2A5 2F5 2D5 2C5 2B4 2C5 7B4 A4 8G4
|
7
|
+
18G5 2E5 2B4- 2A4 2D5 2C5+ 2G5 2F5 18F5 2D5 2A4 2G4 2C5 2B4 2F5 2E5
|
8
|
+
12E5 2F5+ 2G5 4C5 C5 D5 2E5 2E5 4D5 2C5 2B4 2A4 A4 B4 2C5 4C5 2B4 2A4 16G4
|
9
|
+
8B4 2B4 C5 B4 A4 B4 2G4 12G5 4B4- 4A4 4A5 2A5 2G5 2F5 2E5 8F5 F5 E5 D5 C5 2B4 2A4
|
10
|
+
2G4+ 2A4 4B4 2B4 2C5 4D5 2D5 2E5 4F5 4F5 4E5 2D5 2C5 2B4 2A4 2B4 C5 D5 4C5 16A4
|
11
|
+
8C5 2C5 2E5 2D5 2C5 12A5 2G5 2F5+ 2D5 2G5 4G4 6A4 B4 C5 7B4 A4 8G4
|
12
|
+
12C5 2E5 2D5 12D5 2F5 2E5 12E5 2G5 2F5 16F5
|
13
|
+
8G4 2G4 2B4 2D5 2F5 2F5 2D5 4E5 4E5 2E5 F5 G5 8C5 2C5 2E5 2G5 2B5- 4B5- 8A5 4C5
|
14
|
+
2B4 2D5 8F5 4A4 4G4 D5 E5 2F5 2F5 4E5 2D5 C5 B4 4A4 2B4 3B4 A4 2B4 2C5 16C5
|
data/examples/encoder.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "razyk/vm"
|
2
|
+
require "razyk/parser"
|
3
|
+
|
4
|
+
ZERO = "KI"
|
5
|
+
ONE = "I"
|
6
|
+
TWO = "(S(S(KS)K)I)"
|
7
|
+
THREE = "((S(S(KS)K))(S(S(KS)K)I))"
|
8
|
+
FOUR = "(S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I))"
|
9
|
+
FIVE = "(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I))"
|
10
|
+
|
11
|
+
def mul(comb, n)
|
12
|
+
"(S(K#{n})(S(K#{comb})I))"
|
13
|
+
end
|
14
|
+
|
15
|
+
def destruct(n)
|
16
|
+
return ZERO if n == 0
|
17
|
+
return ONE if n == 1
|
18
|
+
return TWO if n == 2
|
19
|
+
return THREE if n == 3
|
20
|
+
return FOUR if n == 4
|
21
|
+
return FIVE if n == 5
|
22
|
+
comb = ONE
|
23
|
+
while n % 2 == 0
|
24
|
+
n /= 2
|
25
|
+
comb = mul(comb, TWO)
|
26
|
+
end
|
27
|
+
while n % 3 == 0
|
28
|
+
n /= 3
|
29
|
+
comb = mul(comb, THREE)
|
30
|
+
end
|
31
|
+
while n % 5 == 0
|
32
|
+
n /= 5
|
33
|
+
comb = mul(comb, FIVE)
|
34
|
+
end
|
35
|
+
if n == 1
|
36
|
+
return comb
|
37
|
+
else
|
38
|
+
return mul(comb, "((S(S(KS)K))#{destruct(n-1)})")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def cons(a, b)
|
43
|
+
"(S(SI(K(#{a})))(K(#{b})))"
|
44
|
+
end
|
45
|
+
|
46
|
+
def ary2list(ary)
|
47
|
+
([256] + ary.reverse).inject("I"){ |cdr, car|
|
48
|
+
cons(destruct(car), cdr)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def evaluate_church(comb)
|
53
|
+
s = {count: 0}
|
54
|
+
RazyK::VM.new(RazyK::Parser.parse("#{comb} $f $x"), statistics: s, recursive: true).run{|b| p b.tree }
|
55
|
+
s[:count]
|
56
|
+
end
|
57
|
+
|
58
|
+
def evaluate_list(comb)
|
59
|
+
s = {count: 0}
|
60
|
+
RazyK::VM.new(RazyK::Parser.parse("$OUT ((K #{comb}) $IN)"), statistics: s, recursive: false).run
|
61
|
+
s[:count]
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
(K
|
2
|
+
(S(SI(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))
|
3
|
+
(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))
|
4
|
+
I)))I)))I))))(K(S(SI(K(S(K((S(S(KS)K))(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))
|
5
|
+
(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))
|
6
|
+
(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
7
|
+
(S(KI)I)))I)))I)))I))))(S(KI)I))))(K(S(SI(K(S(K((S(S(KS)K))(S(S(KS)K)I)))
|
8
|
+
(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K(S
|
9
|
+
(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I))))(K(S(SI(K(S(K((S(S
|
10
|
+
(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))
|
11
|
+
(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I))))
|
12
|
+
(K(S(SI(K(S(K((S(S(KS)K))(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))
|
13
|
+
(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I))))
|
14
|
+
(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(KI)I)))I))))(K(S(SI(K(S(K((S(S(KS)K))
|
15
|
+
(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))
|
16
|
+
(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I))))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
17
|
+
(S(KI)I)))I)))I))))(K(S(SI(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S
|
18
|
+
(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I))))
|
19
|
+
(K(S(SI(K(S(K((S(S(KS)K))(S(K((S(S(KS)K))(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S
|
20
|
+
(K(S(S(KS)K)I))(S(KI)I)))I))))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
21
|
+
(S(KI)I)))I)))I))))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(KI)I)))I))))
|
22
|
+
(K(S(SI(K(S(K((S(S(KS)K))(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))
|
23
|
+
(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I))))
|
24
|
+
(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(KI)I)))I))))(K(S(SI(K(S(K((S(S(KS)K))
|
25
|
+
(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K(S(S
|
26
|
+
(KS)K)I))(S(KI)I)))I)))I))))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))
|
27
|
+
(S(KI)I)))I)))I))))(K(S(SI(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))
|
28
|
+
(S(S(KS)K)I)))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S
|
29
|
+
(S(KS)K)I))(S(KI)I)))I)))I)))I)))I))))(K(S(SI(K(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))
|
30
|
+
(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))
|
31
|
+
(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
32
|
+
(S(KI)I)))I)))I)))I))))(K(S(SI(K(S(K((S(S(KS)K))(S(K(S(S(KS)(S(KK)
|
33
|
+
(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS)K)I))
|
34
|
+
(S(KI)I)))I))))(S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(KI)I)))I))))
|
35
|
+
(K(S(SI(K(S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))
|
36
|
+
(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I))))(K(S(SI(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
37
|
+
(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))
|
38
|
+
(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I)))I)))I)))I))))
|
39
|
+
(KI)))))))))))))))))))))))))))))))
|
@@ -0,0 +1,20 @@
|
|
1
|
+
K
|
2
|
+
(S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)
|
3
|
+
K))(S(S(KS)K)I)))))(K((S(SI(K(KI)))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)
|
4
|
+
K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K)I)
|
5
|
+
)))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)K))((S(S
|
6
|
+
(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)
|
7
|
+
K))(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K)
|
8
|
+
)(S(S(KS)K)I)))I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K)
|
9
|
+
)(S(S(KS)K)I)))))(K((S(SI(K((S(K((S(S(KS)K))(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S
|
10
|
+
(K(S(S(KS)K)I))(S(KI)I)))I))))(S(KI)I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((
|
11
|
+
S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(K((S(S(KS)K))(S(S(KS)K)I)))(
|
12
|
+
S(K(S(K((S(S(KS)K))(S(S(KS)K)I)))(S(KI)I)))I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S
|
13
|
+
(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(K((S(S(KS)K))(S(K(S(S
|
14
|
+
(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I)))(S(K(S(K(S(S(KS
|
15
|
+
)K)I))(S(KI)I)))I))))(S(KI)I)))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I))
|
16
|
+
)))(K((S(SI(K((S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)I)))I
|
17
|
+
)))))(K((S(SI(K(KI)))(K((S(SI(K((S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S
|
18
|
+
(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S
|
19
|
+
(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I)))I)))I)))I)))))(K(I
|
20
|
+
))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
@@ -0,0 +1,20 @@
|
|
1
|
+
K
|
2
|
+
(S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)
|
3
|
+
K))(S(S(KS)K)I)))))(K((S(SI(K(KI)))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)
|
4
|
+
K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K)I)
|
5
|
+
)))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I)))))(K((S(SI(K(((S(S(KS)K))(S(S
|
6
|
+
(KS)K)I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)
|
7
|
+
K)I)))))(K((S(SI(K((S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)K)
|
8
|
+
I)))I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)
|
9
|
+
I)))))(K((S(SI(K((S(K((S(S(KS)K))(S(S(KS)K)I)))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)
|
10
|
+
))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)I)))))
|
11
|
+
(K((S(SI(K((S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))
|
12
|
+
I)))I)))))(K((S(SI(K((S(S(KS)K)I))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K))(S(S(KS)K)
|
13
|
+
I)))))(K((S(SI(K((S(K(S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(S(S(KS)
|
14
|
+
K)I)))I)))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))))(K((S(SI(K((S(S(KS)K))((S(S(KS)K)
|
15
|
+
)(S(S(KS)K)I)))))(K((S(SI(K((S(S(KS)(S(KK)(S(K(S(S(KS)K)I))I)))(S(K((S(S(KS)K))(
|
16
|
+
S(S(KS)K)I)))I)))))(K((S(SI(K(KI)))(K((S(SI(K((S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K
|
17
|
+
)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(
|
18
|
+
KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(K(S(K(S(S(KS)K)I))(S(KI)I)))I)))I)))I)))I)))I)))
|
19
|
+
I)))I)))))(K(I))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
20
|
+
))))))))))))
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "encoder"
|
2
|
+
|
3
|
+
scores = $stdin.read.split(/\s+/m)
|
4
|
+
tempo = scores.shift.to_i
|
5
|
+
|
6
|
+
def name2tone(s)
|
7
|
+
/\A(\d*)([A-G])(\d+)([-+]?)\z/ =~ s
|
8
|
+
l = Regexp.last_match(1)
|
9
|
+
k = Regexp.last_match(2)
|
10
|
+
o = Regexp.last_match(3)
|
11
|
+
shift = Regexp.last_match(4)
|
12
|
+
if l == ""
|
13
|
+
l = 1
|
14
|
+
else
|
15
|
+
l = l.to_i
|
16
|
+
end
|
17
|
+
o = o.to_i
|
18
|
+
k = {"C" => 0, "D" => 2, "E" => 4, "F" => 5, "G" => 7, "A" => 9, "B" => 11}[k]
|
19
|
+
if shift == "-"
|
20
|
+
k -= 1
|
21
|
+
if k == -1
|
22
|
+
o -= 1
|
23
|
+
k = 11
|
24
|
+
end
|
25
|
+
elsif shift == "+"
|
26
|
+
k += 1
|
27
|
+
if k == 12
|
28
|
+
o += 1
|
29
|
+
k = 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
[l, o, k]
|
33
|
+
end
|
34
|
+
|
35
|
+
lazy = "K" + ary2list([tempo, scores.map{|s| name2tone(s) }].flatten)
|
36
|
+
puts lazy
|
37
|
+
|
38
|
+
system("bundle exec razyk --audio -e '#{lazy}'")
|
data/lib/razyk.rb
CHANGED
@@ -6,10 +6,15 @@ require "razyk/vm"
|
|
6
6
|
module RazyK
|
7
7
|
def self.run(program, opt={}, &blk)
|
8
8
|
opt[:input] ||= $stdin
|
9
|
-
opt[:
|
9
|
+
if opt[:audio]
|
10
|
+
opt[:output] = RazyK::Audio::Port.new
|
11
|
+
else
|
12
|
+
opt[:output] ||= $stdout
|
13
|
+
end
|
14
|
+
opt[:memory] ||= {}
|
10
15
|
tree = Parser.parse(program, opt)
|
11
16
|
root = Pair.new(:OUT, Pair.new(tree, :IN))
|
12
|
-
vm = VM.new(root, opt[:input], opt[:output])
|
17
|
+
vm = VM.new(root, opt[:input], opt[:output], recursive: opt[:recursive], statistics: opt[:statistics])
|
13
18
|
|
14
19
|
if blk
|
15
20
|
vm.run(&blk)
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "razyk"
|
4
|
+
require "optparse"
|
5
|
+
|
6
|
+
module RazyK
|
7
|
+
class ApplicationError < RuntimeError; end
|
8
|
+
|
9
|
+
class Application
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@program = nil
|
13
|
+
@step = false
|
14
|
+
@web_server = false
|
15
|
+
@optparse = option_parser
|
16
|
+
end
|
17
|
+
|
18
|
+
def option_parser
|
19
|
+
OptionParser.new do |opt|
|
20
|
+
opt.banner = "Usage: razyk [options] [programfile]"
|
21
|
+
opt.on("-e 'program'",
|
22
|
+
"specify LazyK program string. Omit [programfile]") do |prog|
|
23
|
+
@program = prog
|
24
|
+
end
|
25
|
+
opt.on("-s", "--step", "step execution. Dump combinator tree by each step") do
|
26
|
+
@step = true
|
27
|
+
end
|
28
|
+
opt.on("--server [PORT]", "start web server") do |port|
|
29
|
+
@port = Integer(port || 9292)
|
30
|
+
@step = true
|
31
|
+
@web_server = true
|
32
|
+
end
|
33
|
+
opt.on("--[no-]statistics", "dump statistics information at exit") do
|
34
|
+
@statistics = { count: 0 }
|
35
|
+
end
|
36
|
+
opt.on("--audio", "output audio stream (supported on only OS X and coreaudio.gem is required)") do
|
37
|
+
begin
|
38
|
+
require "coreaudio"
|
39
|
+
rescue LoadError
|
40
|
+
raise RazyK::ApplicationError, "--audio option require coreaudio.gem (available only on OS X). Please install coreaudio.gem"
|
41
|
+
end
|
42
|
+
require "razyk/audio"
|
43
|
+
@audio = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
private :option_parser
|
48
|
+
|
49
|
+
def run_web_server
|
50
|
+
require "razyk/webapp"
|
51
|
+
app = RazyK::WebApp.new
|
52
|
+
# This should work, but rack-1.2.1 fails. :app don't overwrite config.ru
|
53
|
+
#Rack::Server.start(:app => app, :Port => @port)
|
54
|
+
trap(:INT) do
|
55
|
+
if Rack::Handler::WEBrick.respond_to?(:shutdown)
|
56
|
+
Rack::Handler::WEBrick.shutdown
|
57
|
+
else
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
end
|
61
|
+
Rack::Handler::WEBrick.run(app, :Port => @port)
|
62
|
+
end
|
63
|
+
|
64
|
+
def run_interpreter(argv)
|
65
|
+
if @program.nil?
|
66
|
+
if argv.empty?
|
67
|
+
raise RazyK::ApplicationError, "please specify LazyK program file"
|
68
|
+
end
|
69
|
+
filepath = argv.shift
|
70
|
+
unless File.readable?(filepath)
|
71
|
+
raise RazyK::ApplicationError, "#{filepath} not found or not readable"
|
72
|
+
end
|
73
|
+
@program = IO.read(filepath)
|
74
|
+
end
|
75
|
+
|
76
|
+
opts = {
|
77
|
+
statistics: @statistics,
|
78
|
+
audio: @audio,
|
79
|
+
}
|
80
|
+
|
81
|
+
if @step
|
82
|
+
RazyK.run(@program, opts) do |vm|
|
83
|
+
$stderr.puts vm.tree.inspect
|
84
|
+
end
|
85
|
+
else
|
86
|
+
RazyK.run(@program, opts)
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
if @statistics
|
90
|
+
puts "Statistics Info:"
|
91
|
+
puts "\t#{@statistics[:started_at]} - #{@statistics[:finished_at]} (#{@statistics[:finished_at]-@statistics[:started_at]} sec)"
|
92
|
+
puts "\treduce count: #{@statistics[:count]}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def run(argv)
|
97
|
+
@optparse.parse!(argv)
|
98
|
+
|
99
|
+
if @web_server
|
100
|
+
run_web_server
|
101
|
+
else
|
102
|
+
run_interpreter(argv)
|
103
|
+
end
|
104
|
+
rescue RazyK::ApplicationError
|
105
|
+
$stderr.puts($!.message)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/razyk/audio.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "coreaudio"
|
4
|
+
require "thread"
|
5
|
+
|
6
|
+
module RazyK::Audio
|
7
|
+
class Player
|
8
|
+
def initialize(tempo: 4)
|
9
|
+
@tempo = tempo
|
10
|
+
@dev = CoreAudio.default_output_device
|
11
|
+
@buf = @dev.output_buffer(1024)
|
12
|
+
@beat_samples = (@dev.nominal_rate / (@tempo * 4)).floor
|
13
|
+
@beat_bufs = Hash.new { |h, k| h[k] = NArray.sint(@beat_samples * (k+1)) }
|
14
|
+
@samples = 0
|
15
|
+
@queue = Queue.new
|
16
|
+
@thread = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def play(length, octave, note)
|
20
|
+
unless (0..8).include?(octave)
|
21
|
+
octave = 4
|
22
|
+
end
|
23
|
+
unless (0..11).include?(note)
|
24
|
+
note = 0
|
25
|
+
end
|
26
|
+
@queue.push([length, octave, note])
|
27
|
+
if @thread.nil? or not(@thread.status)
|
28
|
+
@thread = Thread.start{ run }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
@queue.push(nil)
|
34
|
+
@thread.join if @thread
|
35
|
+
end
|
36
|
+
|
37
|
+
def run
|
38
|
+
begin
|
39
|
+
@buf.start
|
40
|
+
while (tuple = @queue.pop)
|
41
|
+
length, octave, note = tuple
|
42
|
+
wav = @beat_bufs[length]
|
43
|
+
if octave | note == 0
|
44
|
+
wav.fill!(0)
|
45
|
+
else
|
46
|
+
freq = (440.0 * (2 ** (octave-4))) # An
|
47
|
+
freq *= 2 ** ((note-9)/12.0)
|
48
|
+
phase = Math::PI * 2 * freq / @dev.nominal_rate
|
49
|
+
breath = (@beat_samples * 0.2).round
|
50
|
+
eot = wav.size - breath
|
51
|
+
eot.times do |j|
|
52
|
+
wav[j] = (0.7 * Math.sin(phase*(@samples+j)) * 0x7FFF).round
|
53
|
+
end
|
54
|
+
breath.times do |j|
|
55
|
+
wav[eot+j] = 0
|
56
|
+
end
|
57
|
+
@samples += wav.size
|
58
|
+
@buf << wav
|
59
|
+
end
|
60
|
+
end
|
61
|
+
rescue
|
62
|
+
puts $!, $@
|
63
|
+
ensure
|
64
|
+
@buf.stop
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "razyk/audio/player"
|
4
|
+
|
5
|
+
module RazyK::Audio
|
6
|
+
class Port
|
7
|
+
def initialize
|
8
|
+
@player = nil
|
9
|
+
@note_length = nil
|
10
|
+
@octave = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(s)
|
14
|
+
bytes = s.unpack("C*")
|
15
|
+
if @player.nil?
|
16
|
+
@player = RazyK::Audio::Player.new(tempo: bytes.shift)
|
17
|
+
end
|
18
|
+
bytes.each do |b|
|
19
|
+
if @note_length and @octave
|
20
|
+
@player.play(@note_length, @octave, b)
|
21
|
+
@note_length = nil
|
22
|
+
@octave = nil
|
23
|
+
elsif @note_length
|
24
|
+
@octave = b
|
25
|
+
else
|
26
|
+
@note_length = b
|
27
|
+
end
|
28
|
+
end
|
29
|
+
s
|
30
|
+
end
|
31
|
+
|
32
|
+
def close_write
|
33
|
+
@player.stop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|