monome / crow

Crow speaks and listens and remembers bits of text. A scriptable USB-CV-II machine
GNU General Public License v3.0
162 stars 34 forks source link

Clock overhaul #477

Closed trentgill closed 1 year ago

trentgill commented 1 year ago

This fixes a bunch of inaccuracies in the clock.sync feature. The semantics remain the same, but now we maintain a separate list of clocks that are synchronized rather than slept.

This code was previously ported from the norns codebase and things got really wonky when converting from the threaded approach of linux to the direct millisecond tick approach on crow. Not sure if it was a matter of a faulty port, cpu limitations, or floating point truncations. Either way this seems to be working reliably & very accurately on crow hardware.

Solves an issure where changing clock.tempo would wildly change the beat count and cause long pauses in running clock routines. Additionally solves an issue where increasing tempo would cause every 2nd event to be skipped.

I think (read: hope) this solves an issue where long-running timelines would simply stop executing after some period of time (and then sometimes resume after a very long delay).

Going to overhaul the management of the clock pool (ie the list of all scheduled events) separately as it will drastically decrease the time the clock system takes each time a new 1ms tick happens. Hence not merging this immediately (hence Do Not Merge tag).


Also adds a new function clock.beats(n) which is in the same family as .sync and .sleep. It will sleep for the number of provided beats, providing the same function as the commonly used idiom clock.sleep(clock.get_beat_sec(beats)). I was planning to use it for timeline but the timing drifts due to CPU limitations & delays caused by the event engine. One would probably want to intersperse clock.sync(1) calls at a regular interval (<8 bars) to ensure things stay on beat (and we can't do that in timeline because there's no sense of when to sync).


Also noting that I committed these changes on top of the dev branch rather than main which is... kinda annoying, but we can probably work around that without doing the whole git cherrypick dance. It's just the last commit that is of interest to any reviewers.