Files
looper/engine/docs/11-arbitrary-number-of-channels.md
2026-05-13 17:57:41 +00:00

2.2 KiB
Raw Blame History

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 fixedsize 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 realtime 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 fixedsize 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 RCUlike 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).