summaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/audio.cc49
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;
}
}