# Arbitrary Number of Channels ## Overview Originally the looper had a fixed maximum of 16 channels (`MAX_CHANNELS = 16`). The limitation has been removed; channels are now stored in a **dynamically allocated array** that grows on demand. ## Implementation - The global `channels` is a pointer (`struct channel_t *_Atomic channels`) instead of a fixed‑size array. - An atomic variable `channel_capacity` tracks the allocated size. - Initial allocation is for 8 channels; when a channel index >= current capacity is needed, the array is doubled. - The old array is **not freed immediately** – it is kept alive for at least one real‑time audio cycle (using the same deferred mechanism as port unregistration) to guarantee that the RT callback never accesses freed memory. ## Key Files | File | Role | |--------------------|-----------------------------------------------------------| | `src/channel.h` | Removes `MAX_CHANNELS`, adds `channels` pointer declaration and `get_channels_array()` inline accessor. | | `src/looper.c` | Contains `ensure_capacity()`, deferred free, and replaces all fixed‑size loop bounds with `channel_capacity`. | | `src/channel.c` | Adapted to use the current array pointer atomically. | | `src/midi.c` | Uses `atomic_load(&channel_capacity)` for bounds checks. | ## Thread Safety During Resize 1. A new, larger array is allocated (`calloc`). 2. Existing channels are copied via `memcpy`. 3. The global `channels` pointer is swapped with `atomic_exchange`. 4. `channel_capacity` is updated. 5. The old pointer is stored in `pending_old` along with the current cycle count (`pending_old_cycle`). 6. In the main loop, `pending_old` is freed only after `global_rt_cycles` has advanced by at least 1, ensuring any RT callback that loaded the old pointer has finished. This is a lightweight RCU‑like pattern that avoids locks and keeps the RT path deterministic. ## Compatibility All existing MIDI commands and FIFO pipe commands work unchanged with the dynamic array. The maximum practical number of channels is limited only by available memory and JACK port limits (typically 1024 per client on modern systems).