diff --git a/src/channel.h b/src/channel.h index 109c716..89580bc 100644 --- a/src/channel.h +++ b/src/channel.h @@ -21,7 +21,7 @@ struct channel_t { atomic_int state; int prev_state; float loop_buffer[LOOP_BUF_SIZE]; - int loop_count; + atomic_int loop_count; int record_pos; int playback_pos; atomic_int active; diff --git a/src/looper.c b/src/looper.c index fd45f04..8f4182c 100644 --- a/src/looper.c +++ b/src/looper.c @@ -72,11 +72,11 @@ int process_callback(jack_nframes_t nframes, void *arg) { switch (state) { case STATE_RECORD: channels[c].record_pos = 0; - channels[c].loop_count = 0; + atomic_store(&channels[c].loop_count, 0); break; case STATE_LOOPING: if (channels[c].prev_state == STATE_RECORD && channels[c].record_pos > 0) - channels[c].loop_count = channels[c].record_pos; + atomic_store(&channels[c].loop_count, channels[c].record_pos); channels[c].playback_pos = 0; break; default: @@ -102,12 +102,13 @@ int process_callback(jack_nframes_t nframes, void *arg) { break; case STATE_LOOPING: - if (channels[c].loop_count > 0) { + int lc = atomic_load(&channels[c].loop_count); + 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) % channels[c].loop_count; + (channels[c].playback_pos + 1) % lc; } } else { memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes); @@ -130,7 +131,7 @@ int process_callback(jack_nframes_t nframes, void *arg) { // push loop output into save ring if saving (atomic load) RingBuf *r = (RingBuf *)atomic_load_explicit(&channels[c].save_ring, memory_order_acquire); if (r != NULL) { - if (state == STATE_LOOPING && channels[c].loop_count > 0) { + if (state == STATE_LOOPING && atomic_load(&channels[c].loop_count) > 0) { float *outf = (float *)out; ring_write(r, outf, nframes); } @@ -236,7 +237,8 @@ static void *writer_thread(void *arg) { unsigned sr = (unsigned)global_sample_rate; if (sr == 0) sr = 48000; - float *outbuf = malloc((size_t)ch->loop_count * sizeof(float)); + int lc = atomic_load(&ch->loop_count); + float *outbuf = malloc((size_t)lc * sizeof(float)); if (!outbuf) { ring_destroy(ring); free(ring); @@ -244,7 +246,7 @@ static void *writer_thread(void *arg) { return NULL; } size_t collected = 0; - size_t want = (size_t)ch->loop_count; + size_t want = (size_t)lc; while (collected < want) { size_t got = ring_read(ring, outbuf + collected, want - collected); collected += got; @@ -253,7 +255,7 @@ static void *writer_thread(void *arg) { nanosleep(&req, NULL); } } - wav_write(path, outbuf, ch->loop_count, sr); + wav_write(path, outbuf, (unsigned)lc, sr); free(outbuf); ring_destroy(ring); @@ -307,7 +309,7 @@ void looper_process_commands(jack_client_t *client) { if (wav_read("loop.wav", &buf, &frames) == 0 && frames > 0) { if (frames > LOOP_BUF_SIZE) frames = LOOP_BUF_SIZE; memcpy(channels[0].loop_buffer, buf, frames * sizeof(float)); - channels[0].loop_count = (int)frames; + atomic_store(&channels[0].loop_count, (int)frames); channels[0].record_pos = 0; channels[0].playback_pos = 0; atomic_store(&channels[0].state, STATE_LOOPING); @@ -320,12 +322,13 @@ void looper_process_commands(jack_client_t *client) { /* ---------- save command (writer thread) ---------- */ if (atomic_exchange(&cmd_save, 0)) { + int lc = atomic_load(&channels[0].loop_count); if (atomic_load(&channels[0].state) == STATE_LOOPING && - channels[0].loop_count > 0 && + lc > 0 && channels[0].save_ring == NULL) { RingBuf *ring = (RingBuf*)malloc(sizeof(RingBuf)); if (ring) { - size_t sz = (size_t)channels[0].loop_count * 2; + size_t sz = (size_t)lc * 2; if (ring_init(ring, sz) == 0) { atomic_store_explicit(&channels[0].save_ring, (_Atomic RingBuf *)ring, memory_order_release); pthread_t th; diff --git a/tests/integration.c b/tests/integration.c index 9850a01..87a0929 100644 --- a/tests/integration.c +++ b/tests/integration.c @@ -819,7 +819,7 @@ static int test_remove_channel(void) { fprintf(stderr, " FAIL: send note 61 failed\n"); return 1; } - safe_usleep(1500000); + safe_usleep(3000000); /* verify channel1_input has disappeared */ ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0); int still_found = 0;