TimeKeeper is an optional utility class to help you keep track of time.
// This example shows the use of TimeKeeper to define a tempo and time
// signature, then produce beat events. The argument to timekeeper.Start
// expresses the alignment intent to guide the temporal alignment of
// separately launched scripts. Typical values are BeatDur and BarDur.
// Launch this example repeatedly to get the idea. Cancel individual
// fibers in the Audio Monitor panel.
let id = `f${this.GetId()}:`;
let ascene = await Ascene.BeginFiber(this);
let inst = ascene.NewAnode("FluidSynth");
ascene.Chain(inst, ascene.GetDAC());
await ascene.Sync();
const prog = Math.floor(10 + 10*Math.random());
console.log("Fluid prog " + prog);
inst.SetParam("prog0", prog);
let timekeeper = new TimeKeeper(ascene);
timekeeper.SetSignature(4, 4);
timekeeper.SetTempo(120);
const beatdur = timekeeper.BeatDur();
timekeeper.On("beat", (songpos) =>
{
if(songpos.CurrentBeatInBar() == 0)
inst.Note(60, 1, beatdur, songpos.Now());
else
inst.Note(58, .5, beatdur * .5, songpos.Now());
});
let align = timekeeper.BeatDur(); // vs timekeeper.BarDur()
await timekeeper.Start(align);
// this enables cancelation and updating via the Fibers panel.
const sleepDur = ascene.Seconds(1);
while(timekeeper.IsRunning())
{
await ascene.Wait(sleepDur);
let msg = yield;
if(msg == "_cancel_")
{
console.log(`${id} canceling`);
timekeeper.Stop();
}
}
console.log(`${id} script complete.`);
Simple example of acceleration and deceleration.
Example of scheduling a full bar worth of notes. It also shows how to play ball with the Fibers Panel enabling status update and cancellation.
Example of TkSection
to represent section durations, signature and tempo changes. Sections
are organized in an array and passed to timekeeper.Start()
.
let sections = [
new TkSection("A", [4,4], 120, 4),
new TkSection("B", [3,4], 120, 4, 2),
new TkSection("C", [4,4], [120,-.05], 4, 2),
];
await timekeeper.Start(align, sections);