ruck 0.1.2 → 0.2.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.
data/README CHANGED
@@ -1,67 +1,35 @@
1
1
  A port of ChucK's strong timing to Ruby!
2
2
 
3
- Use Ruck's "shreds" to coordinate interleaved execution
4
- of threads (continuations) with precise virtual timing.
5
- Actual run-time is abstracted and shreds declare how much
6
- virtual time they took to execute. Scheduling of shreds
7
- is done by a ...
3
+ ruck lets you easily create a virtual clock against
4
+ which precise timing of execution can be guaranteed. The
5
+ virtual clock can be kept roughly in sync with real time
6
+ if you want it to, but you don't have to. For example, in
7
+ ChucK, even if your scripts take too long to generate
8
+ samples in real time, the audio stream isn't compromised
9
+ because it's timed against the virtual clock.
8
10
 
9
- SHREDULER
11
+ ruck provides an easily extended scheduler for non-preemptive
12
+ shreds (threads) implemented using continuations.
13
+ Cooperatively scheduled threads usually don't require
14
+ synchronization since execution is never interrupted.
10
15
 
11
- UGenShreduler:
12
-
13
- This shreduler calculates an audio unit generator graph's
14
- output in virtual time. The graph can be modified by
15
- shreds all the while.
16
-
17
- The graph is written in Ruby for flexibility, so it's
18
- too slow (on my computer) for real time, so there is no
19
- real-time playback. You can use WavOut, though.
20
- (See ex01.rb)
21
-
22
- Check out the library of built-in unit generators in ugen/
23
- and make your own.
16
+ A few example shredulers (schedulers) are provided:
24
17
 
25
- Unit Generator Usage
26
- ====================
27
-
28
- Play a sine wave (ex02.rb):
29
-
30
- s = SinOsc.new(:freq => 440)
31
- w = WavOut.new(:filename => "ex02.wav")
32
- s >> w >> blackhole
33
- play 3.seconds
34
-
35
- Attach lambdas to unit generator attributes (ex03.rb):
18
+ UGenShreduler:
36
19
 
37
- wav = WavOut.new(:filename => "ex03.wav")
38
- sin2 = SinOsc.new(:freq => 3)
39
- sin = SinOsc.new(:freq => L{ sin2.last * 220 + 660 },
40
- :gain => L{ 0.5 + sin2.last * 0.5 })
41
- [sin >> wav, sin2] >> blackhole
42
- play 3.seconds
20
+ Recently moved to its own gem: ruck-ugen
43
21
 
44
22
  RealTimeShreduler
45
23
 
46
- This shreduler attempts to keep virtual time in line with
47
- real time.
48
- (See ex10.rb)
24
+ Recently moved to its own gem: ruck-realtime
49
25
 
50
26
  MIDIShreduler
51
27
 
52
- This shreduler uses MIDIator and midilib to support live
53
- MIDI playback and saving MIDI to disk. An example runner
54
- is provided in midi_runner.rb which you invoke like this:
55
-
56
- $ ruck_midi MIDI_FILENAME NUM_TRACKS LIVE SCRIPT_FILENAME [...]
57
-
58
- where LIVE is "no" to only save the MIDI output, or "yes"
59
- to also play in real-time.
28
+ Recently moved to its own gem: ruck-midi
60
29
 
61
30
  GLAppShreduler
62
31
 
63
- You don't want to know. (But the scripts are included so
64
- you can find them if you're really curious.)
32
+ You don't want to know. But see ruck-glapp if you do.
65
33
 
66
34
  USAGE
67
35
  =====
@@ -77,4 +45,4 @@ examples/ directory. Those scripts contain no boilerplate includes
77
45
  because they are written to be invoked on the command line by
78
46
  one of the bin/ scripts. For example:
79
47
 
80
- $ ruck_ugen examples/ex01.rb
48
+ $ ruck_ugen examples/ugen/ex01.rb
data/Rakefile CHANGED
@@ -1,25 +1,25 @@
1
+ require 'rubygems'
2
+ require 'rake'
1
3
 
2
4
  begin
3
5
  require "jeweler"
4
- Jeweler::Tasks.new do |gemspec|
5
- gemspec.name = "ruck"
6
- gemspec.email = "tom@alltom.com"
7
- gemspec.homepage = "http://github.com/alltom/ruck"
8
- gemspec.authors = ["Tom Lieber"]
9
- gemspec.summary = "strong timing for Ruby: cooperative threads on a virtual clock"
10
- gemspec.description = <<-EOF
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ruck"
8
+ gem.email = "tom@alltom.com"
9
+ gem.homepage = "http://github.com/alltom/ruck"
10
+ gem.authors = ["Tom Lieber"]
11
+ gem.summary = "strong timing for Ruby: cooperative threads on a virtual clock"
12
+ gem.description = <<-EOF
11
13
  Ruck uses continuations and a simple scheduler to ensure "shreds"
