Skip to content

feat(audio): audio mixer — mic + app passthrough into virtual mic #17

Description

@thewrz

Feedback Safety Guardrails (Critical)

A mixer that routes arbitrary sources into a virtual mic is one misconfigured link away from a feedback loop. HonkHonk must prevent this at multiple layers.

Layer 1: Graph-Level Prevention (router.rs)

Block feedback-creating links before they exist:

  • Self-routing filter: Never link HonkHonk Mix capture → HonkHonk Mix input. Check NODE_NAME / APP_NAME on both ends before creating any link.
  • Output-to-input cycle detection: Before creating a link, trace the graph to verify the source is not downstream of HonkHonk Mix capture. Example dangerous cycle: HonkHonk Mix capture → Discord → Discord output → HonkHonk Mix input.
  • Monitor port exclusion: Never route PipeWire monitor ports (*.monitor_FL/FR) into the mixer — these tap output streams and would create instant feedback if the output feeds back to input.
  • Whitelist by media.class: Only allow "Stream/Output/Audio" (app playback) and "Audio/Source" (mic/capture devices) as mixer inputs. Reject "Audio/Sink", "Stream/Input/Audio", and monitor ports.

Layer 2: Runtime Feedback Detection (engine.rs / mixer)

Detect feedback that slips past graph checks:

struct FeedbackDetector {
    rms_history: VecDeque<f32>,     // rolling window of RMS levels
    threshold_db: f32,              // sustained level that indicates feedback (e.g. -6dB)
    sustained_frames: usize,       // how many consecutive frames above threshold
    cooldown_frames: usize,        // frames to wait after clamping before re-enabling
}

Detection heuristics:

  • Sustained high RMS: If mix output RMS exceeds threshold for N consecutive frames (~200ms), likely feedback
  • Rapid amplitude growth: If RMS increases by >12dB within 50ms, likely feedback onset
  • Spectral concentration (stretch goal): Feedback loops produce narrow spectral peaks — detect via simple bandpass energy ratio

Layer 3: Emergency Clamping

When feedback is detected, act immediately:

  1. Hard clamp mix output to -24dB (not silence — allows user to hear something went wrong)
  2. Mute the suspected source — the most recently enabled mixer channel is the likely culprit
  3. Send AudioEvent::FeedbackDetected { suspected_source } to UI
  4. UI shows warning: "Feedback detected — [source name] was muted. Check your audio routing."
  5. Cooldown period: Don't re-enable the source for 2 seconds even if user toggles it back on
  6. Log the event with graph state for debugging

Layer 4: UI Guardrails

  • Warning on risky routes: If user tries to enable a source that looks like it could loop (e.g., an app whose output feeds the same device HonkHonk captures from), show a confirmation dialog
  • Mixer channel shows feedback indicator (red pulse, ⚠️ icon) when detector triggers
  • "Safe mode" toggle: When enabled, only allow mic + HonkHonk SFX — no app passthrough. Default on for first-time users.
  • Undo buffer: Last 3 routing changes stored so user can quickly revert if feedback occurs

Anti-Patterns to Avoid

Anti-pattern Why dangerous
Routing HonkHonk Mix monitor back to HonkHonk Mix input Instant feedback loop
Routing Discord output → mixer while Discord input = HonkHonk Mic Audio round-trip through Discord
Routing system audio sink monitor → mixer Captures everything including HonkHonk's own output
No volume limit on routed sources Multiple loud sources can clip/distort even without feedback

Metadata

Metadata

Assignees

No one assigned

    Labels

    audioPipeWire, decode, playback

    Type

    No type

    Projects

    Status
    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions