move engine to engine/
This commit is contained in:
72
engine/docs/1-multichannel.md
Normal file
72
engine/docs/1-multichannel.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 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). |
|
||||
| 63 | **Unbind** – reset the bound channel back to **0**. |
|
||||
|
||||
> **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.
|
||||
> - To **unbind** (reset to channel 0), send `control + note 63`.
|
||||
|
||||
## 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