12
- (threads in Ruck) are woken at precisely the right time according
14
+ (Ruck threads) are woken at precisely the right time according
13
15
  to its virtual clock. Schedulers can map virtual time to samples
14
16
  in a WAV file, real time, time in a MIDI file, or anything else
15
17
  by overriding "sim_to" in the Shreduler class.
16
-
17
- A small library of useful unit generators and plenty of examples
18
- are provided. See the README or the web page for details.
19
18
  EOF
20
- gemspec.has_rdoc = false
19
+ gem.has_rdoc = false
20
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
21
  end
22
22
  Jeweler::GemcutterTasks.new
23
23
  rescue LoadError
24
- puts "Jewler not available. Install it with: sudo gem install jeweler"
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
25
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -4,6 +4,7 @@ module Ruck
4
4
  class Shred
5
5
  attr_accessor :now
6
6
  attr_accessor :finished
7
+ attr_accessor :name
7
8
 
8
9
  def initialize(shreduler, now, name, &block)
9
10
  @shreduler = shreduler
@@ -28,6 +29,7 @@ module Ruck
28
29
  end
29
30
 
30
31
  @finished = true
32
+ @shreduler.remove_shred self
31
33
  end
32
34
 
33
35
  def yield(samples)
@@ -41,7 +43,12 @@ module Ruck
41
43
  end
42
44
 
43
45
  def finish
44
- @resume.call # last save point
46
+ @finished = true
47
+ @shreduler.remove_shred self
48
+
49
+ if @shreduler.current_shred == self
50
+ @resume.call # last save point
51
+ end
45
52
  end
46
53
 
47
54
  # shreds sort in order of position in time
@@ -66,14 +73,15 @@ module Ruck
66
73
  @running = false
67
74
  end
68
75
 
69
- def spork(name = "", &shred)
70
- LOG.debug "Adding shred \"#{name}\" at #{@now}"
71
- @shreds << Shred.new(self, @now, name, &shred)
72
- @shred
76
+ def spork(name = "", &shred_block)
77
+ shred = Shred.new(self, @now, name, &shred_block)
78
+ LOG.debug "Adding shred \"#{shred.name}\" at #{@now}"
79
+ @shreds << shred
80
+ shred
73
81
  end
74
82
 
75
83
  def remove_shred(shred)
76
- LOG.debug "Removing shred \"#{name}\" at #{@now}"
84
+ LOG.debug "Removing shred \"#{shred.name}\" at #{@now}"
77
85
  @shreds.delete shred
78
86
  end
79
87
 
@@ -82,7 +90,7 @@ module Ruck
82
90
  end
83
91
 
84
92
  # called when shreds allow time to pass
85
- # a convnient method to override
93
+ # a convenient method to override
86
94
  def sim_to(new_now)
87
95
  @now = new_now
88
96
  end
@@ -101,11 +109,11 @@ module Ruck
101
109
 
102
110
  sim_to(shred.now)
103
111
 
104
- invoke_shred shred
112
+ invoke_shred(shred)
105
113
 
106
114
  if @current_shred.finished
107
115
  LOG.debug "#{shred} finished"
108
- @shreds.delete(shred)
116
+ remove_shred(shred)
109
117
  end
110
118
  end
111
119
 
@@ -123,36 +131,5 @@ module Ruck
123
131
  @running = false
124
132
  end
125
133
  end
126
-
127
- class UGenShreduler < Shreduler
128
- def run
129
- require File.join(File.dirname(__FILE__), "misc", "pcm_time_helpers")
130
- super
131
- end
132
-
133
- def sim_to(new_now)
134
- while @now < new_now.to_i
135
- BLACKHOLE.next @now
136
- @now += 1
137
- end
138
- end
139
- end
140
-
141
- class RealTimeShreduler < Shreduler
142
- def run
143
- @start_time = Time.now
144
- super
145
- end
146
-
147
- def sim_to(new_now)
148
- actual_now = Time.now
149
- simulated_now = @start_time + (new_now.to_f / SAMPLE_RATE)
150
- if simulated_now > actual_now
151
- sleep(simulated_now - actual_now)
152
- end
153
-
154
- @now = new_now
155
- end
156
- end
157
134
 
158
135
  end
data/lib/ruck.rb CHANGED
@@ -6,8 +6,3 @@ module Ruck
6
6
  end
7
7
 
