Skip to content

Commit

Permalink
feat: try to compensate link start phase differences
Browse files Browse the repository at this point in the history
This rewinds time by up to 1 bar to ensure the clock time is synced with the phase.
  • Loading branch information
thegamecracks committed Jun 18, 2024
1 parent 58e6168 commit fc4c2aa
Showing 1 changed file with 31 additions and 1 deletion.
32 changes: 31 additions & 1 deletion sardine_core/clock/link_clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ def __init__(
self._internal_time: float = 0.0
self._last_capture: Optional[link.SessionState] = None
self._phase: float = 0.0
self._link_phase: float = 0.0
self._playing: bool = False
self._tempo: float = float(tempo)
self._tidal_nudge: int = 0
self._link_time: int = 0
self._beats_per_cycle: int = 4
self._framerate: float = 1 / 20
self._paused_link_phase: float = 0.0
self._time_shift: float = 0.0

## VORTEX ################################################

Expand Down Expand Up @@ -151,11 +154,12 @@ def _capture_link_info(self, *, update_transport: bool):
playing: bool = s.isPlaying()
tempo: float = s.tempo()

self._internal_time = self._link_time / 1_000_000
self._internal_time = self._link_time / 1_000_000 + self._time_shift
self._beat = int(beat)
self._beat_duration = 60 / tempo
# Sardine phase is typically defined from 0.0 to the beat duration.
# Conversions are needed for the phase coming from the LinkClock.
self._link_phase = phase
self._phase = phase % 1 * self.beat_duration
self._playing, last_playing = playing, self._playing
self._tempo = tempo
Expand All @@ -167,6 +171,8 @@ def _capture_link_info(self, *, update_transport: bool):
self.env.pause()

def before_loop(self):
self._time_shift = 0.0

self._link = link.Link(self._tempo)
self._link.enabled = True
self._link.startStopSyncEnabled = True
Expand All @@ -180,3 +186,27 @@ def loop(self):

def after_loop(self):
self._link = None

def hook(self, event: str, *args):
super().hook(event, *args)

if self._link is None:
return
elif event == "pause":
# Remember the current phase so the next time the clock is resumed,
# we can rewind time so the phase appears continuous.
self._paused_link_phase = self._link_phase
elif event == "resume":
# Alternative formula: (-bpb + lp - plp) % -bpb
delta = (self._link_phase - self._paused_link_phase) % self.beats_per_bar
if delta > 0:
# Don't allow time to jump forward, rewind instead.
delta -= self.beats_per_bar

self._time_shift = delta * self.beat_duration

# We could also try to broadcast start/stop from sardine transport methods,
# but we don't have a way to prevent _capture_link_info() from triggering this.
#
# if event in ("pause", "resume"):
# self._link.setIsPlaying(event == "resume", self._link_time)

0 comments on commit fc4c2aa

Please sign in to comment.