ASCILINE/experiments
Nate 58626d7602 fix(#7): anchor the audio master clock so it never jumps backward (startup freeze)
Cold-start root cause: on a slow first load the <audio> element starts late, so
the audio-ready gate's wall-clock fallback has already advanced playback a second
or two by the time audio finally begins at currentTime≈0. The master clock then
snapped back toward 0, every buffered frame read as "in the future", and
renderFrame() deadlocked until audio caught up — the freeze. A refresh warms the
cache, audio starts immediately, the gap (and the freeze) vanish — which is why
reloading "fixes" it.

Fix: the first time audio is genuinely playing, capture the offset between the
wall clock and the audio clock and add it back, so the master clock follows
audio's *rate* without ever moving backward. When audio starts promptly the
offset is ~0, so normal playback is unchanged.

experiments/freeze_repro.js models a 2s-late audio start with a realistic jitter
buffer + 60fps render loop: the original code and a naive `currentTime > 0` guard
render 0-1 of ~96 frames after audio starts (frozen ~4s); the anchored clock
renders 96/96 smooth. Real-browser regression (muted Chrome): normal playback
unaffected at ~29 fps.
2026-06-14 01:24:05 -04:00
..
check_vectors.js feat: adaptive raw/zlib/delta frame codec (opt-in, backward compatible) 2026-06-13 02:22:29 -04:00
freeze_repro.js fix(#7): anchor the audio master clock so it never jumps backward (startup freeze) 2026-06-14 01:24:05 -04:00
gen_vectors.py feat: adaptive raw/zlib/delta frame codec (opt-in, backward compatible) 2026-06-13 02:22:29 -04:00
make_test_clips.sh feat: adaptive raw/zlib/delta frame codec (opt-in, backward compatible) 2026-06-13 02:22:29 -04:00
test_e2e.js feat: adaptive raw/zlib/delta frame codec (opt-in, backward compatible) 2026-06-13 02:22:29 -04:00