diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-07 21:34:00 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-07 21:34:00 +0100 |
| commit | 727177329f833f76683b53570f3268c39b463e86 (patch) | |
| tree | a4e531c06e719ba8cf49df5436ecc5bdca955364 /src/audio/tracker.cc | |
| parent | f9c5e84f01d0d7d1c981db4a0594dee9986429c4 (diff) | |
This fixes irregular timing in miniaudio playback while WAV dump was correct.
ROOT CAUSE:
Sample offsets were calculated relative to the ring buffer READ position
(audio_get_playback_time), but should be calculated relative to the WRITE
position (where we're currently rendering). The write position is ~400ms
ahead of the read position (the lookahead buffer).
ISSUE TIMELINE:
1. tracker_update() gets playback_time (read pos, e.g., 0.450s)
2. Calculates offset for event at 0.500s: (0.500 - 0.450) * 32000 = 1600 samples
3. BUT: We're actually writing at 0.850s (write pos = read pos + 400ms buffer)
4. Event triggers at 0.850s + 1600 samples = 0.900s instead of 0.500s!
5. Result: Event is 400ms late!
The timing error was compounded by the fact that the playback position
advances continuously between tracker_update() calls (60fps), making the
calculated offsets stale by the time rendering happens.
SOLUTION:
1. Added total_written_ tracking to AudioRingBuffer
2. Added audio_get_render_time() to get write position
3. Updated tracker.cc to use render_time instead of playback_time for offsets
CHANGES:
- ring_buffer.h: Add get_total_written() method, total_written_ member
- ring_buffer.cc: Initialize and track total_written_ in write()
- audio.h: Add audio_get_render_time() function
- audio.cc: Implement audio_get_render_time() using get_total_written()
- tracker.cc: Use current_render_time for sample offset calculation
RESULT:
Sample offsets now calculated relative to where we're currently rendering,
not where audio is currently playing. Events trigger at exact times in both
WAV dump (offline) and miniaudio (realtime) playback.
VERIFICATION:
1. WAV dump: Already working (confirmed by user)
2. Miniaudio: Should now match WAV dump timing exactly
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/audio/tracker.cc')
| -rw-r--r-- | src/audio/tracker.cc | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/src/audio/tracker.cc b/src/audio/tracker.cc index 93a1c49..1cccc57 100644 --- a/src/audio/tracker.cc +++ b/src/audio/tracker.cc @@ -239,8 +239,9 @@ void tracker_update(float music_time_sec) { } // Step 2: Update all active patterns and trigger individual events - // Get current audio playback position for sample-accurate timing - const float current_playback_time = audio_get_playback_time(); + // Get current audio RENDER position (write position) for sample-accurate timing + // This is where we're currently writing to the ring buffer (~400ms ahead of playback) + const float current_render_time = audio_get_render_time(); const float SAMPLE_RATE = 32000.0f; // Audio sample rate for (int i = 0; i < MAX_SPECTROGRAMS; ++i) { @@ -265,8 +266,9 @@ void tracker_update(float music_time_sec) { const float event_trigger_time = active.start_music_time + (event.unit_time * unit_duration_sec); - // Calculate sample-accurate offset from current playback position - const float time_delta = event_trigger_time - current_playback_time; + // Calculate sample-accurate offset from current RENDER position (write pos) + // This is where we're currently writing to the buffer, not where playback is + const float time_delta = event_trigger_time - current_render_time; int sample_offset = (int)(time_delta * SAMPLE_RATE); // Clamp to 0 if negative (event is late, play immediately) |
