2-midi-looping #3

Merged
boomjacky merged 17 commits from 2-midi-looping into master 2026-05-10 12:24:23 -04:00
Showing only changes of commit 85e828f461 - Show all commits

View File

@@ -30,32 +30,33 @@ spsc_queue_t cmd_queue;
static int pending_unregister_idx = -1;
static int pending_unregister_cycle = 0;
/* Deferred free of old channel array (must not free while RT thread may hold pointer) */
/* Deferred free of old channel array (must not free while RT thread may hold
* pointer) */
static struct channel_t *pending_old = NULL;
static int pending_old_cycle = 0;
/* Helper: grow the channel array so that index idx is valid */
static int ensure_capacity(jack_client_t *client, int idx) {
(void)client;
int cur_cap = atomic_load(&channel_capacity);
if (idx < cur_cap)
return 0;
int new_cap = cur_cap == 0 ? 8 : cur_cap;
while (new_cap <= idx)
new_cap *= 2;
struct channel_t *new_arr = calloc(new_cap, sizeof(struct channel_t));
if (!new_arr)
return -1;
/* copy existing channels */
if (cur_cap > 0)
memcpy(new_arr, atomic_load(&channels), cur_cap * sizeof(struct channel_t));
/* atomically publish new array, defer free of old */
struct channel_t *old = atomic_exchange(&channels, new_arr);
atomic_store(&channel_capacity, new_cap);
/* schedule old pointer for later deallocation (after RT cycle) */
pending_old = old;
pending_old_cycle = atomic_load(&global_rt_cycles);
(void)client;
int cur_cap = atomic_load(&channel_capacity);
if (idx < cur_cap)
return 0;
int new_cap = cur_cap == 0 ? 8 : cur_cap;
while (new_cap <= idx)
new_cap *= 2;
struct channel_t *new_arr = calloc(new_cap, sizeof(struct channel_t));
if (!new_arr)
return -1;
/* copy existing channels */
if (cur_cap > 0)
memcpy(new_arr, atomic_load(&channels), cur_cap * sizeof(struct channel_t));
/* atomically publish new array, defer free of old */
struct channel_t *old = atomic_exchange(&channels, new_arr);
atomic_store(&channel_capacity, new_cap);
/* schedule old pointer for later deallocation (after RT cycle) */
pending_old = old;
pending_old_cycle = atomic_load(&global_rt_cycles);
return 0;
}
static void apply_command(command_t cmd) {
@@ -182,7 +183,8 @@ int process_callback(jack_nframes_t nframes, void *arg) {
const float *f_in = (const float *)in;
for (i = 0; i < nframes; i++) {
if (active_channels[c].record_pos < LOOP_BUF_SIZE)
active_channels[c].loop_buffer[active_channels[c].record_pos++] = f_in[i];
active_channels[c].loop_buffer[active_channels[c].record_pos++] =
f_in[i];
f_out[i] = f_in[i];
}
} else {
@@ -194,9 +196,11 @@ int process_callback(jack_nframes_t nframes, void *arg) {
if (active_channels[c].loop_count > 0) {
float *outf = (float *)out;
for (i = 0; i < nframes; i++) {
outf[i] = active_channels[c].loop_buffer[active_channels[c].playback_pos];
outf[i] =
active_channels[c].loop_buffer[active_channels[c].playback_pos];
active_channels[c].playback_pos =
(active_channels[c].playback_pos + 1) % active_channels[c].loop_count;
(active_channels[c].playback_pos + 1) %
active_channels[c].loop_count;
}
} else {
memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes);
@@ -404,7 +408,8 @@ void looper_process_commands(jack_client_t *client) {
}
}
/* Deferred free of old channel array wait until RT thread has seen new pointer */
/* Deferred free of old channel array wait until RT thread has seen new
* pointer */
if (pending_old != NULL) {
int current_cycle = atomic_load(&global_rt_cycles);
if (current_cycle - pending_old_cycle >= 1) {