diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h index 174ef6c9e3..55665caa33 100644 --- a/api/audio/echo_canceller3_config.h +++ b/api/audio/echo_canceller3_config.h @@ -73,6 +73,7 @@ struct EchoCanceller3Config { struct Mask { Mask(); Mask(const Mask& m); + float m0 = 0.1f; float m1 = 0.01f; float m2 = 0.0001f; float m3 = 0.01f; @@ -120,6 +121,8 @@ struct EchoCanceller3Config { GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f}; GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f}; + float max_inc_factor = 2.0f; + float max_dec_factor_lf = 0.25f; float floor_first_increase = 0.00001f; } gain_updates; diff --git a/modules/audio_processing/aec3/BUILD.gn b/modules/audio_processing/aec3/BUILD.gn index 5298d515ac..21cb63c9ac 100644 --- a/modules/audio_processing/aec3/BUILD.gn +++ b/modules/audio_processing/aec3/BUILD.gn @@ -116,6 +116,7 @@ rtc_static_library("aec3") { "../../../rtc_base:rtc_base_approved", "../../../rtc_base:safe_minmax", "../../../system_wrappers:cpu_features_api", + "../../../system_wrappers:field_trial_api", "../../../system_wrappers:metrics_api", ] diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc index 9591c6795c..a9f564a686 100644 --- a/modules/audio_processing/aec3/suppression_gain.cc +++ b/modules/audio_processing/aec3/suppression_gain.cc @@ -24,10 +24,16 @@ #include "modules/audio_processing/logging/apm_data_dumper.h" #include "rtc_base/atomicops.h" #include "rtc_base/checks.h" +#include "system_wrappers/include/field_trial.h" namespace webrtc { namespace { +bool EnableTransparencyImprovements() { + return !field_trial::IsEnabled( + "WebRTC-Aec3TransparencyImprovementsKillSwitch"); +} + // Adjust the gains according to the presence of known external filters. void AdjustForExternalFilters(std::array* gain) { // Limit the low frequency gains to avoid the impact of the high-pass filter @@ -148,6 +154,7 @@ void GainToNoAudibleEcho( bool low_noise_render, bool saturated_echo, bool linear_echo_estimate, + bool enable_transparency_improvements, const std::array& nearend, const std::array& weighted_echo, const std::array& masker, @@ -169,7 +176,10 @@ void GainToNoAudibleEcho( RTC_DCHECK_GT(1.f, nearend_masking_margin); const float masker_margin = - linear_echo_estimate ? config.gain_mask.m1 : config.gain_mask.m8; + linear_echo_estimate + ? (enable_transparency_improvements ? config.gain_mask.m0 + : config.gain_mask.m1) + : config.gain_mask.m8; for (size_t k = 0; k < gain->size(); ++k) { const float unity_gain_masker = std::max(nearend[k], masker[k]); @@ -196,11 +206,17 @@ constexpr size_t kUpperAccurateBandPlus1 = 29; // Computes the signal output power that masks the echo signal. void MaskingPower(const EchoCanceller3Config& config, + bool enable_transparency_improvements, const std::array& nearend, const std::array& comfort_noise, const std::array& last_masker, const std::array& gain, std::array* masker) { + if (enable_transparency_improvements) { + std::copy(comfort_noise.begin(), comfort_noise.end(), masker->begin()); + return; + } + // Apply masking over time. float masking_factor = config.gain_mask.temporal_masking_lf; auto limit = config.gain_mask.temporal_masking_lf_bands; @@ -286,6 +302,18 @@ void SuppressionGain::LowerBandGain( min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f; min_gain[k] = std::min(min_gain[k], 1.f); } + if (enable_transparency_improvements_) { + for (size_t k = 0; k < 6; ++k) { + // Make sure the gains of the low frequencies do not decrease too + // quickly after strong nearend. + if (last_nearend_[k] > last_echo_[k]) { + min_gain[k] = + std::max(min_gain[k], + last_gain_[k] * config_.gain_updates.max_dec_factor_lf); + min_gain[k] = std::min(min_gain[k], 1.f); + } + } + } } else { min_gain.fill(0.f); } @@ -293,10 +321,20 @@ void SuppressionGain::LowerBandGain( // Compute the maximum gain by limiting the gain increase from the previous // gain. std::array max_gain; - for (size_t k = 0; k < gain->size(); ++k) { - max_gain[k] = std::min(std::max(last_gain_[k] * gain_increase_[k], - config_.gain_updates.floor_first_increase), - 1.f); + if (enable_transparency_improvements_) { + for (size_t k = 0; k < gain->size(); ++k) { + max_gain[k] = + std::min(std::max(last_gain_[k] * config_.gain_updates.max_inc_factor, + config_.gain_updates.floor_first_increase), + 1.f); + } + } else { + for (size_t k = 0; k < gain->size(); ++k) { + max_gain[k] = + std::min(std::max(last_gain_[k] * gain_increase_[k], + config_.gain_updates.floor_first_increase), + 1.f); + } } // Iteratively compute the gain required to attenuate the echo to a non @@ -304,10 +342,12 @@ void SuppressionGain::LowerBandGain( gain->fill(0.f); std::array masker; for (int k = 0; k < 2; ++k) { - MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker); + MaskingPower(config_, enable_transparency_improvements_, nearend, + comfort_noise, last_masker_, *gain, &masker); GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, - linear_echo_estimate, nearend, weighted_echo, masker, - min_gain, max_gain, one_by_weighted_echo, gain); + linear_echo_estimate, enable_transparency_improvements_, + nearend, weighted_echo, masker, min_gain, max_gain, + one_by_weighted_echo, gain); AdjustForExternalFilters(gain); } @@ -319,10 +359,11 @@ void SuppressionGain::LowerBandGain( weighted_echo, *gain); // Store data required for the gain computation of the next block. + std::copy(nearend.begin(), nearend.end(), last_nearend_.begin()); std::copy(weighted_echo.begin(), weighted_echo.end(), last_echo_.begin()); std::copy(gain->begin(), gain->end(), last_gain_.begin()); - MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, - &last_masker_); + MaskingPower(config_, enable_transparency_improvements_, nearend, + comfort_noise, last_masker_, *gain, &last_masker_); aec3::VectorMath(optimization_).Sqrt(*gain); // Debug outputs for the purpose of development and analysis. @@ -342,12 +383,14 @@ SuppressionGain::SuppressionGain(const EchoCanceller3Config& config, state_change_duration_blocks_( static_cast(config_.filter.config_change_duration_blocks)), coherence_gain_(sample_rate_hz, - config_.suppressor.bands_with_reliable_coherence) { + config_.suppressor.bands_with_reliable_coherence), + enable_transparency_improvements_(EnableTransparencyImprovements()) { RTC_DCHECK_LT(0, state_change_duration_blocks_); one_by_state_change_duration_blocks_ = 1.f / state_change_duration_blocks_; last_gain_.fill(1.f); last_masker_.fill(0.f); gain_increase_.fill(1.f); + last_nearend_.fill(0.f); last_echo_.fill(0.f); } @@ -376,7 +419,8 @@ void SuppressionGain::GetGain( comfort_noise_spectrum, low_band_gain); // Adjust the gain for bands where the coherence indicates not echo. - if (config_.suppressor.bands_with_reliable_coherence > 0) { + if (config_.suppressor.bands_with_reliable_coherence > 0 && + !enable_transparency_improvements_) { std::array G_coherence; coherence_gain_.ComputeGain(linear_aec_fft, render_fft, capture_fft, G_coherence); diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h index 7b34d0a05d..f3719eed4e 100644 --- a/modules/audio_processing/aec3/suppression_gain.h +++ b/modules/audio_processing/aec3/suppression_gain.h @@ -78,11 +78,13 @@ class SuppressionGain { std::array last_gain_; std::array last_masker_; std::array gain_increase_; + std::array last_nearend_; std::array last_echo_; LowNoiseRenderDetector low_render_detector_; bool initial_state_ = true; int initial_state_change_counter_ = 0; CoherenceGain coherence_gain_; + const bool enable_transparency_improvements_; RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain); };