diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc index 67929b147a..8777887431 100644 --- a/modules/audio_processing/aec3/echo_remover.cc +++ b/modules/audio_processing/aec3/echo_remover.cc @@ -32,11 +32,17 @@ #include "rtc_base/atomicops.h" #include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" namespace webrtc { namespace { +bool UseShadowFilterOutput() { + return !field_trial::IsEnabled( + "WebRTC-Aec3UtilizeShadowFilterOutputKillSwitch"); +} + void LinearEchoPower(const FftData& E, const FftData& Y, std::array* S2) { @@ -86,12 +92,41 @@ class EchoRemoverImpl final : public EchoRemover { } private: + // Selects which of the shadow and main linear filter outputs that is most + // appropriate to pass to the suppressor. + const std::array& ChooseLinearFilterOutput( + const SubtractorOutput& subtractor_output) { + if (!use_shadow_filter_output_) { + return subtractor_output.e_main; + } + + // As the output of the main adaptive filter generally should be better than + // the shadow filter output, add a margin and threshold for when choosing + // the shadow filter output. + if (subtractor_output.e2_shadow < 0.9f * subtractor_output.e2_main && + subtractor_output.y2 > 30.f * 30.f * kBlockSize && + (subtractor_output.s2_main > 60.f * 60.f * kBlockSize || + subtractor_output.s2_shadow > 60.f * 60.f * kBlockSize)) { + return subtractor_output.e_shadow; + } + + // If the main filter is diverged, choose the filter output that has the + // lowest power. + if (subtractor_output.e2_shadow < subtractor_output.e2_main && + subtractor_output.y2 < subtractor_output.e2_main) { + return subtractor_output.e_shadow; + } + + return subtractor_output.e_main; + } + static int instance_count_; const EchoCanceller3Config config_; const Aec3Fft fft_; std::unique_ptr data_dumper_; const Aec3Optimization optimization_; const int sample_rate_hz_; + const bool use_shadow_filter_output_; Subtractor subtractor_; SuppressionGain suppression_gain_; ComfortNoiseGenerator cng_; @@ -121,6 +156,7 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config, new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), optimization_(DetectOptimization()), sample_rate_hz_(sample_rate_hz), + use_shadow_filter_output_(UseShadowFilterOutput()), subtractor_(config, data_dumper_.get(), optimization_), suppression_gain_(config_, optimization_, sample_rate_hz), cng_(optimization_), @@ -222,7 +258,7 @@ void EchoRemoverImpl::ProcessCapture( // If the delay is known, use the echo subtractor. subtractor_.Process(*render_buffer, y0, render_signal_analyzer_, aec_state_, &subtractor_output); - const auto& e = subtractor_output.e_main; + const auto& e = ChooseLinearFilterOutput(subtractor_output); // Compute spectra. WindowedPaddedFft(fft_, y0, y_old_, &Y); diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc index 41711547c3..785c208025 100644 --- a/modules/audio_processing/aec3/subtractor.cc +++ b/modules/audio_processing/aec3/subtractor.cc @@ -182,8 +182,8 @@ void Subtractor::Process(const RenderBuffer& render_buffer, shadow_filter_.Filter(render_buffer, &S); bool shadow_saturation = false; - PredictionError(fft_, S, y, &e_shadow, nullptr, adaptation_during_saturation_, - &shadow_saturation); + PredictionError(fft_, S, y, &e_shadow, &output->s_shadow, + adaptation_during_saturation_, &shadow_saturation); // Compute the signal powers in the subtractor output. output->UpdatePowers(y); diff --git a/modules/audio_processing/aec3/subtractor_output.cc b/modules/audio_processing/aec3/subtractor_output.cc index a405c3e71a..affa4a3a06 100644 --- a/modules/audio_processing/aec3/subtractor_output.cc +++ b/modules/audio_processing/aec3/subtractor_output.cc @@ -19,6 +19,7 @@ SubtractorOutput::~SubtractorOutput() = default; void SubtractorOutput::Reset() { s_main.fill(0.f); + s_shadow.fill(0.f); e_main.fill(0.f); e_shadow.fill(0.f); E_main.re.fill(0.f); @@ -27,6 +28,8 @@ void SubtractorOutput::Reset() { E2_shadow.fill(0.f); e2_main = 0.f; e2_shadow = 0.f; + s2_main = 0.f; + s2_shadow = 0.f; y2 = 0.f; } @@ -36,6 +39,9 @@ void SubtractorOutput::UpdatePowers(rtc::ArrayView y) { e2_main = std::accumulate(e_main.begin(), e_main.end(), 0.f, sum_of_squares); e2_shadow = std::accumulate(e_shadow.begin(), e_shadow.end(), 0.f, sum_of_squares); + s2_main = std::accumulate(s_main.begin(), s_main.end(), 0.f, sum_of_squares); + s2_shadow = + std::accumulate(s_shadow.begin(), s_shadow.end(), 0.f, sum_of_squares); } } // namespace webrtc diff --git a/modules/audio_processing/aec3/subtractor_output.h b/modules/audio_processing/aec3/subtractor_output.h index 229fd92a3c..89727e9396 100644 --- a/modules/audio_processing/aec3/subtractor_output.h +++ b/modules/audio_processing/aec3/subtractor_output.h @@ -25,11 +25,14 @@ struct SubtractorOutput { ~SubtractorOutput(); std::array s_main; + std::array s_shadow; std::array e_main; std::array e_shadow; FftData E_main; std::array E2_main; std::array E2_shadow; + float s2_main = 0.f; + float s2_shadow = 0.f; float e2_main = 0.f; float e2_shadow = 0.f; float y2 = 0.f;