Soften the AEC3 transparent mode to handle broken headsets

This CL softens the effect of the AEC3 transparent mode to also handle
headsets that leak low-level echoes in a nonlinear way.
This is handled by reintroducing the limit in the echo path gain for the
nonlinear mode. Due to recent improvements in echo suppressor behavior
this is now possible to do with a limited impact on the near-end speech.

Bug: webrtc:9246,chromium:840347
Change-Id: I0ca5157160d1884ba93b962323b56016756986d3
Reviewed-on: https://webrtc-review.googlesource.com/74703
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23145}
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index 31ad319..19f65d0 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -15,11 +15,21 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
+namespace {
+
+bool EnableSoftTransparentMode() {
+  return !field_trial::IsEnabled("WebRTC-Aec3SoftTransparentModeKillSwitch");
+}
+
+}  // namespace
 
 ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
-    : config_(config), S2_old_(config_.filter.main.length_blocks) {
+    : config_(config),
+      S2_old_(config_.filter.main.length_blocks),
+      soft_transparent_mode_(EnableSoftTransparentMode()) {
   Reset();
 }
 
@@ -64,7 +74,10 @@
                          0.f, a - config_.echo_model.stationary_gate_slope * b);
                    });
 
-    NonLinearEstimate(aec_state.EchoPathGain(), X2, Y2, R2);
+    float echo_path_gain = aec_state.TransparentMode() && soft_transparent_mode_
+                               ? 0.01f
+                               : aec_state.EchoPathGain();
+    NonLinearEstimate(echo_path_gain, X2, Y2, R2);
 
     // If the echo is saturated, estimate the echo power as the maximum echo
     // power with a leakage factor.
@@ -87,12 +100,13 @@
       }
     }
   }
-
-  // If the echo is deemed inaudible, set the residual echo to zero.
-  if (aec_state.TransparentMode()) {
-    R2->fill(0.f);
-    R2_old_.fill(0.f);
-    R2_hold_counter_.fill(0.f);
+  if (!soft_transparent_mode_) {
+    // If the echo is deemed inaudible, set the residual echo to zero.
+    if (aec_state.TransparentMode()) {
+      R2->fill(0.f);
+      R2_old_.fill(0.f);
+      R2_hold_counter_.fill(0.f);
+    }
   }
 
   std::copy(R2->begin(), R2->end(), R2_old_.begin());
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.h b/modules/audio_processing/aec3/residual_echo_estimator.h
index b789c0c..d03b89a 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.h
+++ b/modules/audio_processing/aec3/residual_echo_estimator.h
@@ -82,6 +82,7 @@
   std::vector<std::array<float, kFftLengthBy2Plus1>> S2_old_;
   std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
   std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
+  const bool soft_transparent_mode_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
 };