macOS: while a microphone is open, all page audio is delivered to the input device's own output channels (aggregate device lists the input device first)
Categories
(Core :: Audio/Video: cubeb, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr115 | --- | unaffected |
| firefox-esr153 | --- | affected |
| firefox157 | --- | wontfix |
| firefox158 | --- | wontfix |
| firefox159 | --- | fix-optional |
People
(Reporter: zamalloachion.diego, Assigned: padenot, NeedInfo)
References
(Regression)
Details
(Keywords: regression)
Attachments
(4 files)
Steps to reproduce:
Needs macOS with a default input device that also has output channels (a USB microphone with a headphone jack, a USB headset, an audio interface) and a different default output device. Here: input = Samson G-Track Pro (USB, 2 in / 2 out), output = the Mac's built-in headphone jack ("External Headphones"), both at 48 kHz. Firefox 155.0.1, macOS 26.5.1, Apple M2 Pro.
- Open the attached
repro.htmland press Start tone. A 330 Hz tone plays on the default output device. - Press Open microphone. It calls
getUserMediawithechoCancellation,noiseSuppressionandautoGainControlallfalse, so the VoiceProcessingIO path is not taken. - Press Close microphone.
Actual results:
Playback goes silent on the default output device for as long as the microphone is open, and returns when the track is stopped. (Heard with a real page that plays Web Audio while pitch-tracking the microphone; the attached minimal page produces the identical re-routing in the cubeb log below.) Nothing is reported to the page: the AudioContext stays running and currentTime keeps advancing. The MediaStream does not have to be connected to the AudioContext (the attached page never connects it); any same-rate AudioContext in the window is affected because it shares the graph.
Analysis
When input and output devices differ, cubeb-coreaudio-rs builds a private aggregate device and re-opens the output side on it. Two changes from 2024 combine badly:
- f8df86f "On aggregate devices put the input device first" fixes input channel selection, but sub-device order also decides output stream order, so the input device's own output channels become channels 1-2 of the aggregate.
- 6d84f46 "Route to the stereo pair even when having an input" (vendored in bug 1903315, see also bug 1903283): a stereo stream now sets
kAudioUnitProperty_AudioChannelLayout = Stereoon the AUHAL and skips the mixer. On the aggregate the stereo pair is channels 1-2, i.e. the input device's outputs. (Inferred from the stream order below; not confirmed by ear on the USB device's own jack.)
The comment above the output format set-up still describes the old order ("the data recorded by the input device's output channels will be appended at the end"), and nothing sets kAudioDevicePropertyPreferredChannelsForStereo or a channel map on the aggregate.
Evidence (further attachments to follow):
cubeb-log-firefox-155.txt(MOZ_LOG=cubeb:4, stream set-up lines only): output opens on device 106 with 2 channels[FrontLeft, FrontRight]; on getUserMedia, "Add devices input 113 and output 106 into an aggregate device 176", then the output side re-opens on 176 with 4 channels, layout[FrontLeft, FrontRight, Discrete, Discrete], no "setting up remixer" line and no AudioChannelLayout error; ontrack.stop()the aggregate is destroyed and output returns to device 106 with 2 channels.aggregate-probe.swiftbuilds the same private aggregate with both orders and prints its output streams. Input-first gives stream 1 (channels 1-2, "Front Left/Right") = the USB microphone's headphone output and stream 2 (channels 3-4) = the built-in headphone jack, with preferred stereo pair[1, 2]. Output-first puts the built-in jack on channels 1-2.
Possible fixes
Offset the output onto the output device's channels within the aggregate (a kAudioOutputUnitProperty_ChannelMap, or setting the aggregate's preferred stereo pair to [n+1, n+2] where n is the input device's output channel count) before taking the stereo-pair shortcut; the mixer path needs the same offset, since the layout it sees labels the input device's channels Front Left/Right.
Workaround for web pages
Create the playback AudioContext with a sampleRate different from the native one. It then lives in its own MediaTrackGraph with an output-only stream that is never moved onto the aggregate (verified in the cubeb log). A second AudioContext at the native rate does not help.
Expected results:
Playback stays on the default output device while a microphone on another device is open. Chrome on the same machine is unaffected (it opens independent input and output units).
| Reporter | ||
Comment 1•21 days ago
|
||
| Reporter | ||
Comment 2•21 days ago
|
||
| Reporter | ||
Comment 3•21 days ago
|
||
Comment 4•13 days ago
|
||
The severity field is not set for this bug.
:karlt, could you have a look please?
For more information, please visit BugBot documentation.
Updated•11 days ago
|
Comment 5•11 days ago
|
||
:padenot, since you are the author of the regressor, bug 1903315, could you take a look? Also, could you set the severity field?
For more information, please visit BugBot documentation.
| Assignee | ||
Comment 6•10 days ago
|
||
Taking.
Comment 7•10 days ago
|
||
Set release status flags based on info from the regressing bug 1903315
Updated•6 days ago
|
Comment 8•4 days ago
|
||
The severity field is not set for this bug.
:karlt, could you have a look please?
For more information, please visit BugBot documentation.
Updated•3 days ago
|
Updated•3 days ago
|
Comment 9•3 days ago
|
||
The severity field is not set for this bug.
:karlt, could you have a look please?
For more information, please visit BugBot documentation.
Description
•