summaryrefslogtreecommitdiff
path: root/src/audio/audio.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/audio.cc')
-rw-r--r--src/audio/audio.cc53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc
index 6ee9782..7c0f490 100644
--- a/src/audio/audio.cc
+++ b/src/audio/audio.cc
@@ -5,6 +5,7 @@
#include "audio.h"
#include "audio_backend.h"
#include "miniaudio_backend.h"
+#include "ring_buffer.h"
#include "synth.h"
#include "util/asset_manager.h"
@@ -13,6 +14,9 @@
#include <stdio.h>
+// Global ring buffer for audio streaming
+static AudioRingBuffer g_ring_buffer;
+
// Global backend pointer for audio abstraction
static AudioBackend* g_audio_backend = nullptr;
static MiniaudioBackend g_default_backend;
@@ -67,6 +71,55 @@ void audio_start() {
g_audio_backend->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 =
+ (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);
+
+ 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];
+
+ // Render audio from synth
+ synth_render(temp_buffer, frames_to_render);
+
+ // Write to ring buffer
+ const int written = g_ring_buffer.write(temp_buffer, samples_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);
+ }
+
+ delete[] temp_buffer;
+ }
+ }
+}
+
+float audio_get_playback_time() {
+ const int64_t total_samples = g_ring_buffer.get_total_read();
+ return (float)total_samples /
+ (RING_BUFFER_SAMPLE_RATE * RING_BUFFER_CHANNELS);
+}
+
+// Expose ring buffer for backends
+AudioRingBuffer* audio_get_ring_buffer() {
+ return &g_ring_buffer;
+}
+
#if !defined(STRIP_ALL)
void audio_render_silent(float duration_sec) {
const int sample_rate = 32000;