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.
@@ -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
@@ -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[:output] ||= $stdout
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
@@ -0,0 +1,8 @@
1
+ # coding: utf-8
2
+
3
+ require "coreaudio"
4
+
5
+ require "razyk/audio/port"
6
+ require "razyk/audio/player"
7
+
8
+
@@ -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