Skip to content

feat(calls): verify echo cancellation on every call — call_audio_aec capability#172

Merged
quad341 merged 1 commit into
mainfrom
feat/aec-verify-97mlk2
Jul 4, 2026
Merged

feat(calls): verify echo cancellation on every call — call_audio_aec capability#172
quad341 merged 1 commit into
mainfrom
feat/aec-verify-97mlk2

Conversation

@quad341

@quad341 quad341 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Part of the reliability baseline (#167), bead tincan-97mlk.2 — AEC is the hard requirement: without echo suppression the far party hears themselves and the whole stack is moot. Until now nothing verified AEC was actually in the audio path; regressions were discovered by human far parties.

What this adds

  • call_audio.verify_aec_in_path() — inspects the live PipeWire graph (pw-link -l) and checks both echo-cancellation invariants (same pair iris's aec_audio.sh documents): the SCO downlink must feed an echo-cancel sink (far-party voice in the AEC reference) and the SCO uplink must be fed by the echo-cancelled source, not a raw mic. Also catches downlink→speaker bypass. Works regardless of who created the links (tincand fix(calls): SCO routing used invalid pw-link flags — never linked call audio (tincan-jukpc) #164, WirePlumber, or iris's bridge). TTS streams into the uplink are intended and not flagged.
  • call_audio_aec capability — set after routing resolves on every call, cleared on teardown; visible in GetStatus() for clients, evals, and the upcoming doctor check. Failures log a WARNING naming the offending nodes.
  • pw-link "File exists" now counts as already-linked success (pre-linked calls no longer read as routing failures).
  • First test coverage for the SCO routing path — the invalid-flags bug (fix(calls): SCO routing used invalid pw-link flags — never linked call audio (tincan-jukpc) #164) shipped because none existed — plus verifier and controller-hook tests.

Testing: full suite green. Live validation: place a call with iris's AEC up — GetStatus should show call_audio_aec: true; tear the AEC down mid-setup and it should go false with a WARNING naming the raw-mic path.

🤖 Generated with Claude Code

…capability (tincan-97mlk.2)

Echo-free calls are the make-or-break requirement of the tincan+iris
stack: without AEC the far party hears themselves and won't stay on the
call. Until now nothing verified the AEC was actually in the audio path —
a regression was only discovered when a human far party complained.

- call_audio.verify_aec_in_path(): inspects the live PipeWire link graph
  (pw-link -l) and checks both echo-cancellation invariants, regardless
  of who created the links (tincand, WirePlumber, or iris aec_audio.sh):
    1. REFERENCE — SCO downlink feeds an echo-cancel sink (far-party
       voice must be in the AEC reference)
    2. CLEAN MIC — SCO uplink is fed by the echo-cancelled source and
       NOT by a raw physical microphone (alsa_input*)
  Also flags downlink→speaker bypass. Agent TTS streams into the uplink
  are intended and not flagged. Recognizes both module-echo-cancel and
  iris_aec_* naming.
- CallController: after SCO routing resolves (or retries exhaust — the
  graph may have been routed by WirePlumber/iris), verify and expose the
  result as the new call_audio_aec capability + INFO/WARNING log.
  Teardown clears the capability and cancels a pending setup timer.
- call_audio: single _run_pw seam (testable); pw-link 'File exists'
  treated as already-linked success so pre-linked calls don't read as
  routing failures.
- tests: first coverage for the SCO routing path (the invalid-flags bug
  shipped because none existed), plus the verifier and controller hooks.

Co-Authored-By: Claude Fable 5 <[email protected]>
@quad341
quad341 merged commit 7499b9b into main Jul 4, 2026
1 check passed
@quad341
quad341 deleted the feat/aec-verify-97mlk2 branch July 4, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant