diff options
Diffstat (limited to 'src/audio')
| -rw-r--r-- | src/audio/audio.cc | 6 | ||||
| -rw-r--r-- | src/audio/audio.h | 6 | ||||
| -rw-r--r-- | src/audio/ring_buffer.cc | 5 | ||||
| -rw-r--r-- | src/audio/ring_buffer.h | 12 | ||||
| -rw-r--r-- | src/audio/tracker.cc | 10 |
5 files changed, 31 insertions, 8 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc index 67345cf..74536e5 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -172,6 +172,12 @@ float audio_get_playback_time() { (RING_BUFFER_SAMPLE_RATE * RING_BUFFER_CHANNELS); } +float audio_get_render_time() { + const int64_t total_samples = g_ring_buffer.get_total_written(); + return (float)total_samples / + (RING_BUFFER_SAMPLE_RATE * RING_BUFFER_CHANNELS); +} + float audio_get_realtime_peak() { if (g_audio_backend == nullptr) { return 0.0f; diff --git a/src/audio/audio.h b/src/audio/audio.h index 14fe615..e063a57 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -27,8 +27,14 @@ void audio_start(); // Starts the audio device callback void audio_render_ahead(float music_time, float dt); // Get current playback time (in seconds) based on samples consumed +// This is the ring buffer READ position (what's being played NOW) float audio_get_playback_time(); +// Get current render time (in seconds) based on samples written +// This is the ring buffer WRITE position (where we're currently rendering) +// Use this for calculating sample-accurate trigger offsets +float audio_get_render_time(); + // Get peak amplitude of samples currently being played (real-time sync) // Returns: Peak amplitude in range [0.0, 1.0+] // Use this for visual effects to ensure audio-visual synchronization diff --git a/src/audio/ring_buffer.cc b/src/audio/ring_buffer.cc index a7e5d9e..7cedb56 100644 --- a/src/audio/ring_buffer.cc +++ b/src/audio/ring_buffer.cc @@ -9,7 +9,7 @@ AudioRingBuffer::AudioRingBuffer() : capacity_(RING_BUFFER_CAPACITY_SAMPLES), write_pos_(0), read_pos_(0), - total_read_(0) { + total_read_(0), total_written_(0) { memset(buffer_, 0, sizeof(buffer_)); } @@ -81,6 +81,9 @@ int AudioRingBuffer::write(const float* samples, int count) { write_pos_.store(remainder, std::memory_order_release); } + // Track total samples written for render timing + total_written_.fetch_add(to_write, std::memory_order_release); + return to_write; } diff --git a/src/audio/ring_buffer.h b/src/audio/ring_buffer.h index b19c1ea..324447a 100644 --- a/src/audio/ring_buffer.h +++ b/src/audio/ring_buffer.h @@ -42,6 +42,11 @@ class AudioRingBuffer { return total_read_.load(std::memory_order_acquire); } + // Get total samples written (for render timing) + int64_t get_total_written() const { + return total_written_.load(std::memory_order_acquire); + } + // Clear buffer (for seeking) void clear(); @@ -49,7 +54,8 @@ class AudioRingBuffer { float buffer_[RING_BUFFER_CAPACITY_SAMPLES]; int capacity_; // Total capacity in samples - std::atomic<int> write_pos_; // Write position (0 to capacity-1) - std::atomic<int> read_pos_; // Read position (0 to capacity-1) - std::atomic<int64_t> total_read_; // Total samples read (for playback time) + std::atomic<int> write_pos_; // Write position (0 to capacity-1) + std::atomic<int> read_pos_; // Read position (0 to capacity-1) + std::atomic<int64_t> total_read_; // Total samples read (for playback time) + std::atomic<int64_t> total_written_; // Total samples written (for render timing) }; 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) |
