Class: Livecode::Clock
- Inherits:
-
Object
- Object
- Livecode::Clock
- Defined in:
- lib/livecode/clock.rb
Overview
Clock
Clock is quite literally the beating pulse of Livecode, providing you with a way to sync up blocks of code.
Creating a clock
Clock.new takes two options; :tempo and :resolution. Tempo should be self-explanatory, and is measured in beats per minute (BPM). The default is 120 BPM. Resolution is the number of ticks per beat. The default is 4, which is the equivalent of 16th notes.
clock = Clock.new(:tempo => 120, :resolution => 4)
Control
clock.start # Starts the clock
clock.stop # Stops the clock, resets the tick
clock.pause # Pauses the clock, does not reset the tick
clock.restart # Restarts the clock
clock.running? # Check if the clock is running
If you lose track of your variables, you can use Clock.stop_all to stop all clocks.
Ticks
The clock is based on ticks, which is simply an incrementing counter. clock.tick will return the current tick, while clock.tick_length will return the length of one tick expressed in seconds.
The modulo operator is quite handy for turning ticks into rythmical structures:
bassdrum.play if clock.tick % 4 == 0 # Plays the bass drum on every beat
snare.play if clock.tick % 8 == 4 # ..and the snare on every other beat
Recipients
A recipient is a callback that will be triggered on every tick. Each recipient must have a unique name, and there’s a few ways to attach them. The following examples all do the same:
clock.recipients.add(:hihat, proc{|clock| hihat.play})
clock.recipients[:hihat] = proc{|clock| hihat.play})
clock.recipients.hihat = proc{|clock| hihat.play}
clock.recipients.hihat{|clock| hihat.play}
clock[:hihat] = proc{|clock| hihat.play}
clock.hihat = proc{|clock| hihat.play}
clock.hihat{|clock| hihat.play}
To remove a recipient, simply unset it:
clock.hihat = false
Furthermore, recipients can be muted, temporarily disabling them:
clock.mute(:bassdrum, :snare) # Mutes the bass drum and snare
clock.solo(:synth, :bass) # Solos the synth and bass
clock.enable_all # Re-enables all recipients
Remember: The callbacks are executed sequentially. If your callback takes more than a split second, you should wrap the code in it’s own thread to allow for parallel processing.
Clock will also try to compensate for the run time of your code in order to stay in sync.
Instance Attribute Summary collapse
-
#resolution ⇒ Object
Returns the value of attribute resolution.
-
#tempo ⇒ Object
Returns the value of attribute tempo.
-
#tick ⇒ Object
readonly
Returns the value of attribute tick.
Class Method Summary collapse
-
.clocks ⇒ Object
Return all registered clocks.
-
.register(clock) ⇒ Object
Register a new clock.
-
.stop_all ⇒ Object
Stop all clocks.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Clock
constructor
A new instance of Clock.
- #method_missing(method_name, *args, &block) ⇒ Object
-
#pause ⇒ Object
Pause the clock.
-
#recipients ⇒ Object
(also: #r)
Clock recipients.
-
#restart ⇒ Object
Restart the clock.
-
#running? ⇒ Boolean
Returns true if the clock is running.
-
#start ⇒ Object
(also: #play)
Start the clock.
-
#stop ⇒ Object
Stop the clock.
-
#tick! ⇒ Object
Run next tick.
-
#tick_length ⇒ Object
(also: #tl)
Length of a single tick (in seconds).
Constructor Details
#initialize(options = {}) ⇒ Clock
Returns a new instance of Clock.
94 95 96 97 98 99 100 101 102 |
# File 'lib/livecode/clock.rb', line 94 def initialize(={}) @tempo = [:tempo] || 120 @resolution = [:resolution] || 4 @tick = -1 @thread = nil @running = false @recipients = ClockRecipients.new Clock.register(self) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
164 165 166 |
# File 'lib/livecode/clock.rb', line 164 def method_missing(method_name, *args, &block) self.recipients.send(method_name, *args, &block) end |
Instance Attribute Details
#resolution ⇒ Object
Returns the value of attribute resolution.
91 92 93 |
# File 'lib/livecode/clock.rb', line 91 def resolution @resolution end |
#tempo ⇒ Object
Returns the value of attribute tempo.
91 92 93 |
# File 'lib/livecode/clock.rb', line 91 def tempo @tempo end |
#tick ⇒ Object (readonly)
Returns the value of attribute tick.
92 93 94 |
# File 'lib/livecode/clock.rb', line 92 def tick @tick end |
Class Method Details
.clocks ⇒ Object
Return all registered clocks.
81 82 83 |
# File 'lib/livecode/clock.rb', line 81 def clocks @@clocks ||= [] end |
.register(clock) ⇒ Object
Register a new clock.
76 77 78 |
# File 'lib/livecode/clock.rb', line 76 def register(clock) clocks << clock end |
.stop_all ⇒ Object
Stop all clocks.
86 87 88 |
# File 'lib/livecode/clock.rb', line 86 def stop_all clocks.each{|clock| clock.stop} end |
Instance Method Details
#pause ⇒ Object
Pause the clock.
136 137 138 139 |
# File 'lib/livecode/clock.rb', line 136 def pause @running = false self end |
#recipients ⇒ Object Also known as: r
Clock recipients
107 |
# File 'lib/livecode/clock.rb', line 107 def recipients; @recipients; end |
#restart ⇒ Object
Restart the clock.
142 143 144 145 |
# File 'lib/livecode/clock.rb', line 142 def restart @tick = -1 start end |
#running? ⇒ Boolean
Returns true if the clock is running.
148 149 150 |
# File 'lib/livecode/clock.rb', line 148 def running? @running ? true : false end |
#start ⇒ Object Also known as: play
Start the clock. Restarts if the clock is already running.
119 120 121 122 123 124 |
# File 'lib/livecode/clock.rb', line 119 def start @running = true stop_thread start_thread self end |
#stop ⇒ Object
Stop the clock.
128 129 130 131 132 133 |
# File 'lib/livecode/clock.rb', line 128 def stop stop_thread @tick = -1 @running = false self end |
#tick! ⇒ Object
Run next tick.
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/livecode/clock.rb', line 153 def tick! @tick += 1 recipients.each do |r|; unless r.silenced? if r.kind_of?(Proc) r.call(self) elsif r.respond_to?(:tick) r.tick(self) end end; end end |
#tick_length ⇒ Object Also known as: tl
Length of a single tick (in seconds).
111 112 113 114 115 |
# File 'lib/livecode/clock.rb', line 111 def tick_length tl = (1/(@tempo.to_f/60))/@resolution tl = 0.00000001 if tl <= 0 tl end |