summaryrefslogtreecommitdiff
path: root/src/audio/synth.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/synth.cc')
-rw-r--r--src/audio/synth.cc51
1 files changed, 28 insertions, 23 deletions
diff --git a/src/audio/synth.cc b/src/audio/synth.cc
index 0161385..d584c62 100644
--- a/src/audio/synth.cc
+++ b/src/audio/synth.cc
@@ -5,7 +5,9 @@
#include "synth.h"
#include "audio/dct.h"
#include "audio/ola.h"
+#include "audio/ring_buffer.h"
#include "util/debug.h"
+#include <atomic>
#include <math.h>
#include <string.h> // For memset
@@ -32,18 +34,18 @@ struct Voice {
int start_sample_offset; // Samples to wait before producing audio output
- const volatile float* active_spectral_data;
+ const float* active_spectral_data;
};
static struct {
Spectrogram spectrograms[MAX_SPECTROGRAMS];
- const volatile float* active_spectrogram_data[MAX_SPECTROGRAMS];
+ std::atomic<const float*> active_spectrogram_data[MAX_SPECTROGRAMS];
bool spectrogram_registered[MAX_SPECTROGRAMS];
} g_synth_data;
static Voice g_voices[MAX_VOICES];
-static volatile float g_current_output_peak =
- 0.0f; // Global peak for visualization
+static std::atomic<float> g_current_output_peak{
+ 0.0f}; // Global peak for visualization
static float g_tempo_scale = 1.0f; // Playback speed multiplier
#if !defined(STRIP_ALL)
@@ -53,7 +55,7 @@ static float g_elapsed_time_sec = 0.0f; // Tracks elapsed time for event hooks
void synth_init() {
memset(&g_synth_data, 0, sizeof(g_synth_data));
memset(g_voices, 0, sizeof(g_voices));
- g_current_output_peak = 0.0f;
+ g_current_output_peak.store(0.0f, std::memory_order_relaxed);
#if !defined(STRIP_ALL)
g_elapsed_time_sec = 0.0f;
#endif /* !defined(STRIP_ALL) */
@@ -108,7 +110,8 @@ int synth_register_spectrogram(const Spectrogram* spec) {
for (int i = 0; i < MAX_SPECTROGRAMS; ++i) {
if (!g_synth_data.spectrogram_registered[i]) {
g_synth_data.spectrograms[i] = *spec;
- g_synth_data.active_spectrogram_data[i] = spec->spectral_data_a;
+ g_synth_data.active_spectrogram_data[i].store(
+ spec->spectral_data_a, std::memory_order_release);
g_synth_data.spectrogram_registered[i] = true;
return i;
}
@@ -128,8 +131,9 @@ float* synth_begin_update(int spectrogram_id) {
return nullptr;
}
- const volatile float* active_ptr =
- g_synth_data.active_spectrogram_data[spectrogram_id];
+ const float* active_ptr =
+ g_synth_data.active_spectrogram_data[spectrogram_id].load(
+ std::memory_order_acquire);
if (active_ptr == g_synth_data.spectrograms[spectrogram_id].spectral_data_a) {
return (float*)(g_synth_data.spectrograms[spectrogram_id].spectral_data_b);
@@ -144,18 +148,17 @@ void synth_commit_update(int spectrogram_id) {
return;
}
- const volatile float* old_active_ptr =
- g_synth_data.active_spectrogram_data[spectrogram_id];
+ const float* old_active_ptr =
+ g_synth_data.active_spectrogram_data[spectrogram_id].load(
+ std::memory_order_acquire);
const float* new_active_ptr =
(old_active_ptr ==
g_synth_data.spectrograms[spectrogram_id].spectral_data_a)
? g_synth_data.spectrograms[spectrogram_id].spectral_data_b
: g_synth_data.spectrograms[spectrogram_id].spectral_data_a;
- // Atomic swap using GCC/Clang builtins for thread safety
- __atomic_store_n(
- (const float**)&g_synth_data.active_spectrogram_data[spectrogram_id],
- new_active_ptr, __ATOMIC_RELEASE);
+ g_synth_data.active_spectrogram_data[spectrogram_id].store(
+ new_active_ptr, std::memory_order_release);
}
void synth_trigger_voice(int spectrogram_id, float volume, float pan,
@@ -215,7 +218,8 @@ void synth_trigger_voice(int spectrogram_id, float volume, float pan,
v.fractional_pos = 0.0f;
v.start_sample_offset = start_offset_samples;
v.active_spectral_data =
- g_synth_data.active_spectrogram_data[spectrogram_id];
+ g_synth_data.active_spectrogram_data[spectrogram_id].load(
+ std::memory_order_acquire);
#if !defined(STRIP_ALL)
// Notify backend of voice trigger event (for testing/tracking)
@@ -233,7 +237,7 @@ void synth_trigger_voice(int spectrogram_id, float volume, float pan,
void synth_render(float* output_buffer, int num_frames) {
// Faster decay for more responsive visuals
- g_current_output_peak *= 0.90f;
+ float peak = g_current_output_peak.load(std::memory_order_relaxed) * 0.90f;
for (int i = 0; i < num_frames; ++i) {
float left_sample = 0.0f;
@@ -258,7 +262,8 @@ void synth_render(float* output_buffer, int num_frames) {
// Fetch the latest active spectrogram pointer for this voice
v.active_spectral_data =
- g_synth_data.active_spectrogram_data[v.spectrogram_id];
+ g_synth_data.active_spectrogram_data[v.spectrogram_id].load(
+ std::memory_order_acquire);
const float* spectral_frame = (const float*)v.active_spectral_data +
(v.current_spectral_frame * DCT_SIZE);
@@ -286,14 +291,14 @@ void synth_render(float* output_buffer, int num_frames) {
output_buffer[i * 2 + 1] = right_sample;
// Update the peak with the new max (attack)
- g_current_output_peak = fmaxf(
- g_current_output_peak, fmaxf(fabsf(left_sample), fabsf(right_sample)));
+ peak = fmaxf(peak, fmaxf(fabsf(left_sample), fabsf(right_sample)));
}
+ g_current_output_peak.store(peak, std::memory_order_release);
+
#if !defined(STRIP_ALL)
- // Update elapsed time for event tracking (32000 Hz sample rate)
- const float sample_rate = 32000.0f;
- g_elapsed_time_sec += (float)num_frames / sample_rate;
+ // Update elapsed time for event tracking
+ g_elapsed_time_sec += (float)num_frames / RING_BUFFER_SAMPLE_RATE;
#endif /* !defined(STRIP_ALL) */
}
@@ -308,5 +313,5 @@ int synth_get_active_voice_count() {
}
float synth_get_output_peak() {
- return g_current_output_peak;
+ return g_current_output_peak.load(std::memory_order_acquire);
}