Skip to content

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

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

aaldrich wants to merge 4 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: current-main macOS/arm64 Xcode suite, 1,822 tests executed, 29 skipped, 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. The branch now includes current upstream main; the filter toggle was placed in the reorganized Dictation settings alongside Skip Silent Recordings, and the screenshot shows that current UI. 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

[Medium risk] Adds audio filtering to the speech recognition pipeline.

The PR appears safe to merge based on the reviewed changes and the resolved prior finding.

Summary

This PR adds an opt-in gate that filters low-level audio before streaming and final ASR, while keeping the existing silent-recording preference independent. It also adds settings, backup compatibility, capture-health handling, and regression tests. The change since the previous review moves one unchanged backup test into a separate test class.

Reviews (4) · Last reviewed commit: "test: keep filter backup regression outs..."

Comment thread Sources/Fluid/Services/ASRService.swift Outdated
@github-actions

Copy link
Copy Markdown

FluidVoice PR build ready

Download FluidVoice-PR-993-1e5293685450

The artifact contains the ad-hoc-signed app ZIP, Xcode archive, build manifest, and installation instructions. It expires 5 days after the build.

Install the app

  1. Extract the downloaded artifact, then extract FluidVoice-PR-993.app.zip.

  2. Move FluidVoice Filter low-level background audio before streaming ASR #993.app into the /Applications folder.

  3. Open Terminal and remove the download quarantine marker:

    xattr -dr com.apple.quarantine "/Applications/FluidVoice #993.app"
    
  4. In Applications, Control-click FluidVoice Filter low-level background audio before streaming ASR #993.app and choose Open.

  5. If macOS still blocks it, open System Settings → Privacy & Security, click Open Anyway, and confirm.

This build has its own app identity, so its permissions are separate from the release version of FluidVoice.

View workflow run

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

This pull request has been marked stale because it has had no activity for 5 days. It will be closed in 2 days if there is no further activity. Add the keep-open or pinned label to prevent automatic closure.

@github-actions github-actions Bot added the stale label Oct 4, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

Closing this pull request because it remained inactive for 2 days after being marked stale.

@github-actions github-actions Bot closed this Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant