diff --git a/esp32/tasks/LNK-029.md b/esp32/tasks/LNK-029.md new file mode 100644 index 0000000..c81fcfa --- /dev/null +++ b/esp32/tasks/LNK-029.md @@ -0,0 +1,102 @@ +--- +id: LNK-029 +title: "Research: mixer FX-slot introspection + multi-slot / multi-param tempo control" +status: todo +assignee: null +priority: medium +tags: [link-firmware, osc, fx, mixer, research, needs-triage] +depends_on: [LNK-005] +created_at: 2026-07-04 +updated_at: 2026-07-04 +--- + +## Goal + +Scope what the device could do with mixer FX beyond today's single hardcoded +target. Today (LNK-005) we send BPM → `/fx//par/01 ,f` (delay-time param) +to **one** configured slot, send-only, assuming the slot holds a delay. This +ticket researches four questions before any implementation: + +1. **What can we read from the mixer about the FX slots?** +2. **What other parameters make sense to tempo-control?** +3. **How to handle multiple tempo-syncable effects at once** (e.g. a delay in one + slot and another effect with its own tap-tempo/rate in another)? +4. **Should we control more than one FX slot?** + +Output is a findings doc + a design recommendation, **not** code. + +## What we already know (grounding) + +- `/fx/N/type ,i` — the loaded **algorithm** per slot, index `[0,60]` + (`docs/xr18-xair-osc-cheatsheet.md`). This is the key introspection hook. +- `/fx/N/par/MM ,f` — per-algorithm parameters, `MM = 01..64`. Which `MM` is the + tempo/delay-time param **depends on the algorithm** (par/01 happens to be delay + time for the delay algorithms we target now). +- We are currently **send-only** and never read `/fx/N/type` — so we're blind to + what's actually loaded and just assume par/01. +- XR18 has 4 FX slots, X32 has 8 (`config_model_slot_max`). +- The receive/subscribe plumbing exists (`osc_in`, xremote — LNK-013), so reading + back mixer state is feasible, we just don't use it for FX. + +Scope note: this ticket is **X32-family only** (XR18/X32). Behringer **Wing** is a +different control protocol and is tracked separately in **LNK-030** (later). + +## Research questions + +### Q1 — FX-slot introspection +- Read `/fx/N/type` for each slot → know the algorithm. Can we also get a + human-readable name, or only the index? Build the **index → algorithm** table + for XR18 and X32 (they may differ). +- For each tempo-relevant algorithm, which `par/MM` is the tempo/delay-time param, + and what are its **units/encoding** (normalized float → ms? a note-division + enum? a raw ms value?). Does the XR/X32 FX expose a "tempo sync on/off" or a + "division" param we should set instead of writing a raw time? +- Can/should we **subscribe** (xremote) so we track slot type changes live and + avoid writing a delay-time to a slot the user just changed to reverb? + +### Q2 — which params are worth controlling +- Catalog tempo-syncable params across algorithms: delay time (delays), LFO rate + (chorus/flanger/phaser), reverb pre-delay, tremolo/auto-pan rate, gate/ducker + timing. Note which are musically useful to lock to Link tempo vs noise. +- Non-tempo params worth a look while we're here? (probably out of scope — keep + this ticket tempo-focused, list others as future.) + +### Q3 — multiple tempo-syncable effects at once +- If a user has a delay in slot 1 and, say, a tremolo/tap-tempo effect in slot 3, + both want the tempo. The device is the tempo authority — we'd write each slot's + tempo param directly (overriding the mixer's own tap-tempo). Confirm that's the + right model vs trying to drive the mixer's tap-tempo input. +- Different targets may want **different note divisions** (1/4 vs 1/8-dotted vs + 1/2). Implies a per-target division/multiplier, not one global BPM→ms. +- Encoding differs per algorithm (ms float vs division enum) — the per-target + mapping must carry the algorithm's param index + unit conversion. + +### Q4 — multi-slot control +- Extend config from a single `fx_slot` to a set of targets: each `{slot, + enabled, division, (auto-detected type → param index + unit)}`. +- Config/UI implications: the web + touch UIs, NVS schema, and validation grow + from one slot to N. How much of the mapping can be **auto-derived** from + `/fx/N/type` so the user just picks slots + divisions? +- Rate-limit / OSC-flood concerns when writing several params on every tempo + change (reuse LNK-011 bpm_publisher send-policy). + +## Deliverables (this is research) + +- [ ] `index → algorithm` tables for XR18 and X32, annotated with the tempo param + index + unit/encoding for each tempo-relevant algorithm. +- [ ] Recommendation: **auto-detect** FX type via `/fx/N/type` (+ optional + subscribe) vs **manual** per-slot config — with the tradeoffs. +- [ ] A proposed config/UI/NVS shape for N targets with per-target note division. +- [ ] A note on the tap-tempo question (write params directly vs drive tap input). +- [ ] Follow-on implementation tickets filed from the findings. + +## Notes + +- Rides on LNK-005 (current FX delay send), LNK-011 (send policy), LNK-013 + (`osc_in`/xremote read-back), and the phase/tempo pipeline validated in LNK-020. +- Reference: `docs/x32-osc-protocol.md`, `docs/xr18-xair-osc-cheatsheet.md`, + `docs/xr18-geq-osc.md`. Hardware to probe: the XR18 (and X32 if available) via + `osc_in` dumps of `/fx/N/type` and `/fx/N/par/*` while loading different + algorithms. +- Keep any resulting unit-conversion math (BPM + division → ms/enum) in a pure, + host-tested module, same pattern as the rest of the firmware. diff --git a/esp32/tasks/LNK-030.md b/esp32/tasks/LNK-030.md new file mode 100644 index 0000000..399d958 --- /dev/null +++ b/esp32/tasks/LNK-030.md @@ -0,0 +1,76 @@ +--- +id: LNK-030 +title: "Research: Behringer Wing support (different OSC protocol) for tempo/FX control" +status: todo +assignee: null +priority: low +tags: [link-firmware, osc, fx, mixer, wing, research, needs-triage] +depends_on: [LNK-005, LNK-029] +created_at: 2026-07-04 +updated_at: 2026-07-04 +--- + +## Goal + +Assess what it takes to support the **Behringer Wing** as a mixer target for +tempo/FX control, the way we support XR18/X32 today. The Wing is **not** an +X32-family device — different control protocol — so this is its own research +track, deliberately **later** than the X32/XR18 FX work in LNK-029. Output is a +findings doc + a `MODEL_WING` feasibility recommendation, **not** code. + +## Why separate from LNK-029 + +LNK-029 (X32/XR18 FX-slot introspection + multi-slot tempo control) assumes the +**X32-family address tree** (`/fx/N/par/MM`, ports 10023/10024). The Wing uses a +different address/param model, so its findings won't port. It's also farther down +the roadmap — keep it from blocking the X32/XR18 work. Reuse LNK-029's *method* +(introspect FX type → map tempo param → fan out to N targets with per-target note +division), just re-answered for the Wing. + +## What we know today (grounding) + +- Model support is XR18/X32 only: `MODEL_XR18=1`, `MODEL_X32=2` + (`app_config.h`); `config_model_port` → X32:10023 / XR18:10024; + `config_model_slot_max` → X32:8 / XR18:4. +- The OSC layer (`osc_out`/`osc_in`) is X32-dialect-specific. Adding a Wing means + either parameterizing that layer or adding a **separate Wing OSC dialect + module** behind the existing `tempo_source`→OSC seam. + +## Research questions + +- **Protocol dialect.** The Wing speaks its own control protocol (OSC-style plus a + text/`$`-style command channel) with a different address tree, node/param model, + and encoding. Confirm: control UDP port(s); whether plain OSC suffices or the + node protocol is required; how FX params are addressed and encoded + (name-addressed nodes vs numeric par indices; value units). +- **FX topology.** Confirm the Wing's FX slot count and effect set (more slots and + a different "premium" effect set than X32's verb/delay), which effects are + tempo-syncable, and how each tempo param is expressed (ms vs beat-division vs a + sync/tap node). +- **Introspection.** Does the Wing expose richer read-back (effect type/name per + slot, param metadata) than X32's `/fx/N/type`? If so, auto-detection may be + *cleaner* on Wing. +- **Firmware integration.** What `MODEL_WING` needs: a new model id + port in + `config_model_port`/`config_model_slot_max`, and how much of LNK-029's Q1–Q4 + (introspection, param catalog, multi-slot fan-out, per-target divisions) is + reusable vs Wing-specific. Estimate: parameterize `osc_out`/`osc_in` vs a new + dialect module. +- **Discovery/connection.** Confirm a Wing is reached the same way as the X32 + (user-set mixer IP) or needs different discovery. + +## Deliverables (this is research) + +- [ ] Wing control port(s) + address/encoding model documented (with real dumps + from a Wing if one is available). +- [ ] Wing FX topology: slot count, tempo-syncable effects, tempo-param encoding. +- [ ] Introspection capability assessment (vs X32 `/fx/N/type`). +- [ ] `MODEL_WING` feasibility + integration recommendation: parameterize the + existing OSC layer vs a separate Wing dialect module behind the seam; how + much of LNK-029 is reusable. +- [ ] Follow-on Wing implementation ticket(s) filed from the findings. + +## Notes + +- Do the X32/XR18 research (LNK-029) first; use its structure as the template. +- Needs a Wing on the bench (or its documented protocol) to dump `/fx` state. +- Keep any tempo→param unit math in a pure, host-tested module, same as the rest.