8
8
  require File.join(File.dirname(__FILE__), "ruck", "shreduling")
9
- require File.join(File.dirname(__FILE__), "ruck", "misc", "metaid")
10
- require File.join(File.dirname(__FILE__), "ruck", "misc", "linkage")
11
- require File.join(File.dirname(__FILE__), "ruck", "ugen", "general")
12
- require File.join(File.dirname(__FILE__), "ruck", "ugen", "wav")
13
- require File.join(File.dirname(__FILE__), "ruck", "ugen", "oscillators")
data/ruck.gemspec CHANGED
@@ -5,22 +5,18 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruck}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tom Lieber"]
12
- s.date = %q{2009-11-21}
12
+ s.date = %q{2010-07-10}
13
13
  s.description = %q{ Ruck uses continuations and a simple scheduler to ensure "shreds"
14
- (threads in Ruck) are woken at precisely the right time according
14
+ (Ruck threads) are woken at precisely the right time according
15
15
  to its virtual clock. Schedulers can map virtual time to samples
16
16
  in a WAV file, real time, time in a MIDI file, or anything else
17
17
  by overriding "sim_to" in the Shreduler class.
18
-
19
- A small library of useful unit generators and plenty of examples
20
- are provided. See the README or the web page for details.
21
18
  }
22
19
  s.email = %q{tom@alltom.com}
23
- s.executables = ["ruck_glapp", "ruck_midi", "ruck_sleep", "ruck_ugen"]
24
20
  s.extra_rdoc_files = [
25
21
  "README"
26
22
  ]
@@ -29,64 +25,15 @@ Gem::Specification.new do |s|
29
25
  "README",
30
26
  "Rakefile",
31
27
  "VERSION",
32
- "bin/ruck_glapp",
33
- "bin/ruck_midi",
34
- "bin/ruck_sleep",
35
- "bin/ruck_ugen",
36
- "examples/glapp/ex01.rb",
37
- "examples/glapp/ex02.rb",
38
- "examples/glapp/ex03.rb",
39
- "examples/midi/ex01.rb",
40
- "examples/midi/ex02.rb",
41
- "examples/ugen/ex01.rb",
42
- "examples/ugen/ex02.rb",
43
- "examples/ugen/ex03.rb",
44
- "examples/ugen/ex04.rb",
45
- "examples/ugen/ex05.rb",
46
- "examples/ugen/ex06.rb",
47
- "examples/ugen/ex07.rb",
48
- "examples/ugen/ex08.rb",
49
- "examples/ugen/ex09.rb",
50
- "examples/ugen/ex10.rb",
51
- "examples/ugen/ex11.rb",
52
- "examples/ugen/ex12.rb",
53
28
  "lib/ruck.rb",
54
- "lib/ruck/bench.rb",
55
- "lib/ruck/misc/linkage.rb",
56
- "lib/ruck/misc/metaid.rb",
57
- "lib/ruck/misc/pcm_time_helpers.rb",
58
- "lib/ruck/misc/riff.rb",
59
- "lib/ruck/misc/wavparse.rb",
60
29
  "lib/ruck/shreduling.rb",
61
- "lib/ruck/ugen/general.rb",
62
- "lib/ruck/ugen/oscillators.rb",
63
- "lib/ruck/ugen/wav.rb",
64
30
  "ruck.gemspec"
65
31
  ]
