docs: add multi-channel and bind feature documentation
Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
This commit is contained in:
@@ -0,0 +1,71 @@
|
|||||||
|
# Multi‑Channel & Bind Feature
|
||||||
|
|
||||||
|
The looper supports up to 16 independent channels (numbered 0–15).
|
||||||
|
Channel 0 is always present and connected to the `looper:input` / `looper:output` audio ports.
|
||||||
|
Additional channels can be created and removed dynamically using MIDI commands.
|
||||||
|
|
||||||
|
## MIDI Ports
|
||||||
|
|
||||||
|
- **`looper:control`** – receives MIDI note‑on events for channel management and state toggling.
|
||||||
|
- **`looper:clock`** – receives MIDI clock messages (0xFA, 0xFC, 0xFB) that affect channel 0 only.
|
||||||
|
|
||||||
|
## Control‑Key Modifier
|
||||||
|
|
||||||
|
Hold the **control key** (MIDI note 64) pressed *before* sending another note to put the looper in “command mode”.
|
||||||
|
While control‑key is active, the next note‑on (with velocity > 0) performs a special action instead of its direct mapping.
|
||||||
|
The control key is released either by sending note‑off (note 64 or any note) or by sending a note‑on while control‑key is already active (the action is performed and control‑key is cleared).
|
||||||
|
|
||||||
|
## Available Commands (under control key)
|
||||||
|
|
||||||
|
| Note | Action |
|
||||||
|
|------|----------------------------------------------------------------------------------------------|
|
||||||
|
| 0–15 | **Bind** the next `control+62` toggle to the channel with that index. |
|
||||||
|
| 60 | **Add** a new dynamic channel (creates `channelX_input` / `channelX_output` ports). |
|
||||||
|
| 61 | **Remove** the highest‑numbered active channel (excluding channel 0). |
|
||||||
|
| 62 | **Toggle** the current bound channel through its state machine: |
|
||||||
|
| | IDLE → RECORD → LOOPING → PAUSED → LOOPING → … (each press advances one step). |
|
||||||
|
|
||||||
|
> **Notes:**
|
||||||
|
> - The default bound channel is **0**. If you never send a bind command, `control+62` controls channel 0.
|
||||||
|
> - To bind a different channel, send `control + note <16>` (e.g., control + note 5 binds channel 5).
|
||||||
|
> - Bind is sticky – it stays until overwritten by another bind command.
|
||||||
|
> - There is **no unbind** command; you can rebind to channel 0 if needed.
|
||||||
|
|
||||||
|
## Direct Mapping (without control key)
|
||||||
|
|
||||||
|
For backward compatibility, the following notes work **without** the control‑key modifier:
|
||||||
|
|
||||||
|
| Note | Action |
|
||||||
|
|------|----------------------------------------------------------------------------------------------|
|
||||||
|
| 1 | Toggle channel 0 state (IDLE→RECORD→LOOPING→PAUSED→LOOPING…). |
|
||||||
|
| 60 | Add a dynamic channel (same as `control+60`). |
|
||||||
|
| 61 | Remove the highest‑numbered active channel (same as `control+61`). |
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
1. **Record a loop on channel 0 (using direct note 1)**
|
||||||
|
- Send note‑on, note 1, velocity 127 → channel 0 enters RECORD.
|
||||||
|
- Play some audio into `looper:input`.
|
||||||
|
- Send note‑on, note 1, velocity 127 again → channel 0 enters LOOPING.
|
||||||
|
- The recorded audio repeats indefinitely.
|
||||||
|
|
||||||
|
2. **Use the control‑key to toggle channel 0**
|
||||||
|
- Send `note‑on, note 64` (control key).
|
||||||
|
- Then send `note‑on, note 62` → toggles channel 0 (IDLE→RECORD).
|
||||||
|
- Send `note‑on, note 64` again, then `note‑on, note 62` again → RECORD→LOOPING.
|
||||||
|
|
||||||
|
3. **Add a new channel and bind it**
|
||||||
|
- Send `note‑on, note 64` + `note‑on, note 60` → creates channel 1.
|
||||||
|
- Send `note‑on, note 64` + `note‑on, note 1` → binds channel 1.
|
||||||
|
- Now `control+62` toggles channel 1 instead of channel 0.
|
||||||
|
- Record audio on channel 1 by sending `control+62` twice.
|
||||||
|
|
||||||
|
4. **Remove a dynamic channel**
|
||||||
|
- Send `note‑on, note 64` + `note‑on, note 61` → removes the highest‑numbered active channel (e.g., channel 1).
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The looper must be connected to a running JACK server.
|
||||||
|
- Channel buffers hold up to 5 seconds of audio at 48 kHz.
|
||||||
|
- After removal, the channel’s audio ports are unregistered on the next main‑loop cycle (deferred to avoid race conditions).
|
||||||
|
- The bind index is stored as an integer (0–15); values outside 0–15 are ignored (the note is processed as a command rather than a bind).
|
||||||
|
|||||||
Reference in New Issue
Block a user