BeatSched

A beat capable function scheduler

Functions can be scheduled for precise execution using relative seconds, relative beats, absolute seconds or absolute beats. This class uses TempoClock for scheduling, and has some overlap of capabilities with that.

The TempoClock class is used to specify what the tempo is, and is used for all beat <-> second calculations. The default global TempoClock object is used, or you can use a specific TempoClock instance.

There is a default global BeatSched that can be addressed through class methods. It uses the SystemClock and the default global TempoClock. You may also create individual instances that maintain their own scheduling queues, tempii, and time epochs.

If using BeatSched instances you can clear the queue, only affecting your own events. If using the global BeatSched class, clearing the queue will affect everybody.

All of these methods exist as both

class (the default global scheduler)

eg.

BeatSched.tsched(seconds,function)

and instance methods (a specific scheduler).

eg.

beatSched = BeatSched.new;

beatSched.tsched(seconds,function)

The default clock used is the SystemClock, but you may also specify to use the AppClock.

tsched(seconds,function)

time based scheduling

delta specified in seconds

xtsched( seconds,function)

exclusive time based schedule

any previous messages scheduling using xtsched, xsched or xqsched will

be cancelled. this is incredibly useful in situations where several messages

might be sent and you only want the last one to be used as the final answer.

example: a monkey is hitting many buttons, changing his mind about which

sound to play next. this would result in many messages being stacked up all

at the same time, and the server would choke trying to execute them all.

so the x-methods are a kind of enforced monophony.

another example: a monophonic sequence plays successive notes, all using xsched,

you then switch to a different sequence. you don't want the note that was

scheduled from the previous sequence to happen. using one of the x-methods,

you don't have to worry about it, the old notes will be cleared when new ones

are scheduled.

sched(beats,function)

delta specified in beats

xsched(beats,function)

exclusive beat based scheduling

qsched(quantize,function)

will happen at the next even division ( 4.0 means on the downbeat of a 4/4 bar ),

or immediately if you happen to be exactly on a division.

xqsched(quantize,function)

exclusive quantized beat based scheduling

tschedAbs(time,function)

will happen at the time specified in seconds

schedAbs(beat,function)

will happen at the beat specified.

xblock

blocks any and all pending x-scheduled messages.

time

get the scheduler's time

time_(seconds)

set the scheduler's time

beat

get the scheduler's current beat

beat_(beat)

set the scheduler's current beat.

this is also used to start a "song": zero the beat, and all absolute times

previously scheduled events will be unpredictable

deltaTillNext(quantizeDivision)

returns the number of beats untiil the next quantizeDivision.

4.0 means the next even bar

16.0 means the next 4 bar cycle

0.25 means the next 16th note

tdeltaTillNext(quantizeDivision)

returns the number of seconds untiil the next beat quantizeDivision.

4.0 means the next even bar

16.0 means the next 4 bar cycle

0.25 means the next 16th note

clear

clear all scheduled events.

In the examples, remember to execute groups of code lines together.

b = BeatSched.new;

b.qsched(4.0,{ "hello".postln; });

b.qsched(4.0,{ "hello".postln; });

b.time; // since the app started

b.time = 0.0; // reset the time

b.time;

b.beat; // the beat is determined by the tempoClock

TempoClock.default.tempo = 2;

b.beat.postln;

TempoClock.default.tempo = 1;

b.beat.postln;

b.time = 0.0;

b.tschedAbs(4.0,{ "4 seconds absolute time".postln; });

b.tschedAbs(2.0,{ "2 seconds absolute time".postln; });

b.xsched(4.0, { "4 beats later".postln });

// cancels previous xsched

b.xsched(2.0, { "2 beats later".postln });

A little rounding error

(

TempoClock.default.tempo = 120 / 60.0;

d = Routine({

20.do({

var t;

t = BeatSched.global.tdeltaTillNext(4.0);

t.postln;

t.wait;

});

});

SystemClock.play(d);

)

at 5206.432346276 we ask for deltaTillNext 4

[ 5204, 4, 5206.432346276 ]

1.5676537239997

that would be

5206.432346276 + 1.5676537239997

// at 5208

5208

// but when the scheded event comes due:

[ 5204, 4, 5207.999072862 ]

0.00092713799949706

its appears to be slightly ahead of schedule, due

to rounding errors in the several math ops that have happened.

so the right answer is 0.00092713799949706

as far as BeatSched is concerned.

but if you try to loop like this, you will suffer from rounding errors.

mostly you would never set up a loop like this, mostly

you just want to know when the next even beat is so you can get your groove on.

Tempo.bpm_(120);

d = Routine({

"wait for the downbeat...".postln;

OSCSched.global.tdeltaTillNext(4.0).wait;

32.do({ arg i;

[i,BeatSched.beat].postln;

Tempo.beats2secs(1.0).wait;

});

});

SystemClock.play(d);