66
32
  s.homepage = %q{http://github.com/alltom/ruck}
67
33
  s.rdoc_options = ["--charset=UTF-8"]
68
34
  s.require_paths = ["lib"]
69
- s.rubygems_version = %q{1.3.5}
35
+ s.rubygems_version = %q{1.3.6}
70
36
  s.summary = %q{strong timing for Ruby: cooperative threads on a virtual clock}
71
- s.test_files = [
72
- "examples/glapp/ex01.rb",
73
- "examples/glapp/ex02.rb",
74
- "examples/glapp/ex03.rb",
75
- "examples/midi/ex01.rb",
76
- "examples/midi/ex02.rb",
77
- "examples/ugen/ex01.rb",
78
- "examples/ugen/ex02.rb",
79
- "examples/ugen/ex03.rb",
80
- "examples/ugen/ex04.rb",
81
- "examples/ugen/ex05.rb",
82
- "examples/ugen/ex06.rb",
83
- "examples/ugen/ex07.rb",
84
- "examples/ugen/ex08.rb",
85
- "examples/ugen/ex09.rb",
86
- "examples/ugen/ex10.rb",
87
- "examples/ugen/ex11.rb",
88
- "examples/ugen/ex12.rb"
89
- ]
90
37
 
91
38
  if s.respond_to? :specification_version then
92
39
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruck
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Tom Lieber
@@ -9,17 +14,14 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-11-21 00:00:00 -08:00
17
+ date: 2010-07-10 00:00:00 -07:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
16
- description: " Ruck uses continuations and a simple scheduler to ensure \"shreds\"\n (threads in Ruck) are woken at precisely the right time according\n to its virtual clock. Schedulers can map virtual time to samples\n in a WAV file, real time, time in a MIDI file, or anything else\n by overriding \"sim_to\" in the Shreduler class.\n \n A small library of useful unit generators and plenty of examples\n are provided. See the README or the web page for details.\n"
21
+ description: " Ruck uses continuations and a simple scheduler to ensure \"shreds\"\n (Ruck threads) are woken at precisely the right time according\n to its virtual clock. Schedulers can map virtual time to samples\n in a WAV file, real time, time in a MIDI file, or anything else\n by overriding \"sim_to\" in the Shreduler class.\n"
17
22
  email: tom@alltom.com
18
- executables:
19
- - ruck_glapp
20
- - ruck_midi
21
- - ruck_sleep
22
- - ruck_ugen
23
+ executables: []
24
+
23
25
  extensions: []
24
26
 
25
27
  extra_rdoc_files:
@@ -29,38 +31,8 @@ files:
29
31
  - README
30
32
  - Rakefile
31
33
  - VERSION
32
- - bin/ruck_glapp
33
- - bin/ruck_midi
34
- - bin/ruck_sleep
35
- - bin/ruck_ugen
36
- - examples/glapp/ex01.rb
37
- - examples/glapp/ex02.rb
38
- - examples/glapp/ex03.rb
39
- - examples/midi/ex01.rb
40
- - examples/midi/ex02.rb
41
- - examples/ugen/ex01.rb
42
- - examples/ugen/ex02.rb
43
- - examples/ugen/ex03.rb
44
- - examples/ugen/ex04.rb
45
- - examples/ugen/ex05.rb
46
- - examples/ugen/ex06.rb
47
- - examples/ugen/ex07.rb
48
- - examples/ugen/ex08.rb
49
- - examples/ugen/ex09.rb
50
- - examples/ugen/ex10.rb
51
- - examples/ugen/ex11.rb
52
- - examples/ugen/ex12.rb
53
34
  - lib/ruck.rb
54
- - lib/ruck/bench.rb
55
- - lib/ruck/misc/linkage.rb
56
- - lib/ruck/misc/metaid.rb
57
- - lib/ruck/misc/pcm_time_helpers.rb
58
- - lib/ruck/misc/riff.rb
59
- - lib/ruck/misc/wavparse.rb
60
35
  - lib/ruck/shreduling.rb
61
- - lib/ruck/ugen/general.rb
62
- - lib/ruck/ugen/oscillators.rb
63
- - lib/ruck/ugen/wav.rb
64
36
  - ruck.gemspec
65
37
  has_rdoc: true
66
38
  homepage: http://github.com/alltom/ruck
@@ -75,36 +47,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
47
  requirements:
76
48
  - - ">="
77
49
  - !ruby/object:Gem::Version
50
+ segments:
51
+ - 0
78
52
  version: "0"
79
- version:
80
53
  required_rubygems_version: !ruby/object:Gem::Requirement
81
54
  requirements:
82
55
  - - ">="
83
56
  - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
84
59
  version: "0"
85
- version:
86
60
  requirements: []
87
61
 
88
62
  rubyforge_project:
89
- rubygems_version: 1.3.5
63
+ rubygems_version: 1.3.6
90
64
  signing_key:
91
65
  specification_version: 3
92
66
  summary: "strong timing for Ruby: cooperative threads on a virtual clock"
93
- test_files:
94
- - examples/glapp/ex01.rb
95
- - examples/glapp/ex02.rb
96
- - examples/glapp/ex03.rb
97
- - examples/midi/ex01.rb
98
- - examples/midi/ex02.rb
99
- - examples/ugen/ex01.rb
100
- - examples/ugen/ex02.rb
101
- - examples/ugen/ex03.rb
102
- - examples/ugen/ex04.rb
103
- - examples/ugen/ex05.rb
104
- - examples/ugen/ex06.rb
105
- - examples/ugen/ex07.rb
106
- - examples/ugen/ex08.rb
107
- - examples/ugen/ex09.rb
108
- - examples/ugen/ex10.rb
109
- - examples/ugen/ex11.rb
110
- - examples/ugen/ex12.rb
67
+ test_files: []
68
+
data/bin/ruck_glapp DELETED
@@ -1,162 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
-
4
- # requires glapp gem
5
- # sudo gem install alltom-glapp
6
- # see http://alltom.com/pages/glapp for more details
7
- # UPDATE: ugh, github stopped producing gems.
8
- # find a way to get it on your own 'til I fix that.
9
-
10
- require "ruck"
11
-
12
- require "rubygems"
13
- require "glapp"
14
-
15
- class GLAppShreduler < Ruck::Shreduler
16
- def initialize
17
- @shred_queues = {}
18
- [:frame,
19
- :key_down, :key_up,
20
- :mouse_down, :mouse_up, :mouse_move].each do |q|
21
- @shred_queues[q] = []
22
- end
23
- super
24
- end
25
-
26
- def starting
27
- @start_time = Time.now
28
- end
29
-
30
- def actual_now
31
- Time.now - @start_time
32
- end
33
-
34
- def sleep_current_til(queue)
35
- shred = current_shred
36
- @shreds.delete(shred)
37
- @shred_queues[queue] << shred
38
- shred.yield(0)
39
-
40
- @ev
41
- end
42
-
43
- def raise_event(ev, queue)
44
- # should use actual_now,
45
- # but we don't want to put it into the future
46
- new_now = actual_now
47
- new_now = [new_now, next_shred.now].min if next_shred
48
- @now = new_now
49
-
50
- @ev = ev # returned by sleep_current_til
51
-
52
- shreds = @shred_queues[queue]
53
- @shred_queues[queue] = []
54
-
55
- shreds.each do |shred|
56
- shred.now = new_now
57
- @shreds << shred
58
- invoke_shred shred
59
- end
60
- end
61
-
62
- def catch_up
63
- while shreds.length > 0 && next_shred.now < actual_now
64
- run_one
65
- end
66
- end
67
- end
68
-
69
- module ShredLocal
70
- def spork(name = "unnamed", &shred)
71
- SHREDULER.spork(name, &shred)
72
- end
73
-
74
- def wait(seconds)
75
- SHREDULER.current_shred.yield(seconds)
76
- end
77
-
78
- def wait_for_frame
79
- SHREDULER.sleep_current_til(:frame)
80
- end
81
-
82
- def wait_for_key_down
83
- SHREDULER.sleep_current_til(:key_down)
84
- end
85
-
86
- def wait_for_key_up
87
- SHREDULER.sleep_current_til(:key_down)
88
- end
89
-
90
- def wait_for_mouse_down
91
- SHREDULER.sleep_current_til(:mouse_down)
92
- end
93
-
94
- def wait_for_mouse_up
95
- SHREDULER.sleep_current_til(:mouse_up)
96
- end
97
-
98
- def wait_for_mouse_move
99
- SHREDULER.sleep_current_til(:mouse_move)
100
- end
101
- end
102
-
103
- class MySketch
104
- include GLApp
105
-
106
- def setup
107
- ARGV.each do |filename|
108
- SHREDULER.spork(filename) do
109
- require filename
110
- end
111
- end
112
- @events = []
113
-
114
- SHREDULER.starting
115
- end
116
-
117
- def draw
118
- @events.each do |pair|
119
- ev, queue = pair
120
- SHREDULER.raise_event ev, queue
121
- end
122
- @events = []
123
-
124
- SHREDULER.catch_up # execute shreds whose time came while drawing previous frame
125
-
126
- SHREDULER.raise_event Object.new, :frame
127
- end
128
-
129
- def keyboard_down(key, modifiers)
130
- @events << [Struct.new(:key).new(key), :key_down]
131
- end
132
-
133
- def keyboard_up(key, modifiers)
134
- @events << [Struct.new(:key).new(key), :key_up]
135
- end
136
-
137
- def special_keyboard_down(key, modifiers)
138
- @events << [Struct.new(:key).new(key), :key_down]
139
- end
140
-
141
- def special_keyboard_up(key, modifiers)
142
- @events << [Struct.new(:key).new(key), :key_up]
143
- end
144
-
145
- def mouse_click(button, state, x, y)
146
- if state == 0
147
- @events << [Struct.new(:button, :x, :y).new(button, x, y), :mouse_down]
148
- else
149
- @events << [Struct.new(:button, :x, :y).new(button, x, y), :mouse_up]
150
- end
151
- end
152
-
153
- def mouse_motion(x, y)
154
- @events << [Struct.new(:x, :y).new(x, y), :mouse_move]
155
- end
156
- end
157
-
158
- SHREDULER = GLAppShreduler.new
159
-
160
- include GLApp::Helpers
161
- include ShredLocal
162
- MySketch.new.show 800, 600, "My Sketch"