Skip to content

Filter low-level background audio before streaming ASR - #993

Open
aaldrich wants to merge 2 commits into
altic-dev:mainfrom
aaldrich:feature/low-level-background-audio-filter
Open

aaldrich wants to merge 2 commits into
altic-dev:mainfrom
aaldrich:feature/low-level-background-audio-filter

Conversation

@aaldrich

@aaldrich aaldrich commented Sep 20, 2026

Copy link
Copy Markdown

Description

Add a separate, opt-in Filter Low-Level Background Audio preference that prevents sustained faint PCM from reaching streaming or final ASR.

This does not change Skip Silent Recordings. That preference retains its existing post-capture behavior for recordings up to four seconds. Keeping the controls independent avoids surprising users who enabled the older setting for its narrower purpose.

When enabled, the capture pipeline now:

  • evaluates 16 kHz mono PCM in 20 ms frames;
  • requires 40 ms of activity before opening;
  • preserves 160 ms of pre-roll and 360 ms of hangover to avoid clipping words;
  • withholds sustained low-level background audio from live previews and final transcription;
  • keeps raw capture readiness, level metering, and health reporting unchanged;
  • leaves dictionary-training capture unfiltered; and
  • returns an empty result through the existing no-audio path when no activity is accepted.

The preference is disabled by default to preserve current behavior for unusually quiet microphones. It is included in settings search and backup/restore, and older backups continue to decode without it.

Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Accepted design Discussion: #990

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac
  • Tested on macOS version: 26.6.2
  • Ran linter in private CI: swiftlint --strict --config .swiftlint.yml Sources Tests Package.swift
  • Ran formatter locally: swiftformat --config .swiftformat Sources
  • Ran tests in private Apple Silicon CI: full macOS/arm64 Xcode suite, 541 tests with 0 failures

Regression coverage includes:

  • sustained faint background rejection;
  • quiet speech immediately above the activity threshold;
  • speech onset and pre-roll;
  • isolated transient rejection;
  • long pauses between speech bursts;
  • arbitrary callback boundaries;
  • state reset between sessions;
  • independence from Skip Silent Recordings;
  • microphone-stall detection using raw pre-gate capture progress; and
  • settings backup/restore compatibility with older backups.

Latency benchmark on Apple Silicon:

  • normal 1,365-sample post-resample callback: 0 ms additional audio-delivery latency;
  • processing: 102 µs median / 138 µs p95;
  • p95 processing cost: 0.162% of the callback budget; and
  • bounded activation effect for smaller packets: +30 ms at 10 ms, +20 ms at 20 ms, 0 ms at 40 ms or larger.

Full report and method: https://github.com/aaldrich/FluidVoice/blob/pr-assets/low-level-background-audio-filter/latency-benchmark.md

Screenshots / Video

Filter Low-Level Background Audio setting

  • No UI/visual changes; screenshots/video are not applicable.

Notes

The setting is opt-in and disabled by default. Fixed conservative thresholds are used initially; an adaptive noise floor can be considered separately if broader hardware testing shows it is needed.

Developed with AI assistance, then manually reviewed and validated with synthetic regression tests, strict SwiftLint, the complete Apple Silicon test suite, real-world reproduction testing, and a dedicated latency benchmark. I will remain responsible for review feedback and maintenance of the contribution.

@greptile-apps

greptile-apps Bot commented Sep 20, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no outstanding correctness, security, or repository-rule issues identified.

Summary

This PR adds an opt-in speech-activity gate that prevents sustained faint PCM from reaching streaming and final ASR while preserving capture metering and diagnostics.

  • Adds the independently persisted, searchable background-audio filter preference.
  • Implements framed activity detection with attack, pre-roll, and hangover behavior.
  • Keeps dictionary-training capture unfiltered.
  • Updates capture-health monitoring to distinguish rejected PCM from stalled raw capture.
  • Adds regression tests for filtering, health assessment, and backup compatibility.

Reviews (2) · Last reviewed commit: "fix(audio): retain capture stall diagnos..."

Comment thread Sources/Fluid/Services/ASRService.swift Outdated
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