Skip to content

fix(macos): open mic at native sample rate to prevent chipmunk audio on 96kHz devices#1973

Merged
richiemcilroy merged 1 commit into
CapSoftware:mainfrom
ManthanNimodiya:fix/macos-mic-96khz-chipmunks
Jul 2, 2026
Merged

fix(macos): open mic at native sample rate to prevent chipmunk audio on 96kHz devices#1973
richiemcilroy merged 1 commit into
CapSoftware:mainfrom
ManthanNimodiya:fix/macos-mic-96khz-chipmunks

Conversation

@ManthanNimodiya

@ManthanNimodiya ManthanNimodiya commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

On macOS, microphones that default to 96 kHz (e.g. some USB/studio mics) were forced to open at 48 kHz. cpal selects the nearest supported config, which on some devices means the stream opens at 96 kHz anyway but the pipeline treats it as 48 kHz, halving the perceived duration and pitching audio up 2x (chipmunk effect).

Fix: read the device's native sample rate via default_input_config() and use that as the preferred rate instead of hardcoding 48 kHz. The downstream resampler already handles conversion to the pipeline's 48 kHz output, so no other changes are needed.

Greptile Summary

This PR fixes a pitch-shift ("chipmunk") bug on macOS microphones that natively run at 96 kHz. Instead of hard-coding 48 kHz as the preferred stream rate, the code now reads the device's actual nominal rate via default_input_config() and uses that — cpal then opens the stream at the matching rate, and the existing downstream resampler converts to the pipeline's 48 kHz output.

  • Root-cause fix: preferred_rate in get_usable_device is now the device's native rate (e.g. 96 kHz) rather than a constant 48 kHz, preventing cpal from silently opening the stream at the wrong clock and treating the buffer counts as if they were 48 kHz samples.
  • Safe fallback: default_input_config() failures (returns Err) fall back to unwrap_or(48_000), which restores the previous behaviour so non-96 kHz devices are unaffected.
  • Settings path unaffected: when caller-supplied MicrophoneDeviceSettings include an explicit sample_rate, select_preferred_config runs first and returns early, so user overrides take full priority over the native rate.

Confidence Score: 5/5

Safe to merge. The change is a small, well-scoped substitution in a single function, with an explicit error fallback that restores the prior 48 kHz behaviour if the new device query fails.

The four-line change touches one code path in get_usable_device. The error fallback to 48 kHz means devices that don't expose a native rate are unaffected. The settings-override path (select_preferred_config) still takes full priority when a caller supplies an explicit sample rate, so no regression there. The callback estimator, resampler, and downstream pipeline all accept arbitrary input rates, making 96 kHz (or any other native rate) a valid stream configuration.

No files require special attention.

Important Files Changed

Filename Overview
crates/recording/src/feeds/microphone.rs Replaces the hardcoded 48 kHz preferred rate with the device's native sample rate read from default_input_config(); falls back to 48 kHz on error, preserving prior behaviour.

Reviews (1): Last reviewed commit: "fix(macos): open mic stream at hardware ..." | Re-trigger Greptile

.map(|c| c.sample_rate().0)
.unwrap_or(48_000);
let preferred_rate = cpal::SampleRate(native_rate);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you can keep this strongly typed as cpal::SampleRate and avoid reaching into .0 (and potentially drop native_rate).

Suggested change
let preferred_rate = device
.default_input_config()
.ok()
.map(|c| c.sample_rate())
.unwrap_or(cpal::SampleRate(48_000));

@richiemcilroy richiemcilroy merged commit 118414e into CapSoftware:main Jul 2, 2026
12 of 17 checks passed
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.

2 participants