From b43d31779684b259bea42999743804c265a54b89 Mon Sep 17 00:00:00 2001 From: skal Date: Sat, 7 Feb 2026 21:50:44 +0100 Subject: fix(audio): Prevent events from triggering one frame early Events were triggering 16ms early in miniaudio playback because music_time was advanced at the START of the frame, causing events to be checked against future time but rendered into the current frame. Fix: Delay music_time advancement until AFTER rendering audio for the frame. This ensures events at time T trigger during frame [T, T+dt], not [T-dt, T]. Sequence now: 1. tracker_update(current_music_time) - Check events at current time 2. audio_render_ahead(...) - Render audio for this frame 3. music_time += dt - Advance for next frame Result: Events now play on-beat, matching WAV dump timing. --- src/main.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/main.cc') diff --git a/src/main.cc b/src/main.cc index 89e21f1..4922d69 100644 --- a/src/main.cc +++ b/src/main.cc @@ -125,12 +125,13 @@ int main(int argc, char** argv) { } #endif - // Calculate delta time and advance music time at scaled rate + // Calculate delta time const float dt = (float)(t - g_last_physical_time); g_last_physical_time = t; - g_music_time += dt * g_tempo_scale; - // Pass music_time (not physical time) to tracker + // CRITICAL: Update tracker BEFORE advancing music_time + // This ensures events trigger in the correct frame, not one frame early + // Pass current music_time (not future time) to tracker g_audio_engine.update(g_music_time); // Fill ring buffer with upcoming audio (look-ahead rendering) @@ -138,6 +139,10 @@ int main(int argc, char** argv) { // acceleration/deceleration At 2.0x tempo, we consume 2x audio per physical // second, so we must render 2x per frame audio_render_ahead(g_music_time, dt * g_tempo_scale); + + // Advance music time AFTER rendering audio for this frame + // This prevents events from triggering one frame early + g_music_time += dt * g_tempo_scale; }; #if !defined(STRIP_ALL) -- cgit v1.2.3