fix: make channel state variables atomic to eliminate data races
Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
This commit is contained in:
@@ -19,11 +19,11 @@ typedef enum {
|
||||
|
||||
struct channel_t {
|
||||
atomic_int state;
|
||||
int prev_state;
|
||||
atomic_int prev_state;
|
||||
float loop_buffer[LOOP_BUF_SIZE];
|
||||
atomic_int loop_count;
|
||||
int record_pos;
|
||||
int playback_pos;
|
||||
atomic_int record_pos;
|
||||
atomic_int playback_pos;
|
||||
atomic_int active;
|
||||
jack_port_t *audio_in;
|
||||
jack_port_t *audio_out;
|
||||
|
||||
36
src/looper.c
36
src/looper.c
@@ -68,16 +68,16 @@ int process_callback(jack_nframes_t nframes, void *arg) {
|
||||
|
||||
int state = atomic_load(&channels[c].state);
|
||||
|
||||
if (state != channels[c].prev_state) {
|
||||
if (state != atomic_load(&channels[c].prev_state)) {
|
||||
switch (state) {
|
||||
case STATE_RECORD:
|
||||
channels[c].record_pos = 0;
|
||||
atomic_store(&channels[c].record_pos, 0);
|
||||
atomic_store(&channels[c].loop_count, 0);
|
||||
break;
|
||||
case STATE_LOOPING:
|
||||
if (channels[c].prev_state == STATE_RECORD && channels[c].record_pos > 0)
|
||||
atomic_store(&channels[c].loop_count, channels[c].record_pos);
|
||||
channels[c].playback_pos = 0;
|
||||
if (atomic_load(&channels[c].prev_state) == STATE_RECORD && atomic_load(&channels[c].record_pos) > 0)
|
||||
atomic_store(&channels[c].loop_count, atomic_load(&channels[c].record_pos));
|
||||
atomic_store(&channels[c].playback_pos, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -91,9 +91,9 @@ int process_callback(jack_nframes_t nframes, void *arg) {
|
||||
float *f_out = (float *)out;
|
||||
const float *f_in = (const float *)in;
|
||||
for (i = 0; i < nframes; i++) {
|
||||
if (channels[c].record_pos < LOOP_BUF_SIZE)
|
||||
channels[c].loop_buffer[channels[c].record_pos++] =
|
||||
f_in[i];
|
||||
int rp = atomic_fetch_add(&channels[c].record_pos, 1);
|
||||
if (rp < LOOP_BUF_SIZE)
|
||||
channels[c].loop_buffer[rp] = f_in[i];
|
||||
f_out[i] = f_in[i];
|
||||
}
|
||||
} else {
|
||||
@@ -106,9 +106,9 @@ int process_callback(jack_nframes_t nframes, void *arg) {
|
||||
if (lc > 0) {
|
||||
float *outf = (float *)out;
|
||||
for (i = 0; i < nframes; i++) {
|
||||
outf[i] = channels[c].loop_buffer[channels[c].playback_pos];
|
||||
channels[c].playback_pos =
|
||||
(channels[c].playback_pos + 1) % lc;
|
||||
int pp = atomic_load(&channels[c].playback_pos);
|
||||
outf[i] = channels[c].loop_buffer[pp];
|
||||
atomic_store(&channels[c].playback_pos, (pp + 1) % lc);
|
||||
}
|
||||
} else {
|
||||
memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes);
|
||||
@@ -137,7 +137,7 @@ int process_callback(jack_nframes_t nframes, void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
channels[c].prev_state = state;
|
||||
atomic_store(&channels[c].prev_state, state);
|
||||
}
|
||||
|
||||
/* MIDI clock events – affect channel 0 only */
|
||||
@@ -197,10 +197,10 @@ int looper_init(jack_client_t *client) {
|
||||
/* channel 0 */
|
||||
channels[0].active = 1;
|
||||
atomic_store(&channels[0].state, STATE_IDLE);
|
||||
channels[0].prev_state = -1;
|
||||
atomic_store(&channels[0].prev_state, -1);
|
||||
channels[0].loop_count = 0;
|
||||
channels[0].record_pos = 0;
|
||||
channels[0].playback_pos = 0;
|
||||
atomic_store(&channels[0].record_pos, 0);
|
||||
atomic_store(&channels[0].playback_pos, 0);
|
||||
atomic_store_explicit(&channels[0].save_ring, NULL, memory_order_release);
|
||||
|
||||
channels[0].audio_in = jack_port_register(
|
||||
@@ -312,10 +312,10 @@ void looper_process_commands(jack_client_t *client) {
|
||||
if (frames > LOOP_BUF_SIZE) frames = LOOP_BUF_SIZE;
|
||||
memcpy(channels[0].loop_buffer, buf, frames * sizeof(float));
|
||||
atomic_store(&channels[0].loop_count, (int)frames);
|
||||
channels[0].record_pos = 0;
|
||||
channels[0].playback_pos = 0;
|
||||
atomic_store(&channels[0].record_pos, 0);
|
||||
atomic_store(&channels[0].playback_pos, 0);
|
||||
atomic_store(&channels[0].state, STATE_LOOPING);
|
||||
channels[0].prev_state = -1;
|
||||
atomic_store(&channels[0].prev_state, -1);
|
||||
free(buf);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to load loop.wav\n");
|
||||
|
||||
Reference in New Issue
Block a user