From 2ee432d51cbcf3b1ff5b155f02d372629d78dc46 Mon Sep 17 00:00:00 2001 From: henrika Date: Mon, 21 Aug 2017 14:43:14 +0200 Subject: [PATCH] Ensures that built-in AGC is enabled on iOS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: b/63895696 Change-Id: I8503299b5e57bd8db99ffc7947883d67dccf19e0 Reviewed-on: https://chromium-review.googlesource.com/621066 Commit-Queue: Henrik Andreasson Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#19429} --- .../ios/voice_processing_audio_unit.mm | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm b/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm index dda7347ed1..3701f3fee3 100644 --- a/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm +++ b/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm @@ -11,6 +11,7 @@ #import "webrtc/modules/audio_device/ios/voice_processing_audio_unit.h" #include "webrtc/rtc_base/checks.h" +#include "webrtc/system_wrappers/include/metrics.h" #import "WebRTC/RTCLogging.h" #import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h" @@ -54,6 +55,21 @@ static const AudioUnitElement kInputBus = 1; // A VP I/O unit's bus 0 connects to output hardware (speaker). static const AudioUnitElement kOutputBus = 0; +// Returns the automatic gain control (AGC) state on the processed microphone +// signal. Should be on by default for Voice Processing audio units. +static OSStatus GetAGCState(AudioUnit audio_unit, UInt32* enabled) { + RTC_DCHECK(audio_unit); + UInt32 size = sizeof(*enabled); + OSStatus result = AudioUnitGetProperty(audio_unit, + kAUVoiceIOProperty_VoiceProcessingEnableAGC, + kAudioUnitScope_Global, + kInputBus, + enabled, + &size); + RTCLog(@"VPIO unit AGC: %u", static_cast(*enabled)); + return result; +} + VoiceProcessingAudioUnit::VoiceProcessingAudioUnit( VoiceProcessingAudioUnitObserver* observer) : observer_(observer), vpio_unit_(nullptr), state_(kInitRequired) { @@ -231,6 +247,54 @@ bool VoiceProcessingAudioUnit::Initialize(Float64 sample_rate) { if (result == noErr) { RTCLog(@"Voice Processing I/O unit is now initialized."); } + + // AGC should be enabled by default for Voice Processing I/O units but it is + // checked below and enabled explicitly if needed. This scheme is used + // to be absolutely sure that the AGC is enabled since we have seen cases + // where only zeros are recorded and a disabled AGC could be one of the + // reasons why it happens. + int agc_was_enabled_by_default = 1; + UInt32 agc_is_enabled = 0; + result = GetAGCState(vpio_unit_, &agc_is_enabled); + if (result != noErr) { + RTCLogError(@"Failed to get AGC state (1st attempt). " + "Error=%ld.", + (long)result); + } else if (!agc_is_enabled) { + // Remember that the AGC was disabled by default. Will be used in UMA. + agc_was_enabled_by_default = 0; + // Try to enable the AGC. + UInt32 enable_agc = 1; + result = + AudioUnitSetProperty(vpio_unit_, + kAUVoiceIOProperty_VoiceProcessingEnableAGC, + kAudioUnitScope_Global, kInputBus, &enable_agc, + sizeof(enable_agc)); + if (result != noErr) { + RTCLogError(@"Failed to enable the built-in AGC. " + "Error=%ld.", + (long)result); + } + result = GetAGCState(vpio_unit_, &agc_is_enabled); + if (result != noErr) { + RTCLogError(@"Failed to get AGC state (2nd attempt). " + "Error=%ld.", + (long)result); + } + } + + // Track if the built-in AGC was enabled by default (as it should) or not. + RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.BuiltInAGCWasEnabledByDefault", + agc_was_enabled_by_default); + RTCLog(@"WebRTC.Audio.BuiltInAGCWasEnabledByDefault: %d", + agc_was_enabled_by_default); + // As a final step, add an UMA histogram for tracking the AGC state. + // At this stage, the AGC should be enabled, and if it is not, more work is + // needed to find out the root cause. + RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.BuiltInAGCIsEnabled", agc_is_enabled); + RTCLog(@"WebRTC.Audio.BuiltInAGCIsEnabled: %u", + static_cast(agc_is_enabled)); + state_ = kInitialized; return true; }