"JavaScript 타이머는 다음 일을 깨우고, 오디오 클럭은 실제로 언제 울릴지 정해."
증상: scheduler drift
playback 엔진에서 solo, 코드, 메트로놈은 같은 음악적 순간에 맞물려야 해. 각 voice가 자기 시작 시각과 JavaScript 타이머만으로 다음 이벤트를 정하면 callback 지연이 서로 다른 오차로 쌓일 수 있어. 메트로놈은 조금 앞서고 코드는 늦는 식으로 그루브가 헐거워져. 연습 도구에서는 작은 어긋남도 손이 믿고 따라갈 기준을 흔들어.
수정: anchored 오디오 클럭 하나
anchor 하나에서 소스 시간과 AudioContext.currentTime을 대응시키고, 모든 voice의 이벤트 시각을 같은 함수로 계산해. lookahead scheduler는 setTimeout이나 setInterval로 자주 깨어나도 돼. 중요한 건 JavaScript timer가 실제 발음 시각을 결정하지 않는다는 점이야. 다음 window의 이벤트를 미리 찾아 Web Audio의 오디오 클럭 시각에 예약해야 해.
공유 timebase는 독립 scheduler가 쌓는 drift를 막아 주지만, 모든 소리가 자동으로 sample-perfect가 된다는 뜻은 아냐. asset 시작점, decode 지연, 신호 경로, 출력 장치 latency 때문에 고정 offset이 남을 수 있어. voice별 calibration과 실제 장치에서의 측정이 여전히 필요해. 클럭은 공통 기준을 주고, 보정은 각 경로의 차이를 맞춰.
one-model 아이디어를 시간에 적용해
Track 3의 단일 진실원이 다른 모자를 쓴 셈이야. 거기서는 음악 모델 하나에서 여러 view가 파생되고, 여기서는 timebase 하나에서 여러 voice의 시각이 파생돼. 다만 단일 소스는 관측 가능한 차이를 없애는 마법이 아니라, 차이를 설명하고 보정할 공통 좌표계야. 표류를 보면 먼저 권위 있는 시간원이 하나인지 확인하고, 그다음 경로별 latency를 측정해.