fix: harden USB audio sample rate detection#65
Merged
Conversation
84665bb to
bb255b2
Compare
Extract sample rate validation logic into pure testable functions. Handles USB audio devices that negotiate rates different from the requested 48kHz (e.g. Jabra PRO 930 at 44.1kHz). Includes cross- validation between nominal and stream rates to detect mismatches. Part of USB audio sample rate hardening to fix Mickey Mouse voice.
Query both nominal rate and physical stream format rate from the aggregate device, cross-validate, and pick the more trustworthy value. Also verify rate on first IOProc callback to catch late device settling (common with USB audio like Jabra PRO 930). Previously, a single unchecked AudioObjectGetPropertyData call could return 0 or stale values, causing fallback to 48kHz when the USB device actually runs at 44.1kHz → wrong resampling ratio → Mickey Mouse voice.
After restarting app audio capture on device change, verify that actualSampleRate was detected (non-zero). If not, retry after 1s to allow USB devices time to negotiate their format.
Log the actual vs requested vs target rate prominently to make Mickey Mouse voice issues diagnosable from logs. Warn when the actual rate differs from the requested rate.
Log and validate the hardware sample rate after recreating the AVAudioEngine. Helps diagnose issues where USB devices haven't settled their format by the time the engine starts.
bb255b2 to
73907e6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SampleRateQuerypure functions that validate and cross-check sample rates from two independent CoreAudio sources (nominal rate + physical stream format)AppAudioCapture— replaces single uncheckedAudioObjectGetPropertyDatacall with dual-source cross-validation and IOProc first-frame rate verificationDualSourceRecorder.stop()for diagnosabilityRoot cause: USB headsets (e.g. Jabra PRO 930) can negotiate a different sample rate than the assumed 48kHz. The aggregate device may run at 44.1kHz, but the old code fell back to 48kHz on query failure → wrong resampling ratio → ~8.7% pitch shift upward → Mickey Mouse voice.
Test Plan
SampleRateQueryvalidation logic (zero, negative, unreasonably high, common USB rates, cross-validation matrix)