Skip to content

Named input profiles: manage, calibrate, and reference multiple note-detection inputs (lead / rhythm / bass) #1012

Description

@topkoa

Vision

FeedBack can already score from multiple audio inputs — the desktop engine runs up to 8 independent source chains, and splitscreen can bind panels to extra capture devices. But managing those inputs is raw and single-input-minded: the Audio page models exactly one device+channel, splitscreen panels pick inputs by raw device name with a per-panel channel cycle and a manual ±5 ms latency nudge, and the tuner only listens to the primary input.

The proposal: named input profiles. You configure an input once — "Lead Guitar", "Bass", "Rhythm" — calibrate it, and then reference it by name everywhere:

  • Audio page: create/manage profiles, see live meters and tuner readouts for every connected instrument at once, run calibration per profile.
  • Splitscreen: each panel's input picker becomes a dropdown of profile names instead of raw device/channel controls.
  • Tuner: an input selector so each band member can tune their own instrument.

Band use case: lead guitar on interface A input 1, rhythm on input 2, bass on interface B — set up once, calibrated, referenced by name from then on.

What already exists (so this is mostly UX + plumbing, not engine work)

  • Engine (feedback-desktop): SourcePool holds up to 8 SourceChains; each has its own YIN pitch detector, optional ML polyphonic detector (Basic Pitch/ONNX), onset detector, chart-scoring NoteVerifier + ChordScorer, per-source gain/meters/monitor-mute, and per-source latency offsets (setVerifierAutoOffset + setVerifierUserOffset, summed). Up to 3 extra capture devices via ExtraInputs. The full per-source N-API/IPC surface (addSource, bindInputDevice, setSourceInputChannel, getSourcePitchDetection, getSourceNoteVerdicts, setSourceChart, …) is already exposed through the preload bridge.
  • note_detect: createNoteDetector({ ownSource: true, deviceKey, channel, verifierOffsetMs }) already allocates its own engine source per instance, and launchCalibration() already measures level / channel / latency (used by input_setup's onboarding wizard).
  • splitscreen: per-panel detectors with independent scoring already work — it's the selection UX (raw device names, channel cycling, manual nudge) that doesn't scale to a band.

What's missing: a naming + persistence + calibration-reuse layer, and consumers that speak it.

Proposed shape (open for discussion)

Profile = { id, name, icon, role (lead/rhythm/bass/any), deviceType, deviceName, channel, gainDb, calibratedOffsetMs, manualOffsetMs, noteDetection: { engine: "yin" | "ml" } }

  • Persisted desktop-side (userData JSON, feedback-input-profiles.json) since device identities are machine-local. Main process owns load/save; changes broadcast to all windows.
  • A small runtime registry (window.feedBackInputProfiles) published by the audio_engine plugin: list / acquire / release, owning the deviceKey 1..3 allocation + bindInputDevice refcounting so audio panel, splitscreen, tuner, and note_detect can't fight over extra-device slots.
  • role lets splitscreen auto-assign profiles to panels using the existing lead/rhythm/bass arrangement matching.
  • Zero visual change by default: the Audio page looks exactly as it does today until you press "+ Add input"; profiles then render as cards (name, device/channel, live meter, live pitch readout, Calibrate button).
  • Calibration reuses note_detect's existing wizard, targeted at a profile's device+channel, writing the measured offset/gain back into the profile.
  • Everything feature-detects across repos so each piece lands independently and degrades to today's behavior (e.g. splitscreen falls back to its current raw pickers when no profiles exist).

Rough phasing

  1. feedback-desktop: profile store + IPC (audio.profiles.* on the bridge) + a per-source gain export the engine is missing. Inert on its own.
  2. feedback-desktop (audio_engine panel): "+ Add input" → profile cards, live all-at-once meters/tuner readouts, runtime registry/allocator.
  3. note_detect: createNoteDetector({ profileId }) + launchCalibration({ profileId }) with write-back.
  4. splitscreen: per-panel profile dropdown (by name), prefs, role auto-assign.
  5. feedback (tuner): input selector listing profile names, reading per-source raw frames.

Open questions — input welcome

  1. Should profiles also be published into the audio-input capability domain as named sources (so input_setup / other capability consumers see them), or stay a separate desktop-side registry? The domain is single-select today; profiles are inherently multi-select.
  2. Offset model: calibrated + manual as separate summed fields (proposed) vs a single effective value?
  3. Should two profiles be allowed on the same device+channel (e.g. differently-calibrated variants)? Proposed: yes, with an informational badge.
  4. Per-profile detection engine (yin vs ml/Basic Pitch) — worth exposing in v1, or default yin everywhere and add later?
  5. Anything web-only worth doing? This design is desktop-first since multi-device capture is a desktop-bridge capability; the browser path (getUserMedia) stays single-input.

Detailed file-level plan exists (engine APIs verified against source); happy to share in a follow-up comment or split per-repo issues once the shape settles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions