From 8cee56f2546c329d193d9478e29894cf9f6ad2ff Mon Sep 17 00:00:00 2001 From: peah Date: Thu, 24 Aug 2017 22:36:53 -0700 Subject: [PATCH] Utilizing the AEC3 config struct for constants. This CL replaces inline constants with config struct constants. BUG=webrtc:5298 Review-Url: https://codereview.webrtc.org/3003733002 Cr-Commit-Position: refs/heads/master@{#19507} --- .../aec3/adaptive_fir_filter_unittest.cc | 2 +- .../audio_processing/aec3/aec_state.cc | 13 ++- .../modules/audio_processing/aec3/aec_state.h | 8 +- .../aec3/aec_state_unittest.cc | 8 +- .../aec3/comfort_noise_generator_unittest.cc | 8 +- .../audio_processing/aec3/echo_remover.cc | 9 ++- .../aec3/echo_remover_metrics_unittest.cc | 2 +- .../audio_processing/aec3/erle_estimator.cc | 27 +++---- .../audio_processing/aec3/erle_estimator.h | 5 +- .../aec3/erle_estimator_unittest.cc | 2 +- .../aec3/main_filter_update_gain_unittest.cc | 2 +- .../aec3/residual_echo_estimator.cc | 11 ++- .../aec3/residual_echo_estimator.h | 7 +- .../aec3/residual_echo_estimator_unittest.cc | 16 ++-- .../shadow_filter_update_gain_unittest.cc | 2 +- .../aec3/subtractor_unittest.cc | 18 +++-- .../audio_processing/aec3/suppression_gain.cc | 79 +++++++++++-------- .../audio_processing/aec3/suppression_gain.h | 7 +- .../aec3/suppression_gain_unittest.cc | 6 +- .../include/audio_processing.h | 55 +++++++++++++ 20 files changed, 193 insertions(+), 94 deletions(-) diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc index ddc7896de6..c861d464e1 100644 --- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc @@ -305,7 +305,7 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) { std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector n(kBlockSize, 0.f); std::vector y(kBlockSize, 0.f); - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); RenderSignalAnalyzer render_signal_analyzer; std::vector e(kBlockSize, 0.f); std::array s_scratch; diff --git a/webrtc/modules/audio_processing/aec3/aec_state.cc b/webrtc/modules/audio_processing/aec3/aec_state.cc index cc344abca0..6908270995 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state.cc +++ b/webrtc/modules/audio_processing/aec3/aec_state.cc @@ -75,11 +75,15 @@ constexpr int kEchoPathChangeCounterMax = 2 * kNumBlocksPerSecond; int AecState::instance_count_ = 0; -AecState::AecState(float reverb_decay) +AecState::AecState(const AudioProcessing::Config::EchoCanceller3& config) : data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), + erle_estimator_(config.param.erle.min, + config.param.erle.max_l, + config.param.erle.max_h), echo_path_change_counter_(kEchoPathChangeCounterInitial), - reverb_decay_(reverb_decay) {} + config_(config), + reverb_decay_(config_.param.ep_strength.default_len) {} AecState::~AecState() = default; @@ -252,7 +256,8 @@ void AecState::UpdateReverb( // Limit the estimated reverb_decay_ to the maximum one needed in practice // to minimize the impact of incorrect estimates. - reverb_decay_ = std::min(0.8f, reverb_decay_); + reverb_decay_ = + std::min(config_.param.ep_strength.default_len, reverb_decay_); } reverb_decay_to_test_ = 0.9f; reverb_decay_candidate_residual_ = -1.f; @@ -260,7 +265,7 @@ void AecState::UpdateReverb( // For noisy impulse responses, assume a fixed tail length. if (tail_power > 0.0005f) { - reverb_decay_ = 0.7f; + reverb_decay_ = config_.param.ep_strength.default_len; } data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_); data_dumper_->DumpRaw("aec3_tail_power", tail_power); diff --git a/webrtc/modules/audio_processing/aec3/aec_state.h b/webrtc/modules/audio_processing/aec3/aec_state.h index 5192a929c6..44a1767125 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state.h +++ b/webrtc/modules/audio_processing/aec3/aec_state.h @@ -20,6 +20,7 @@ #include "webrtc/modules/audio_processing/aec3/erl_estimator.h" #include "webrtc/modules/audio_processing/aec3/erle_estimator.h" #include "webrtc/modules/audio_processing/aec3/render_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/rtc_base/array_view.h" #include "webrtc/rtc_base/constructormagic.h" #include "webrtc/rtc_base/optional.h" @@ -31,7 +32,7 @@ class ApmDataDumper; // Handles the state and the conditions for the echo removal functionality. class AecState { public: - explicit AecState(float reverb_decay); + explicit AecState(const AudioProcessing::Config::EchoCanceller3& config); ~AecState(); // Returns whether the linear filter estimate is usable. @@ -140,13 +141,14 @@ class AecState { rtc::Optional filter_delay_; rtc::Optional external_delay_; size_t blocks_since_last_saturation_ = 1000; - float reverb_decay_; float reverb_decay_to_test_ = 0.9f; float reverb_decay_candidate_ = 0.f; float reverb_decay_candidate_residual_ = -1.f; EchoAudibility echo_audibility_; + const AudioProcessing::Config::EchoCanceller3 config_; + float reverb_decay_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState); + RTC_DISALLOW_COPY_AND_ASSIGN(AecState); }; } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc b/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc index 7062d244b8..05530ca6d1 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc @@ -18,7 +18,7 @@ namespace webrtc { // Verify the general functionality of AecState TEST(AecState, NormalUsage) { ApmDataDumper data_dumper(42); - AecState state(0.f); + AecState state(AudioProcessing::Config::EchoCanceller3{}); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main = {}; @@ -163,7 +163,7 @@ TEST(AecState, NormalUsage) { // Verifies the a non-significant delay is correctly identified. TEST(AecState, NonSignificantDelay) { - AecState state(0.f); + AecState state(AudioProcessing::Config::EchoCanceller3{}); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main; @@ -192,7 +192,7 @@ TEST(AecState, NonSignificantDelay) { // Verifies the delay for a converged filter is correctly identified. TEST(AecState, ConvergedFilterDelay) { constexpr int kFilterLength = 10; - AecState state(0.f); + AecState state(AudioProcessing::Config::EchoCanceller3{}); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main; @@ -228,7 +228,7 @@ TEST(AecState, ConvergedFilterDelay) { // Verify that the externally reported delay is properly reported and converted. TEST(AecState, ExternalDelay) { - AecState state(0.f); + AecState state(AudioProcessing::Config::EchoCanceller3{}); std::array E2_main; std::array E2_shadow; std::array Y2; diff --git a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc index 9e10ee8ce3..7cb0aa1e67 100644 --- a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc @@ -36,7 +36,8 @@ TEST(ComfortNoiseGenerator, NullLowerBandNoise) { std::array N2; FftData noise; EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) - .Compute(AecState(0.f), N2, nullptr, &noise), + .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}), + N2, nullptr, &noise), ""); } @@ -44,7 +45,8 @@ TEST(ComfortNoiseGenerator, NullUpperBandNoise) { std::array N2; FftData noise; EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) - .Compute(AecState(0.f), N2, &noise, nullptr), + .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}), + N2, &noise, nullptr), ""); } @@ -91,7 +93,7 @@ TEST(ComfortNoiseGenerator, TestOptimizations) { TEST(ComfortNoiseGenerator, CorrectLevel) { ComfortNoiseGenerator cng(DetectOptimization()); - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); std::array N2; N2.fill(1000.f * 1000.f); diff --git a/webrtc/modules/audio_processing/aec3/echo_remover.cc b/webrtc/modules/audio_processing/aec3/echo_remover.cc index a67a04e4e3..32ecc73926 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover.cc @@ -72,6 +72,7 @@ class EchoRemoverImpl final : public EchoRemover { private: static int instance_count_; + const AudioProcessing::Config::EchoCanceller3 config_; const Aec3Fft fft_; std::unique_ptr data_dumper_; const Aec3Optimization optimization_; @@ -95,16 +96,18 @@ int EchoRemoverImpl::instance_count_ = 0; EchoRemoverImpl::EchoRemoverImpl( const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz) - : fft_(), + : config_(config), + fft_(), data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), optimization_(DetectOptimization()), sample_rate_hz_(sample_rate_hz), subtractor_(data_dumper_.get(), optimization_), - suppression_gain_(optimization_), + suppression_gain_(config_, optimization_), cng_(optimization_), suppression_filter_(sample_rate_hz_), - aec_state_(0.8f) { + residual_echo_estimator_(config_), + aec_state_(config_) { RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); } diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc index 21a5af2735..094508effa 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc @@ -126,7 +126,7 @@ TEST(DbMetric, Constructor) { // Verify the general functionality of EchoRemoverMetrics. TEST(EchoRemoverMetrics, NormalUsage) { EchoRemoverMetrics metrics; - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); std::array comfort_noise_spectrum; std::array suppressor_gain; comfort_noise_spectrum.fill(10.f); diff --git a/webrtc/modules/audio_processing/aec3/erle_estimator.cc b/webrtc/modules/audio_processing/aec3/erle_estimator.cc index 8cdaee56be..da0e421c00 100644 --- a/webrtc/modules/audio_processing/aec3/erle_estimator.cc +++ b/webrtc/modules/audio_processing/aec3/erle_estimator.cc @@ -16,16 +16,13 @@ namespace webrtc { -namespace { - -constexpr float kMinErle = 1.f; -constexpr float kMaxLfErle = 8.f; -constexpr float kMaxHfErle = 1.5f; - -} // namespace - -ErleEstimator::ErleEstimator() { - erle_.fill(kMinErle); +ErleEstimator::ErleEstimator(float min_erle, + float max_erle_lf, + float max_erle_hf) + : min_erle_(min_erle), + max_erle_lf_(max_erle_lf), + max_erle_hf_(max_erle_hf) { + erle_.fill(min_erle_); hold_counters_.fill(0); } @@ -50,19 +47,19 @@ void ErleEstimator::Update( if (new_erle > erle_[k]) { hold_counters_[k - 1] = 100; erle_[k] += 0.1f * (new_erle - erle_[k]); - erle_[k] = rtc::SafeClamp(erle_[k], kMinErle, max_erle); + erle_[k] = rtc::SafeClamp(erle_[k], min_erle_, max_erle); } } } }; - erle_update(1, kFftLengthBy2 / 2, kMaxLfErle); - erle_update(kFftLengthBy2 / 2, kFftLengthBy2, kMaxHfErle); + erle_update(1, kFftLengthBy2 / 2, max_erle_lf_); + erle_update(kFftLengthBy2 / 2, kFftLengthBy2, max_erle_hf_); std::for_each(hold_counters_.begin(), hold_counters_.end(), [](int& a) { --a; }); std::transform(hold_counters_.begin(), hold_counters_.end(), - erle_.begin() + 1, erle_.begin() + 1, [](int a, float b) { - return a > 0 ? b : std::max(kMinErle, 0.97f * b); + erle_.begin() + 1, erle_.begin() + 1, [&](int a, float b) { + return a > 0 ? b : std::max(min_erle_, 0.97f * b); }); erle_[0] = erle_[1]; diff --git a/webrtc/modules/audio_processing/aec3/erle_estimator.h b/webrtc/modules/audio_processing/aec3/erle_estimator.h index 48bb75a668..91a8c6ceb8 100644 --- a/webrtc/modules/audio_processing/aec3/erle_estimator.h +++ b/webrtc/modules/audio_processing/aec3/erle_estimator.h @@ -21,7 +21,7 @@ namespace webrtc { // Estimates the echo return loss enhancement based on the signal spectra. class ErleEstimator { public: - ErleEstimator(); + ErleEstimator(float min_erle, float max_erle_lf, float max_erle_hf); ~ErleEstimator(); // Updates the ERLE estimate. @@ -35,6 +35,9 @@ class ErleEstimator { private: std::array erle_; std::array hold_counters_; + const float min_erle_; + const float max_erle_lf_; + const float max_erle_hf_; RTC_DISALLOW_COPY_AND_ASSIGN(ErleEstimator); }; diff --git a/webrtc/modules/audio_processing/aec3/erle_estimator_unittest.cc b/webrtc/modules/audio_processing/aec3/erle_estimator_unittest.cc index dc95eee040..be435c0a41 100644 --- a/webrtc/modules/audio_processing/aec3/erle_estimator_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/erle_estimator_unittest.cc @@ -36,7 +36,7 @@ TEST(ErleEstimator, Estimates) { std::array E2; std::array Y2; - ErleEstimator estimator; + ErleEstimator estimator(1.f, 8.f, 1.5f); // Verifies that the ERLE estimate is properley increased to higher values. X2.fill(500 * 1000.f * 1000.f); diff --git a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc index 6e8a80b532..cbd62b58ad 100644 --- a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc @@ -53,7 +53,7 @@ void RunFilterUpdateTest(int num_blocks_to_process, Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); RenderSignalAnalyzer render_signal_analyzer; std::array s_scratch; std::array s; diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc index c708664db4..0dfec66cb2 100644 --- a/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc +++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc @@ -79,7 +79,9 @@ constexpr float kHeadsetEchoPathGain = 0.0005f; } // namespace -ResidualEchoEstimator::ResidualEchoEstimator() { +ResidualEchoEstimator::ResidualEchoEstimator( + const AudioProcessing::Config::EchoCanceller3& config) + : config_(config) { Reset(); } @@ -188,11 +190,12 @@ void ResidualEchoEstimator::NonLinearEstimate( const std::array& Y2, std::array* R2) { // Choose gains. - const float echo_path_gain_lf = headset_detected ? kHeadsetEchoPathGain : 100; + const float echo_path_gain_lf = + headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.lf; const float echo_path_gain_mf = - headset_detected ? kHeadsetEchoPathGain : 1000; + headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.mf; const float echo_path_gain_hf = - headset_detected ? kHeadsetEchoPathGain : 5000; + headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.hf; // Compute preliminary residual echo. std::transform( diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h index e9370ba5c8..5d2835dee3 100644 --- a/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h +++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h @@ -18,6 +18,7 @@ #include "webrtc/modules/audio_processing/aec3/aec3_common.h" #include "webrtc/modules/audio_processing/aec3/aec_state.h" #include "webrtc/modules/audio_processing/aec3/render_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/rtc_base/array_view.h" #include "webrtc/rtc_base/constructormagic.h" @@ -25,7 +26,8 @@ namespace webrtc { class ResidualEchoEstimator { public: - ResidualEchoEstimator(); + explicit ResidualEchoEstimator( + const AudioProcessing::Config::EchoCanceller3& config); ~ResidualEchoEstimator(); void Estimate(bool using_subtractor_output, @@ -69,8 +71,9 @@ class ResidualEchoEstimator { S2_old_; std::array X2_noise_floor_; std::array X2_noise_floor_counter_; + const AudioProcessing::Config::EchoCanceller3 config_; - RTC_DISALLOW_COPY_AND_ASSIGN(ResidualEchoEstimator); + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator); }; } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc index b448c4df43..6abb155734 100644 --- a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc @@ -12,6 +12,7 @@ #include "webrtc/modules/audio_processing/aec3/aec3_fft.h" #include "webrtc/modules/audio_processing/aec3/aec_state.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" #include "webrtc/rtc_base/random.h" #include "webrtc/test/gtest.h" @@ -22,22 +23,25 @@ namespace webrtc { // Verifies that the check for non-null output residual echo power works. TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) { - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, std::vector(1, 10)); std::vector> H2; std::array S2_linear; std::array Y2; - EXPECT_DEATH(ResidualEchoEstimator().Estimate(true, aec_state, render_buffer, - S2_linear, Y2, nullptr), - ""); + EXPECT_DEATH( + ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{}) + .Estimate(true, aec_state, render_buffer, S2_linear, Y2, nullptr), + ""); } #endif TEST(ResidualEchoEstimator, BasicTest) { - ResidualEchoEstimator estimator; - AecState aec_state(0.f); + ResidualEchoEstimator estimator(AudioProcessing::Config::EchoCanceller3{}); + AudioProcessing::Config::EchoCanceller3 config; + config.param.ep_strength.default_len = 0.f; + AecState aec_state(config); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, std::vector(1, 10)); std::array E2_main; diff --git a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc index 1ceb634278..99e3f25795 100644 --- a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc @@ -47,7 +47,7 @@ void RunFilterUpdateTest(int num_blocks_to_process, Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); RenderSignalAnalyzer render_signal_analyzer; std::array s; FftData S; diff --git a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc b/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc index 32fc054bf7..07b121337a 100644 --- a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc @@ -40,7 +40,7 @@ float RunSubtractorTest(int num_blocks_to_process, std::array Y2; std::array E2_main; std::array E2_shadow; - AecState aec_state(0.f); + AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); x_old.fill(0.f); Y2.fill(0.f); E2_main.fill(0.f); @@ -109,9 +109,11 @@ TEST(Subtractor, DISABLED_NullOutput) { RenderSignalAnalyzer render_signal_analyzer; std::vector y(kBlockSize, 0.f); - EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer, - AecState(0.f), nullptr), - ""); + EXPECT_DEATH( + subtractor.Process(render_buffer, y, render_signal_analyzer, + AecState(AudioProcessing::Config::EchoCanceller3{}), + nullptr), + ""); } // Verifies the check for the capture signal size. @@ -124,9 +126,11 @@ TEST(Subtractor, WrongCaptureSize) { std::vector y(kBlockSize - 1, 0.f); SubtractorOutput output; - EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer, - AecState(0.f), &output), - ""); + EXPECT_DEATH( + subtractor.Process(render_buffer, y, render_signal_analyzer, + AecState(AudioProcessing::Config::EchoCanceller3{}), + &output), + ""); } #endif diff --git a/webrtc/modules/audio_processing/aec3/suppression_gain.cc b/webrtc/modules/audio_processing/aec3/suppression_gain.cc index a25f748edc..8e78967e5c 100644 --- a/webrtc/modules/audio_processing/aec3/suppression_gain.cc +++ b/webrtc/modules/audio_processing/aec3/suppression_gain.cc @@ -109,6 +109,7 @@ float UpperBandsGain( // Limits the gain increase. void UpdateMaxGainIncrease( + const AudioProcessing::Config::EchoCanceller3& config, size_t no_saturation_counter, bool low_noise_render, const std::array& last_echo, @@ -123,27 +124,28 @@ void UpdateMaxGainIncrease( float min_increasing; float min_decreasing; + auto& param = config.param.gain_updates; if (low_noise_render) { - max_increasing = 8.f; - max_decreasing = 8.f; - rate_increasing = 2.f; - rate_decreasing = 2.f; - min_increasing = 4.f; - min_decreasing = 4.f; + max_increasing = param.low_noise.max_inc; + max_decreasing = param.low_noise.max_dec; + rate_increasing = param.low_noise.rate_inc; + rate_decreasing = param.low_noise.rate_dec; + min_increasing = param.low_noise.min_inc; + min_decreasing = param.low_noise.min_dec; } else if (no_saturation_counter > 10) { - max_increasing = 4.f; - max_decreasing = 4.f; - rate_increasing = 2.f; - rate_decreasing = 2.f; - min_increasing = 1.2f; - min_decreasing = 2.f; + max_increasing = param.normal.max_inc; + max_decreasing = param.normal.max_dec; + rate_increasing = param.normal.rate_inc; + rate_decreasing = param.normal.rate_dec; + min_increasing = param.normal.min_inc; + min_decreasing = param.normal.min_dec; } else { - max_increasing = 1.2f; - max_decreasing = 1.2f; - rate_increasing = 1.5f; - rate_decreasing = 1.5f; - min_increasing = 1.f; - min_decreasing = 1.f; + max_increasing = param.saturation.max_inc; + max_decreasing = param.saturation.max_dec; + rate_increasing = param.saturation.rate_inc; + rate_decreasing = param.saturation.rate_dec; + min_increasing = param.saturation.min_inc; + min_decreasing = param.saturation.min_dec; } for (size_t k = 0; k < new_gain.size(); ++k) { @@ -163,6 +165,7 @@ void UpdateMaxGainIncrease( // Computes the gain to reduce the echo to a non audible level. void GainToNoAudibleEcho( + const AudioProcessing::Config::EchoCanceller3& config, bool low_noise_render, bool saturated_echo, const std::array& nearend, @@ -172,16 +175,17 @@ void GainToNoAudibleEcho( const std::array& max_gain, const std::array& one_by_echo, std::array* gain) { - constexpr float kEchoMaskingMargin = 1.f / 100.f; const float nearend_masking_margin = - low_noise_render ? 0.1f : (saturated_echo ? 0.001f : 0.01f); + low_noise_render ? 0.1f + : (saturated_echo ? config.param.gain_mask.m2 + : config.param.gain_mask.m3); for (size_t k = 0; k < gain->size(); ++k) { RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]); if (echo[k] <= nearend_masking_margin * nearend[k]) { (*gain)[k] = 1.f; } else { - (*gain)[k] = kEchoMaskingMargin * masker[k] * one_by_echo[k]; + (*gain)[k] = config.param.gain_mask.m1 * masker[k] * one_by_echo[k]; } (*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]); @@ -189,7 +193,8 @@ void GainToNoAudibleEcho( } // Computes the signal output power that masks the echo signal. -void MaskingPower(const std::array& nearend, +void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config, + const std::array& nearend, const std::array& comfort_noise, const std::array& last_masker, const std::array& gain, @@ -197,7 +202,8 @@ void MaskingPower(const std::array& nearend, std::array side_band_masker; for (size_t k = 0; k < gain.size(); ++k) { side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k]; - (*masker)[k] = comfort_noise[k] + 0.1f * last_masker[k]; + (*masker)[k] = + comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k]; } for (size_t k = 1; k < gain.size() - 1; ++k) { (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]); @@ -227,7 +233,9 @@ void SuppressionGain::LowerBandGain( // Compute the minimum gain as the attenuating gain to put the signal just // above the zero sample values. std::array min_gain; - const float min_echo_power = low_noise_render ? 192.f : 64.f; + const float min_echo_power = + low_noise_render ? config_.param.echo_audibility.low_render_limit + : config_.param.echo_audibility.normal_render_limit; if (no_saturation_counter_ > 10) { for (size_t k = 0; k < nearend.size(); ++k) { const float denom = std::min(nearend[k], echo[k]); @@ -243,7 +251,9 @@ void SuppressionGain::LowerBandGain( 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], 0.001f), 1.f); + std::min(std::max(last_gain_[k] * gain_increase_[k], + config_.param.gain_updates.floor_first_increase), + 1.f); } // Iteratively compute the gain required to attenuate the echo to a non @@ -251,9 +261,9 @@ void SuppressionGain::LowerBandGain( gain->fill(0.f); for (int k = 0; k < 2; ++k) { std::array masker; - MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker); - GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker, - min_gain, max_gain, one_by_echo, gain); + MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker); + GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend, + echo, masker, min_gain, max_gain, one_by_echo, gain); AdjustForExternalFilters(gain); if (narrow_peak_band) { NarrowBandAttenuation(*narrow_peak_band, gain); @@ -261,18 +271,21 @@ void SuppressionGain::LowerBandGain( } // Update the allowed maximum gain increase. - UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_, - echo, last_gain_, *gain, &gain_increase_); + UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render, + last_echo_, echo, last_gain_, *gain, &gain_increase_); // Store data required for the gain computation of the next block. std::copy(echo.begin(), echo.end(), last_echo_.begin()); std::copy(gain->begin(), gain->end(), last_gain_.begin()); - MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_); + MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, + &last_masker_); aec3::VectorMath(optimization_).Sqrt(*gain); } -SuppressionGain::SuppressionGain(Aec3Optimization optimization) - : optimization_(optimization) { +SuppressionGain::SuppressionGain( + const AudioProcessing::Config::EchoCanceller3& config, + Aec3Optimization optimization) + : optimization_(optimization), config_(config) { last_gain_.fill(1.f); last_masker_.fill(0.f); gain_increase_.fill(1.f); diff --git a/webrtc/modules/audio_processing/aec3/suppression_gain.h b/webrtc/modules/audio_processing/aec3/suppression_gain.h index d22eb8a523..2d618c3ddd 100644 --- a/webrtc/modules/audio_processing/aec3/suppression_gain.h +++ b/webrtc/modules/audio_processing/aec3/suppression_gain.h @@ -16,13 +16,15 @@ #include "webrtc/modules/audio_processing/aec3/aec3_common.h" #include "webrtc/modules/audio_processing/aec3/render_signal_analyzer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/rtc_base/constructormagic.h" namespace webrtc { class SuppressionGain { public: - explicit SuppressionGain(Aec3Optimization optimization); + SuppressionGain(const AudioProcessing::Config::EchoCanceller3& config, + Aec3Optimization optimization); void GetGain(const std::array& nearend, const std::array& echo, const std::array& comfort_noise, @@ -58,7 +60,8 @@ class SuppressionGain { LowNoiseRenderDetector low_render_detector_; size_t no_saturation_counter_ = 0; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGain); + const AudioProcessing::Config::EchoCanceller3 config_; + RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain); }; } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/suppression_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/suppression_gain_unittest.cc index 61238d93d4..cde3c94a32 100644 --- a/webrtc/modules/audio_processing/aec3/suppression_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/suppression_gain_unittest.cc @@ -29,7 +29,8 @@ TEST(SuppressionGain, NullOutputGains) { R2.fill(0.f); N2.fill(0.f); float high_bands_gain; - EXPECT_DEATH(SuppressionGain(DetectOptimization()) + EXPECT_DEATH(SuppressionGain(AudioProcessing::Config::EchoCanceller3{}, + DetectOptimization()) .GetGain(E2, R2, N2, RenderSignalAnalyzer(), false, std::vector>( 3, std::vector(kBlockSize, 0.f)), @@ -41,7 +42,8 @@ TEST(SuppressionGain, NullOutputGains) { // Does a sanity check that the gains are correctly computed. TEST(SuppressionGain, BasicGainComputation) { - SuppressionGain suppression_gain(DetectOptimization()); + SuppressionGain suppression_gain(AudioProcessing::Config::EchoCanceller3(), + DetectOptimization()); RenderSignalAnalyzer analyzer; float high_bands_gain; std::array E2; diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h index 0a0951791a..de77bac30a 100644 --- a/webrtc/modules/audio_processing/include/audio_processing.h +++ b/webrtc/modules/audio_processing/include/audio_processing.h @@ -17,6 +17,7 @@ #include #include // size_t #include // FILE +#include #include #include "webrtc/modules/audio_processing/beamformer/array_util.h" @@ -267,6 +268,49 @@ class AudioProcessing : public rtc::RefCountInterface { // The functionality is not yet activated in the code and turning this on // does not yet have the desired behavior. struct EchoCanceller3 { + struct Param { + struct Erle { + float min = 1.f; + float max_l = 8.f; + float max_h = 1.5f; + } erle; + + struct EpStrength { + float lf = 100.f; + float mf = 1000.f; + float hf = 5000.f; + float default_len = 0.7f; + } ep_strength; + + struct Mask { + float m1 = 0.01f; + float m2 = 0.001f; + float m3 = 0.01f; + float m4 = 0.1f; + } gain_mask; + + struct EchoAudibility { + float low_render_limit = 192.f; + float normal_render_limit = 64.f; + } echo_audibility; + + struct GainUpdates { + struct GainChanges { + float max_inc; + float max_dec; + float rate_inc; + float rate_dec; + float min_inc; + float min_dec; + }; + + GainChanges low_noise = {8.f, 8.f, 2.f, 2.f, 4.f, 4.f}; + GainChanges normal = {4.f, 4.f, 2.f, 2.f, 1.2f, 2.f}; + GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f}; + + float floor_first_increase = 0.001f; + } gain_updates; + } param; bool enabled = false; } echo_canceller3; @@ -277,6 +321,17 @@ class AudioProcessing : public rtc::RefCountInterface { struct GainController2 { bool enabled = false; } gain_controller2; + + // Explicit copy assignment implementation to avoid issues with memory + // sanitizer complaints in case of self-assignment. + // TODO(peah): Add buildflag to ensure that this is only included for memory + // sanitizer builds. + Config& operator=(const Config& config) { + if (this != &config) { + memcpy(this, &config, sizeof(*this)); + } + return *this; + } }; // TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.