Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use different scopes on the output bus depending on AudioUnit type #233

Merged
merged 2 commits into from
Aug 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 42 additions & 29 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3783,7 +3783,16 @@ impl<'ctx> CoreStreamData<'ctx> {
let r = audio_unit_get_property(
self.output_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
if using_voice_processing_unit {
// With a VPIO unit the output scope includes all channels in the hw.
// The VPIO unit however is only MONO which the input scope reflects.
kAudioUnitScope_Input
} else {
// With a HAL unit the output scope for the output bus returns the number of
// output channels of the hw, as we want. The input scope seems limited to
// two channels.
kAudioUnitScope_Output
},
AU_OUT_BUS,
&mut output_hw_desc,
&mut size,
Expand All @@ -3810,13 +3819,44 @@ impl<'ctx> CoreStreamData<'ctx> {
return Err(Error::error());
}

// Simple case of stereo output, map to the stereo pair (that might not be the first
// two channels). Fall back to regular mixing if this fails.
let mut maybe_need_mixer = true;
if self.output_stream_params.channels() == 2
&& self.output_stream_params.layout() == ChannelLayout::STEREO
{
let layout = AudioChannelLayout {
mChannelLayoutTag: kAudioChannelLayoutTag_Stereo,
..Default::default()
};
let r = audio_unit_set_property(
self.output_unit,
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Input,
AU_OUT_BUS,
&layout,
mem::size_of::<AudioChannelLayout>(),
);
if r != NO_ERR {
cubeb_log!(
"AudioUnitSetProperty/output/kAudioUnitProperty_AudioChannelLayout rv={}",
r
);
}
maybe_need_mixer = r != NO_ERR;
}

// Notice: when we are using aggregate device, the output_hw_desc.mChannelsPerFrame is
// the total of all the output channel count of the devices added in the aggregate device.
// Due to our aggregate device settings, the data recorded by the input device's output
// channels will be appended at the end of the raw data given by the output callback.
let params = unsafe {
let mut p = *self.output_stream_params.as_ptr();
p.channels = output_hw_desc.mChannelsPerFrame;
p.channels = if maybe_need_mixer {
output_hw_desc.mChannelsPerFrame
} else {
self.output_stream_params.channels()
};
if using_voice_processing_unit {
// VPIO will always use the sample rate of the input hw for both input and output,
// as reported to us. (We can override it but we cannot improve quality this way).
Expand Down Expand Up @@ -3868,33 +3908,6 @@ impl<'ctx> CoreStreamData<'ctx> {
device_layout
);

// Simple case of stereo output, map to the stereo pair (that might not be the first
// two channels). Fall back to regular mixing if this fails.
let mut maybe_need_mixer = true;
if self.output_stream_params.channels() == 2
&& self.output_stream_params.layout() == ChannelLayout::STEREO
{
let layout = AudioChannelLayout {
mChannelLayoutTag: kAudioChannelLayoutTag_Stereo,
..Default::default()
};
let r = audio_unit_set_property(
self.output_unit,
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Input,
AU_OUT_BUS,
&layout,
mem::size_of::<AudioChannelLayout>(),
);
if r != NO_ERR {
cubeb_log!(
"AudioUnitSetProperty/output/kAudioUnitProperty_AudioChannelLayout rv={}",
r
);
}
maybe_need_mixer = r != NO_ERR;
}

if maybe_need_mixer {
// The mixer will be set up when
// 0. not playing simply stereo, or failing to set the channel layout to the stereo
Expand Down
Loading