Use playout sample rate for audio unit.
Fixing a race condition where session.sampleRate changes before AudioDeviceIOS::HandleValidRouteChange() finishes. session.sampleRate is read into session_sample_rate at 576 and used at 623 to initialize the audio unit. However, in the call to SetupAudioBuffersForActiveAudioSession() the session.sampleRate is read again and may have changed, resulting in different sample rates used for the buffers and the audio unit. The consequence is a sample rate mismatch with either high pitched or low pitched audio. The fix is to always use the buffer sample rate for the audio unit. The DCHECK at 622 would save us in debug, but not in production, hence removed. Change-Id: I562f1bf7f94d7447139ada2636b02ade7fcd6371 Bug: webrtc:14011 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/260329 Reviewed-by: Henrik Andreasson <henrika@google.com> Commit-Queue: Peter Hanspers <peterhanspers@webrtc.org> Cr-Commit-Position: refs/heads/main@{#36708}
This commit is contained in:
parent
8ec4a2eca3
commit
d4fce5a361
@ -169,7 +169,7 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
|
||||
void HandleInterruptionEnd();
|
||||
void HandleValidRouteChange();
|
||||
void HandleCanPlayOrRecordChange(bool can_play_or_record);
|
||||
void HandleSampleRateChange(float sample_rate);
|
||||
void HandleSampleRateChange();
|
||||
void HandlePlayoutGlitchDetected();
|
||||
void HandleOutputVolumeChange();
|
||||
|
||||
|
||||
@ -546,7 +546,7 @@ void AudioDeviceIOS::HandleValidRouteChange() {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
|
||||
RTCLog(@"%@", session);
|
||||
HandleSampleRateChange(session.sampleRate);
|
||||
HandleSampleRateChange();
|
||||
}
|
||||
|
||||
void AudioDeviceIOS::HandleCanPlayOrRecordChange(bool can_play_or_record) {
|
||||
@ -554,13 +554,13 @@ void AudioDeviceIOS::HandleCanPlayOrRecordChange(bool can_play_or_record) {
|
||||
UpdateAudioUnit(can_play_or_record);
|
||||
}
|
||||
|
||||
void AudioDeviceIOS::HandleSampleRateChange(float sample_rate) {
|
||||
void AudioDeviceIOS::HandleSampleRateChange() {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
RTCLog(@"Handling sample rate change to %f.", sample_rate);
|
||||
RTCLog(@"Handling sample rate change.");
|
||||
|
||||
// Don't do anything if we're interrupted.
|
||||
if (is_interrupted_) {
|
||||
RTCLog(@"Ignoring sample rate change to %f due to interruption.", sample_rate);
|
||||
RTCLog(@"Ignoring sample rate change due to interruption.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -573,31 +573,30 @@ void AudioDeviceIOS::HandleSampleRateChange(float sample_rate) {
|
||||
// The audio unit is already initialized or started.
|
||||
// Check to see if the sample rate or buffer size has changed.
|
||||
RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
|
||||
const double session_sample_rate = session.sampleRate;
|
||||
const double new_sample_rate = session.sampleRate;
|
||||
const NSTimeInterval session_buffer_duration = session.IOBufferDuration;
|
||||
const size_t session_frames_per_buffer =
|
||||
static_cast<size_t>(session_sample_rate * session_buffer_duration + .5);
|
||||
const size_t new_frames_per_buffer =
|
||||
static_cast<size_t>(new_sample_rate * session_buffer_duration + .5);
|
||||
const double current_sample_rate = playout_parameters_.sample_rate();
|
||||
const size_t current_frames_per_buffer = playout_parameters_.frames_per_buffer();
|
||||
RTCLog(@"Handling playout sample rate change to: %f\n"
|
||||
RTCLog(@"Handling playout sample rate change:\n"
|
||||
" Session sample rate: %f frames_per_buffer: %lu\n"
|
||||
" ADM sample rate: %f frames_per_buffer: %lu",
|
||||
sample_rate,
|
||||
session_sample_rate,
|
||||
(unsigned long)session_frames_per_buffer,
|
||||
new_sample_rate,
|
||||
(unsigned long)new_frames_per_buffer,
|
||||
current_sample_rate,
|
||||
(unsigned long)current_frames_per_buffer);
|
||||
|
||||
// Sample rate and buffer size are the same, no work to do.
|
||||
if (std::abs(current_sample_rate - session_sample_rate) <= DBL_EPSILON &&
|
||||
current_frames_per_buffer == session_frames_per_buffer) {
|
||||
if (std::abs(current_sample_rate - new_sample_rate) <= DBL_EPSILON &&
|
||||
current_frames_per_buffer == new_frames_per_buffer) {
|
||||
RTCLog(@"Ignoring sample rate change since audio parameters are intact.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extra sanity check to ensure that the new sample rate is valid.
|
||||
if (session_sample_rate <= 0.0) {
|
||||
RTCLogError(@"Sample rate is invalid: %f", session_sample_rate);
|
||||
if (new_sample_rate <= 0.0) {
|
||||
RTCLogError(@"Sample rate is invalid: %f", new_sample_rate);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -619,9 +618,9 @@ void AudioDeviceIOS::HandleSampleRateChange(float sample_rate) {
|
||||
SetupAudioBuffersForActiveAudioSession();
|
||||
|
||||
// Initialize the audio unit again with the new sample rate.
|
||||
RTC_DCHECK_EQ(playout_parameters_.sample_rate(), session_sample_rate);
|
||||
if (!audio_unit_->Initialize(session_sample_rate)) {
|
||||
RTCLogError(@"Failed to initialize the audio unit with sample rate: %f", session_sample_rate);
|
||||
if (!audio_unit_->Initialize(playout_parameters_.sample_rate())) {
|
||||
RTCLogError(@"Failed to initialize the audio unit with sample rate: %d",
|
||||
playout_parameters_.sample_rate());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -631,8 +630,8 @@ void AudioDeviceIOS::HandleSampleRateChange(float sample_rate) {
|
||||
if (result != noErr) {
|
||||
RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
|
||||
[session notifyAudioUnitStartFailedWithError:result];
|
||||
RTCLogError(@"Failed to start audio unit with sample rate: %f, reason %d",
|
||||
session_sample_rate,
|
||||
RTCLogError(@"Failed to start audio unit with sample rate: %d, reason %d",
|
||||
playout_parameters_.sample_rate(),
|
||||
result);
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user