summaryrefslogtreecommitdiff
path: root/src/audio/audio.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-26 10:09:34 +0100
committerskal <pascal.massimino@gmail.com>2026-03-26 10:09:34 +0100
commit8c5e41724fdfc3be24e95f48ae4b2be616404074 (patch)
tree052d8512b43ff4d41af66d71f5fa8dc7de0f609a /src/audio/audio.cc
parent26627e8b9fee3fb3b2ec6314fc5cf45620769fcb (diff)
fix(audio): P1-P3 fixes from audio code reviewHEADmain
P1 — correctness bugs: - tracker.cc: move delete[] loop before pool reset so guard condition is valid - audio_engine: replace tracker_reset() with tracker_init() in reset()/seek() so synth IDs are re-registered after synth_init() clears spectrogram slots - spectrogram_resource_manager: set spec.version in load_procedural() (was UB) P2 — minor bugs: - synth.cc: move pan clamp unconditionally before debug-only block - gen.cc: remove dead `freq` variable in generate_note_spectrogram() - tracker.cc: remove duplicate g_sample_synth_cache clear loop P3 — cleanup: - Replace hardcoded 32000.0f with RING_BUFFER_SAMPLE_RATE (5 sites) - audio.cc: extract clip_samples() helper, remove duplicated clip loops - audio_engine: inline update_silent(), remove no-op prewarm_for_time_range() - Remove stale comments: stdio.h include, NEW: labels, CACHING block, NOTE: - Move TODO(timing) drift notes from source to TODO.md handoff(Gemini): audio review implemented, 36/36 tests passing
Diffstat (limited to 'src/audio/audio.cc')
-rw-r--r--src/audio/audio.cc33
1 files changed, 12 insertions, 21 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc
index 89380cd..3b98452 100644
--- a/src/audio/audio.cc
+++ b/src/audio/audio.cc
@@ -16,6 +16,15 @@
#include <ctime>
#include <stdio.h>
+static void clip_samples(float* buf, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (buf[i] > 1.0f)
+ buf[i] = 1.0f;
+ if (buf[i] < -1.0f)
+ buf[i] = -1.0f;
+ }
+}
+
// Global ring buffer for audio streaming
static AudioRingBuffer g_ring_buffer;
@@ -99,12 +108,6 @@ void audio_render_ahead(float music_time, float dt, float target_fill) {
// Render in small chunks to keep synth time synchronized with tracker
// Chunk size: one frame's worth of audio (~16.6ms @ 60fps)
- // TODO(timing): CRITICAL BUG - Truncation here may cause 180ms drift over 63
- // beats (int) cast loses fractional samples: 0.333 samples/frame * 2560
- // frames = 853 samples = 27ms But observed drift is 180ms, so this is not the
- // only source (27ms < 180ms) NOTE: This is NOT a float vs double precision
- // issue - floats handle <500s times fine See also: tracker.cc BPM timing
- // calculation
const int chunk_frames = (int)(dt * RING_BUFFER_SAMPLE_RATE);
const int chunk_samples = chunk_frames * RING_BUFFER_CHANNELS;
@@ -176,13 +179,7 @@ void audio_render_ahead(float music_time, float dt, float target_fill) {
// Render directly to ring buffer (NO COPY, NO ALLOCATION)
synth_render(write_ptr, actual_frames);
- // Apply clipping in-place (Phase 2: ensure samples stay in [-1.0, 1.0])
- for (int i = 0; i < actual_samples; ++i) {
- if (write_ptr[i] > 1.0f)
- write_ptr[i] = 1.0f;
- if (write_ptr[i] < -1.0f)
- write_ptr[i] = -1.0f;
- }
+ clip_samples(write_ptr, actual_samples);
// Commit written data atomically
g_ring_buffer.commit_write(actual_samples);
@@ -208,13 +205,7 @@ void audio_render_ahead(float music_time, float dt, float target_fill) {
synth_render(second_ptr, second_frames);
- // Apply clipping to wrap-around region
- for (int i = 0; i < second_samples; ++i) {
- if (second_ptr[i] > 1.0f)
- second_ptr[i] = 1.0f;
- if (second_ptr[i] < -1.0f)
- second_ptr[i] = -1.0f;
- }
+ clip_samples(second_ptr, second_samples);
g_ring_buffer.commit_write(second_samples);
@@ -279,7 +270,7 @@ AudioRingBuffer* audio_get_ring_buffer() {
#if !defined(STRIP_ALL)
void audio_render_silent(float duration_sec) {
- const int sample_rate = 32000;
+ const int sample_rate = RING_BUFFER_SAMPLE_RATE;
const int chunk_size = 512;
int total_frames = (int)(duration_sec * sample_rate);
float buffer[chunk_size * 2]; // Stereo