razyk 0.0.1 → 0.1.0
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.
- 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
|