From ea180f48287cbd12db38c6f46ddaf12d4afcc675 Mon Sep 17 00:00:00 2001 From: Loic Coenen Date: Mon, 4 May 2026 22:15:16 +0000 Subject: [PATCH] fix: add mutex to protect shared buffers in audio routing tests Co-authored-by: aider (deepseek/deepseek-coder) --- test_audio_routing.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/test_audio_routing.c b/test_audio_routing.c index 6cc5d16..9fc8668 100644 --- a/test_audio_routing.c +++ b/test_audio_routing.c @@ -56,6 +56,9 @@ static atomic_bool test_midi_pending; static float test_output_buffer[MAX_CHANNELS][MAX_SAMPLES]; static atomic_size_t test_output_count[MAX_CHANNELS]; +// Mutex to protect shared buffers between main thread and JACK callback +static pthread_mutex_t test_buffer_mutex = PTHREAD_MUTEX_INITIALIZER; + // ============================================================ // Test framework // ============================================================ @@ -78,6 +81,8 @@ static int test_process_callback(jack_nframes_t nframes, void *arg) { (void)arg; if (!atomic_load(&test_running)) return 0; + pthread_mutex_lock(&test_buffer_mutex); + // Write test audio to output ports (to be sent to looper) for (int ch = 0; ch < MAX_CHANNELS; ch++) { jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) @@ -130,6 +135,8 @@ static int test_process_callback(jack_nframes_t nframes, void *arg) { // Process MIDI events if needed } + pthread_mutex_unlock(&test_buffer_mutex); + return 0; } @@ -248,6 +255,8 @@ static void send_sine_wave(int channel, float frequency, float amplitude, jack_n jack_nframes_t sample_rate = jack_get_sample_rate(test_client); jack_nframes_t total_samples = (sample_rate * duration) / 1000; + pthread_mutex_lock(&test_buffer_mutex); + // Fill the shared input buffer for (jack_nframes_t i = 0; i < total_samples; i++) { test_audio_input[channel][i] = amplitude * sinf(2.0 * M_PI * frequency * i / sample_rate); @@ -255,6 +264,8 @@ static void send_sine_wave(int channel, float frequency, float amplitude, jack_n atomic_store(&test_audio_input_count[channel], total_samples); atomic_store(&test_audio_input_read[channel], 0); + pthread_mutex_unlock(&test_buffer_mutex); + // Wait for the JACK callback to consume the audio // (the callback runs in a separate thread) usleep(duration * 1000 + 100000); // duration ms + 100ms extra @@ -264,27 +275,40 @@ static void send_midi_note(int note, int velocity) { if (!test_client) return; if (atomic_load(&test_timeout)) return; + pthread_mutex_lock(&test_buffer_mutex); + // Store MIDI message for the JACK callback to send test_midi_buffer[0] = 0x90; // Note On, channel 0 test_midi_buffer[1] = note & 0x7F; test_midi_buffer[2] = velocity & 0x7F; atomic_store(&test_midi_pending, true); + pthread_mutex_unlock(&test_buffer_mutex); + usleep(100000); // 100ms to let JACK process } static float get_channel_rms(int channel) { + pthread_mutex_lock(&test_buffer_mutex); + size_t count = atomic_load(&test_output_count[channel]); - if (count == 0) return 0.0f; + if (count == 0) { + pthread_mutex_unlock(&test_buffer_mutex); + return 0.0f; + } double sum_sq = 0.0; for (size_t i = 0; i < count; i++) { sum_sq += test_output_buffer[channel][i] * test_output_buffer[channel][i]; } + + pthread_mutex_unlock(&test_buffer_mutex); return sqrtf(sum_sq / count); } static void clear_output_buffers(void) { + pthread_mutex_lock(&test_buffer_mutex); + for (int ch = 0; ch < MAX_CHANNELS; ch++) { atomic_store(&test_output_count[ch], 0); memset(test_output_buffer[ch], 0, sizeof(test_output_buffer[ch])); @@ -293,6 +317,8 @@ static void clear_output_buffers(void) { memset(test_audio_input[ch], 0, sizeof(test_audio_input[ch])); } atomic_store(&test_midi_pending, false); + + pthread_mutex_unlock(&test_buffer_mutex); } // ============================================================