diff options
Diffstat (limited to 'src/audio/audio.cc')
| -rw-r--r-- | src/audio/audio.cc | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc index 7c0f490..779cb6c 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -73,39 +73,46 @@ void audio_start() { void audio_render_ahead(float music_time, float dt) { // Calculate how much audio is currently buffered - const int buffered_samples = g_ring_buffer.available_read(); - const float buffered_time = + int buffered_samples = g_ring_buffer.available_read(); + float buffered_time = (float)buffered_samples / (RING_BUFFER_SAMPLE_RATE * RING_BUFFER_CHANNELS); // Target: maintain look-ahead buffer const float target_lookahead = (float)RING_BUFFER_LOOKAHEAD_MS / 1000.0f; - // Only render if we're below target - if (buffered_time < target_lookahead * 0.5f) { // Refill when half empty - // Calculate how many frames to render - const float time_to_render = target_lookahead - buffered_time; - const int frames_to_render = - (int)(time_to_render * RING_BUFFER_SAMPLE_RATE); + // Render in small chunks to keep synth time synchronized with tracker + // Chunk size: one frame's worth of audio (~16.6ms @ 60fps) + const int chunk_frames = (int)(dt * RING_BUFFER_SAMPLE_RATE); + const int chunk_samples = chunk_frames * RING_BUFFER_CHANNELS; - if (frames_to_render > 0) { - // Allocate temporary buffer (stereo) - const int samples_to_render = frames_to_render * RING_BUFFER_CHANNELS; - float* temp_buffer = new float[samples_to_render]; + // Keep rendering small chunks until buffer is full enough + while (buffered_time < target_lookahead) { + const int frames_to_render = chunk_frames; + if (frames_to_render <= 0) break; - // Render audio from synth - synth_render(temp_buffer, frames_to_render); + // Allocate temporary buffer (stereo) + const int samples_to_render = frames_to_render * RING_BUFFER_CHANNELS; + float* temp_buffer = new float[samples_to_render]; - // Write to ring buffer - const int written = g_ring_buffer.write(temp_buffer, samples_to_render); + // Render audio from synth (advances synth state incrementally) + synth_render(temp_buffer, frames_to_render); - // Notify backend of frames rendered (for testing/tracking) - if (g_audio_backend != nullptr) { - g_audio_backend->on_frames_rendered(written / RING_BUFFER_CHANNELS); - } + // Write to ring buffer + const int written = g_ring_buffer.write(temp_buffer, samples_to_render); - delete[] temp_buffer; + // Notify backend of frames rendered (for testing/tracking) + if (g_audio_backend != nullptr) { + g_audio_backend->on_frames_rendered(written / RING_BUFFER_CHANNELS); } + + delete[] temp_buffer; + + // Update buffered time for next iteration + buffered_time += (float)written / (RING_BUFFER_SAMPLE_RATE * RING_BUFFER_CHANNELS); + + // Safety: avoid infinite loop if buffer is full + if (written < samples_to_render) break; } } |
