Getting my head around the Tidal scheduler

There were bugs in recent (unreleased) changes to the scheduler in Sound.Tidal.Stream, I thought I'd share my journey through it:

So (by default) every 1/20th of a second, tidal calculates 1/20th of a second's worth of events and sends them out. These events can include cps changes, which is a complication, but events are processed in order of onset time so that cps changes should be properly accounted for.

If the cps slows down, some events originally in that timeframe will go out of it, and be dropped and left for the next frame. If the cps speeds up, I fear some events will be lost, though. That probably deserves an issue.. (done)

The time an event is played, is the sum of a few things: the cycle position converted to system clock time, the latency config value, the 'nudge' control value, the 'nudgeAll' value, and the frametimespan value. I guess the latter makes sense, it makes sure that the overall latency value is never more than the frametimespan value.

There's two datatypes for tempo-related state, one about the cps, its phase (a system clock time and the cycle time at that point), the global nudge value, a network socket to send and receive on, and network address for the clock server. The other is clock-related state; the number of ticks (in frames, the duration of which is a constant config value), what time the clock started, the current calculation window in system clock time (start and stop system clock time) and cycle time (start and stop cycle position). I don't think there's really a good reason for these being passed around as two separate datatypes.

first (and once) have now been refactored to use the same code as the scheduler. It uses the same Tempo state as the main loop, but creates a 'fake' State object. Something was wrong with how this is handled, now solved. https://github.com/tidalcycles/Tidal/commit/ed5808685960a416194c09d9a25746a87c4f0a9b

3 Likes