diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h index 125ae83a2b..e2f70a4c68 100644 --- a/modules/audio_processing/aec3/aec_state.h +++ b/modules/audio_processing/aec3/aec_state.h @@ -75,6 +75,12 @@ class AecState { return erle_estimator_.Erle(onset_compensated); } + // Returns the non-capped ERLE. + rtc::ArrayView> ErleUnbounded() + const { + return erle_estimator_.ErleUnbounded(); + } + // Returns the fullband ERLE estimate in log2 units. float FullBandErleLog2() const { return erle_estimator_.FullbandErleLog2(); } diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc index 6c177c9a10..2bfaa951d8 100644 --- a/modules/audio_processing/aec3/echo_remover.cc +++ b/modules/audio_processing/aec3/echo_remover.cc @@ -172,6 +172,7 @@ class EchoRemoverImpl final : public EchoRemover { std::vector> Y2_heap_; std::vector> E2_heap_; std::vector> R2_heap_; + std::vector> R2_unbounded_heap_; std::vector> S2_linear_heap_; std::vector Y_heap_; std::vector E_heap_; @@ -218,6 +219,7 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config, Y2_heap_(NumChannelsOnHeap(num_capture_channels_)), E2_heap_(NumChannelsOnHeap(num_capture_channels_)), R2_heap_(NumChannelsOnHeap(num_capture_channels_)), + R2_unbounded_heap_(NumChannelsOnHeap(num_capture_channels_)), S2_linear_heap_(NumChannelsOnHeap(num_capture_channels_)), Y_heap_(NumChannelsOnHeap(num_capture_channels_)), E_heap_(NumChannelsOnHeap(num_capture_channels_)), @@ -264,6 +266,8 @@ void EchoRemoverImpl::ProcessCapture( E2_stack; std::array, kMaxNumChannelsOnStack> R2_stack; + std::array, kMaxNumChannelsOnStack> + R2_unbounded_stack; std::array, kMaxNumChannelsOnStack> S2_linear_stack; std::array Y_stack; @@ -280,6 +284,8 @@ void EchoRemoverImpl::ProcessCapture( E2_stack.data(), num_capture_channels_); rtc::ArrayView> R2( R2_stack.data(), num_capture_channels_); + rtc::ArrayView> R2_unbounded( + R2_unbounded_stack.data(), num_capture_channels_); rtc::ArrayView> S2_linear( S2_linear_stack.data(), num_capture_channels_); rtc::ArrayView Y(Y_stack.data(), num_capture_channels_); @@ -301,6 +307,8 @@ void EchoRemoverImpl::ProcessCapture( E2_heap_.data(), num_capture_channels_); R2 = rtc::ArrayView>( R2_heap_.data(), num_capture_channels_); + R2_unbounded = rtc::ArrayView>( + R2_unbounded_heap_.data(), num_capture_channels_); S2_linear = rtc::ArrayView>( S2_linear_heap_.data(), num_capture_channels_); Y = rtc::ArrayView(Y_heap_.data(), num_capture_channels_); @@ -406,8 +414,8 @@ void EchoRemoverImpl::ProcessCapture( if (capture_output_used_) { // Estimate the residual echo power. residual_echo_estimator_.Estimate(aec_state_, *render_buffer, S2_linear, Y2, - suppression_gain_.IsDominantNearend(), - R2); + suppression_gain_.IsDominantNearend(), R2, + R2_unbounded); // Suppressor nearend estimate. if (aec_state_.UsableLinearEstimate()) { @@ -430,7 +438,7 @@ void EchoRemoverImpl::ProcessCapture( // Compute preferred gains. float high_bands_gain; - suppression_gain_.GetGain(nearend_spectrum, echo_spectrum, R2, + suppression_gain_.GetGain(nearend_spectrum, echo_spectrum, R2, R2_unbounded, cng_.NoiseSpectrum(), render_signal_analyzer_, aec_state_, x, clock_drift, &high_bands_gain, &G); diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h index cae896e82c..55797592a9 100644 --- a/modules/audio_processing/aec3/erle_estimator.h +++ b/modules/audio_processing/aec3/erle_estimator.h @@ -62,6 +62,18 @@ class ErleEstimator { : subband_erle_estimator_.Erle(onset_compensated); } + // Returns the non-capped subband ERLE. + rtc::ArrayView> ErleUnbounded() + const { + // Unbounded ERLE is only used with the subband erle estimator where the + // ERLE is often capped at low values. When the signal dependent ERLE + // estimator is used the capped ERLE is returned. + return !signal_dependent_erle_estimator_ + ? subband_erle_estimator_.ErleUnbounded() + : signal_dependent_erle_estimator_->Erle( + /*onset_compensated=*/false); + } + // Returns the subband ERLE that are estimated during onsets (only used for // testing). rtc::ArrayView> ErleDuringOnsets() diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc index 6df71424bc..e38f2386f7 100644 --- a/modules/audio_processing/aec3/erle_estimator_unittest.cc +++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc @@ -50,6 +50,16 @@ void VerifyErle( EXPECT_NEAR(kTrueErle, erle_time_domain, 0.5); } +void VerifyErleGreaterOrEqual( + rtc::ArrayView> erle1, + rtc::ArrayView> erle2) { + for (size_t ch = 0; ch < erle1.size(); ++ch) { + for (size_t i = 0; i < kFftLengthBy2Plus1; ++i) { + EXPECT_GE(erle1[ch][i], erle2[ch][i]); + } + } +} + void FormFarendTimeFrame(std::vector>>* x) { const std::array frame = { 7459.88, 17209.6, 17383, 20768.9, 16816.7, 18386.3, 4492.83, 9675.85, @@ -156,9 +166,10 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleIncreaseAndHold) { kNumBands, std::vector>( num_render_channels, std::vector(kBlockSize, 0.f))); std::vector>> - filter_frequency_response( - config.filter.refined.length_blocks, - std::vector>(num_capture_channels)); + filter_frequency_response( + config.filter.refined.length_blocks, + std::vector>( + num_capture_channels)); std::unique_ptr render_delay_buffer( RenderDelayBuffer::Create(config, kSampleRateHz, num_render_channels)); @@ -181,6 +192,10 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleIncreaseAndHold) { VerifyErle(estimator.Erle(/*onset_compensated=*/true), std::pow(2.f, estimator.FullbandErleLog2()), config.erle.max_l, config.erle.max_h); + VerifyErleGreaterOrEqual(estimator.Erle(/*onset_compensated=*/false), + estimator.Erle(/*onset_compensated=*/true)); + VerifyErleGreaterOrEqual(estimator.ErleUnbounded(), + estimator.Erle(/*onset_compensated=*/false)); FormNearendFrame(&x, &X2, E2, Y2); // Verifies that the ERLE is not immediately decreased during nearend @@ -194,6 +209,10 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleIncreaseAndHold) { VerifyErle(estimator.Erle(/*onset_compensated=*/true), std::pow(2.f, estimator.FullbandErleLog2()), config.erle.max_l, config.erle.max_h); + VerifyErleGreaterOrEqual(estimator.Erle(/*onset_compensated=*/false), + estimator.Erle(/*onset_compensated=*/true)); + VerifyErleGreaterOrEqual(estimator.ErleUnbounded(), + estimator.Erle(/*onset_compensated=*/false)); } TEST_P(ErleEstimatorMultiChannel, VerifyErleTrackingOnOnsets) { @@ -212,9 +231,10 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleTrackingOnOnsets) { kNumBands, std::vector>( num_render_channels, std::vector(kBlockSize, 0.f))); std::vector>> - filter_frequency_response( - config.filter.refined.length_blocks, - std::vector>(num_capture_channels)); + filter_frequency_response( + config.filter.refined.length_blocks, + std::vector>( + num_capture_channels)); std::unique_ptr render_delay_buffer( RenderDelayBuffer::Create(config, kSampleRateHz, num_render_channels)); diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc index 0688429d47..15bebecb5f 100644 --- a/modules/audio_processing/aec3/residual_echo_estimator.cc +++ b/modules/audio_processing/aec3/residual_echo_estimator.cc @@ -177,7 +177,8 @@ void ResidualEchoEstimator::Estimate( rtc::ArrayView> S2_linear, rtc::ArrayView> Y2, bool dominant_nearend, - rtc::ArrayView> R2) { + rtc::ArrayView> R2, + rtc::ArrayView> R2_unbounded) { RTC_DCHECK_EQ(R2.size(), Y2.size()); RTC_DCHECK_EQ(R2.size(), S2_linear.size()); @@ -193,14 +194,18 @@ void ResidualEchoEstimator::Estimate( if (aec_state.SaturatedEcho()) { for (size_t ch = 0; ch < num_capture_channels; ++ch) { std::copy(Y2[ch].begin(), Y2[ch].end(), R2[ch].begin()); + std::copy(Y2[ch].begin(), Y2[ch].end(), R2_unbounded[ch].begin()); } } else { const bool onset_compensated = erle_onset_compensation_in_dominant_nearend_ || !dominant_nearend; LinearEstimate(S2_linear, aec_state.Erle(onset_compensated), R2); + LinearEstimate(S2_linear, aec_state.ErleUnbounded(), R2_unbounded); } - AddReverb(ReverbType::kLinear, aec_state, render_buffer, R2); + UpdateReverb(ReverbType::kLinear, aec_state, render_buffer); + AddReverb(R2); + AddReverb(R2_unbounded); } else { const float echo_path_gain = GetEchoPathGain(aec_state, /*gain_for_early_reflections=*/true); @@ -210,6 +215,7 @@ void ResidualEchoEstimator::Estimate( if (aec_state.SaturatedEcho()) { for (size_t ch = 0; ch < num_capture_channels; ++ch) { std::copy(Y2[ch].begin(), Y2[ch].end(), R2[ch].begin()); + std::copy(Y2[ch].begin(), Y2[ch].end(), R2_unbounded[ch].begin()); } } else { // Estimate the echo generating signal power. @@ -229,11 +235,14 @@ void ResidualEchoEstimator::Estimate( } NonLinearEstimate(echo_path_gain, X2, R2); + NonLinearEstimate(echo_path_gain, X2, R2_unbounded); } if (config_.echo_model.model_reverb_in_nonlinear_mode && !aec_state.TransparentModeActive()) { - AddReverb(ReverbType::kNonLinear, aec_state, render_buffer, R2); + UpdateReverb(ReverbType::kNonLinear, aec_state, render_buffer); + AddReverb(R2); + AddReverb(R2_unbounded); } } @@ -244,6 +253,7 @@ void ResidualEchoEstimator::Estimate( for (size_t ch = 0; ch < num_capture_channels; ++ch) { for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) { R2[ch][k] *= residual_scaling[k]; + R2_unbounded[ch][k] *= residual_scaling[k]; } } } @@ -292,14 +302,10 @@ void ResidualEchoEstimator::UpdateRenderNoisePower( } } -// Adds the estimated power of the reverb to the residual echo power. -void ResidualEchoEstimator::AddReverb( - ReverbType reverb_type, - const AecState& aec_state, - const RenderBuffer& render_buffer, - rtc::ArrayView> R2) { - const size_t num_capture_channels = R2.size(); - +// Updates the reverb estimation. +void ResidualEchoEstimator::UpdateReverb(ReverbType reverb_type, + const AecState& aec_state, + const RenderBuffer& render_buffer) { // Choose reverb partition based on what type of echo power model is used. const size_t first_reverb_partition = reverb_type == ReverbType::kLinear @@ -334,6 +340,11 @@ void ResidualEchoEstimator::AddReverb( echo_reverb_.UpdateReverbNoFreqShaping(render_power, echo_path_gain, aec_state.ReverbDecay()); } +} +// Adds the estimated power of the reverb to the residual echo power. +void ResidualEchoEstimator::AddReverb( + rtc::ArrayView> R2) const { + const size_t num_capture_channels = R2.size(); // Add the reverb power. rtc::ArrayView reverb_power = diff --git a/modules/audio_processing/aec3/residual_echo_estimator.h b/modules/audio_processing/aec3/residual_echo_estimator.h index 9e977766cb..c071854c4a 100644 --- a/modules/audio_processing/aec3/residual_echo_estimator.h +++ b/modules/audio_processing/aec3/residual_echo_estimator.h @@ -40,7 +40,8 @@ class ResidualEchoEstimator { rtc::ArrayView> S2_linear, rtc::ArrayView> Y2, bool dominant_nearend, - rtc::ArrayView> R2); + rtc::ArrayView> R2, + rtc::ArrayView> R2_unbounded); private: enum class ReverbType { kLinear, kNonLinear }; @@ -52,12 +53,15 @@ class ResidualEchoEstimator { // render signal. void UpdateRenderNoisePower(const RenderBuffer& render_buffer); + // Updates the reverb estimation. + void UpdateReverb(ReverbType reverb_type, + const AecState& aec_state, + const RenderBuffer& render_buffer); + // Adds the estimated unmodelled echo power to the residual echo power // estimate. - void AddReverb(ReverbType reverb_type, - const AecState& aec_state, - const RenderBuffer& render_buffer, - rtc::ArrayView> R2); + void AddReverb( + rtc::ArrayView> R2) const; // Gets the echo path gain to apply. float GetEchoPathGain(const AecState& aec_state, diff --git a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc index e80838b5f6..3d760b7dda 100644 --- a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc +++ b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc @@ -48,6 +48,8 @@ TEST_P(ResidualEchoEstimatorMultiChannel, BasicTest) { num_capture_channels); std::vector> Y2(num_capture_channels); std::vector> R2(num_capture_channels); + std::vector> R2_unbounded( + num_capture_channels); std::vector>> x( kNumBands, std::vector>( num_render_channels, std::vector(kBlockSize, 0.f))); @@ -100,7 +102,8 @@ TEST_P(ResidualEchoEstimatorMultiChannel, BasicTest) { output); estimator.Estimate(aec_state, *render_delay_buffer->GetRenderBuffer(), - S2_linear, Y2, /*dominant_nearend=*/false, R2); + S2_linear, Y2, /*dominant_nearend=*/false, R2, + R2_unbounded); } } diff --git a/modules/audio_processing/aec3/subband_erle_estimator.cc b/modules/audio_processing/aec3/subband_erle_estimator.cc index 1e957f23ac..dc7f92fd99 100644 --- a/modules/audio_processing/aec3/subband_erle_estimator.cc +++ b/modules/audio_processing/aec3/subband_erle_estimator.cc @@ -49,6 +49,7 @@ SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config, accum_spectra_(num_capture_channels), erle_(num_capture_channels), erle_onset_compensated_(num_capture_channels), + erle_unbounded_(num_capture_channels), erle_during_onsets_(num_capture_channels), coming_onset_(num_capture_channels), hold_counters_(num_capture_channels) { @@ -62,6 +63,7 @@ void SubbandErleEstimator::Reset() { for (size_t ch = 0; ch < num_capture_channels; ++ch) { erle_[ch].fill(min_erle_); erle_onset_compensated_[ch].fill(min_erle_); + erle_unbounded_[ch].fill(min_erle_); erle_during_onsets_[ch].fill(min_erle_); coming_onset_[ch].fill(true); hold_counters_[ch].fill(0); @@ -90,6 +92,10 @@ void SubbandErleEstimator::Update( auto& erle_oc = erle_onset_compensated_[ch]; erle_oc[0] = erle_oc[1]; erle_oc[kFftLengthBy2] = erle_oc[kFftLengthBy2 - 1]; + + auto& erle_u = erle_unbounded_[ch]; + erle_u[0] = erle_u[1]; + erle_u[kFftLengthBy2] = erle_u[kFftLengthBy2 - 1]; } } @@ -163,6 +169,11 @@ void SubbandErleEstimator::UpdateBands( update_erle_band(erle_onset_compensated_[ch][k], new_erle[k], low_render_energy, min_erle_, max_erle_[k]); } + + // Virtually unbounded ERLE. + constexpr float kUnboundedErleMax = 100000.0f; + update_erle_band(erle_unbounded_[ch][k], new_erle[k], low_render_energy, + min_erle_, kUnboundedErleMax); } } } diff --git a/modules/audio_processing/aec3/subband_erle_estimator.h b/modules/audio_processing/aec3/subband_erle_estimator.h index ffed6a57a5..8bf9c4d645 100644 --- a/modules/audio_processing/aec3/subband_erle_estimator.h +++ b/modules/audio_processing/aec3/subband_erle_estimator.h @@ -47,6 +47,12 @@ class SubbandErleEstimator { : erle_; } + // Returns the non-capped ERLE estimate. + rtc::ArrayView> ErleUnbounded() + const { + return erle_unbounded_; + } + // Returns the ERLE estimate at onsets (only used for testing). rtc::ArrayView> ErleDuringOnsets() const { @@ -88,6 +94,7 @@ class SubbandErleEstimator { std::vector> erle_; // ERLE lowered during render onsets. std::vector> erle_onset_compensated_; + std::vector> erle_unbounded_; // Estimation of ERLE during render onsets. std::vector> erle_during_onsets_; std::vector> coming_onset_; diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc index 601c9c2664..6405d71c2d 100644 --- a/modules/audio_processing/aec3/suppression_gain.cc +++ b/modules/audio_processing/aec3/suppression_gain.cc @@ -23,10 +23,15 @@ #include "modules/audio_processing/logging/apm_data_dumper.h" #include "rtc_base/atomic_ops.h" #include "rtc_base/checks.h" +#include "system_wrappers/include/field_trial.h" namespace webrtc { namespace { +bool UseUnboundedEchoSpectrum() { + return field_trial::IsEnabled("WebRTC-Aec3UseUnboundedEchoSpectrum"); +} + void LimitLowFrequencyGains(std::array* gain) { // Limit the low frequency gains to avoid the impact of the high-pass filter // on the lower-frequency gain influencing the overall achieved gain. @@ -342,7 +347,8 @@ SuppressionGain::SuppressionGain(const EchoCanceller3Config& config, config_.suppressor.nearend_tuning), normal_params_(config_.suppressor.last_lf_band, config_.suppressor.first_hf_band, - config_.suppressor.normal_tuning) { + config_.suppressor.normal_tuning), + use_unbounded_echo_spectrum_(UseUnboundedEchoSpectrum()) { RTC_DCHECK_LT(0, state_change_duration_blocks_); last_gain_.fill(1.f); if (config_.suppressor.use_subband_nearend_detection) { @@ -363,6 +369,8 @@ void SuppressionGain::GetGain( rtc::ArrayView> echo_spectrum, rtc::ArrayView> residual_echo_spectrum, + rtc::ArrayView> + residual_echo_spectrum_unbounded, rtc::ArrayView> comfort_noise_spectrum, const RenderSignalAnalyzer& render_signal_analyzer, @@ -374,8 +382,13 @@ void SuppressionGain::GetGain( RTC_DCHECK(high_bands_gain); RTC_DCHECK(low_band_gain); + // Choose residual echo spectrum for the dominant nearend detector. + const auto echo = use_unbounded_echo_spectrum_ + ? residual_echo_spectrum_unbounded + : residual_echo_spectrum; + // Update the nearend state selection. - dominant_nearend_detector_->Update(nearend_spectrum, residual_echo_spectrum, + dominant_nearend_detector_->Update(nearend_spectrum, echo, comfort_noise_spectrum, initial_state_); // Compute gain for the lower band. @@ -391,6 +404,9 @@ void SuppressionGain::GetGain( *high_bands_gain = UpperBandsGain(echo_spectrum, comfort_noise_spectrum, narrow_peak_band, aec_state.SaturatedEcho(), render, *low_band_gain); + + data_dumper_->DumpRaw("aec3_dominant_nearend", + dominant_nearend_detector_->IsNearendState()); } void SuppressionGain::SetInitialState(bool state) { diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h index 57264c262b..7c4a1c9f7d 100644 --- a/modules/audio_processing/aec3/suppression_gain.h +++ b/modules/audio_processing/aec3/suppression_gain.h @@ -42,6 +42,8 @@ class SuppressionGain { rtc::ArrayView> echo_spectrum, rtc::ArrayView> residual_echo_spectrum, + rtc::ArrayView> + residual_echo_spectrum_unbounded, rtc::ArrayView> comfort_noise_spectrum, const RenderSignalAnalyzer& render_signal_analyzer, @@ -128,6 +130,9 @@ class SuppressionGain { std::vector nearend_smoothers_; const GainParameters nearend_params_; const GainParameters normal_params_; + // Determines if the dominant nearend detector uses the unbounded residual + // echo spectrum. + const bool use_unbounded_echo_spectrum_; std::unique_ptr dominant_nearend_detector_; RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain); diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc index 26bfc24ebb..999b0f27ab 100644 --- a/modules/audio_processing/aec3/suppression_gain_unittest.cc +++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc @@ -26,29 +26,30 @@ namespace aec3 { // Verifies that the check for non-null output gains works. TEST(SuppressionGainDeathTest, NullOutputGains) { - std::vector> E2(1, {0.f}); - std::vector> R2(1, {0.f}); + std::vector> E2(1, {0.0f}); + std::vector> R2(1, {0.0f}); + std::vector> R2_unbounded(1, {0.0f}); std::vector> S2(1); - std::vector> N2(1, {0.f}); + std::vector> N2(1, {0.0f}); for (auto& S2_k : S2) { - S2_k.fill(.1f); + S2_k.fill(0.1f); } FftData E; FftData Y; - E.re.fill(0.f); - E.im.fill(0.f); - Y.re.fill(0.f); - Y.im.fill(0.f); + E.re.fill(0.0f); + E.im.fill(0.0f); + Y.re.fill(0.0f); + Y.im.fill(0.0f); float high_bands_gain; AecState aec_state(EchoCanceller3Config{}, 1); EXPECT_DEATH( SuppressionGain(EchoCanceller3Config{}, DetectOptimization(), 16000, 1) - .GetGain(E2, S2, R2, N2, + .GetGain(E2, S2, R2, R2_unbounded, N2, RenderSignalAnalyzer((EchoCanceller3Config{})), aec_state, std::vector>>( 3, std::vector>( - 1, std::vector(kBlockSize, 0.f))), + 1, std::vector(kBlockSize, 0.0f))), false, &high_bands_gain, nullptr), ""); } @@ -67,15 +68,17 @@ TEST(SuppressionGain, BasicGainComputation) { float high_bands_gain; std::vector> E2(kNumCaptureChannels); std::vector> S2(kNumCaptureChannels, - {0.f}); + {0.0f}); std::vector> Y2(kNumCaptureChannels); std::vector> R2(kNumCaptureChannels); + std::vector> R2_unbounded( + kNumCaptureChannels); std::vector> N2(kNumCaptureChannels); std::array g; std::vector output(kNumCaptureChannels); std::vector>> x( kNumBands, std::vector>( - kNumRenderChannels, std::vector(kBlockSize, 0.f))); + kNumRenderChannels, std::vector(kBlockSize, 0.0f))); EchoCanceller3Config config; AecState aec_state(config, kNumCaptureChannels); ApmDataDumper data_dumper(42); @@ -89,8 +92,9 @@ TEST(SuppressionGain, BasicGainComputation) { for (size_t ch = 0; ch < kNumCaptureChannels; ++ch) { E2[ch].fill(10.f); Y2[ch].fill(10.f); - R2[ch].fill(.1f); - N2[ch].fill(100.f); + R2[ch].fill(0.1f); + R2_unbounded[ch].fill(0.1f); + N2[ch].fill(100.0f); } for (auto& subtractor_output : output) { subtractor_output.Reset(); @@ -107,17 +111,18 @@ TEST(SuppressionGain, BasicGainComputation) { aec_state.Update(delay_estimate, subtractor.FilterFrequencyResponses(), subtractor.FilterImpulseResponses(), *render_delay_buffer->GetRenderBuffer(), E2, Y2, output); - suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, false, - &high_bands_gain, &g); + suppression_gain.GetGain(E2, S2, R2, R2_unbounded, N2, analyzer, aec_state, + x, false, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), - [](float a) { EXPECT_NEAR(1.f, a, 0.001); }); + [](float a) { EXPECT_NEAR(1.0f, a, 0.001f); }); // Ensure that a strong nearend is detected to mask any echoes. for (size_t ch = 0; ch < kNumCaptureChannels; ++ch) { E2[ch].fill(100.f); Y2[ch].fill(100.f); R2[ch].fill(0.1f); + R2_unbounded[ch].fill(0.1f); S2[ch].fill(0.1f); N2[ch].fill(0.f); } @@ -126,22 +131,23 @@ TEST(SuppressionGain, BasicGainComputation) { aec_state.Update(delay_estimate, subtractor.FilterFrequencyResponses(), subtractor.FilterImpulseResponses(), *render_delay_buffer->GetRenderBuffer(), E2, Y2, output); - suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, false, - &high_bands_gain, &g); + suppression_gain.GetGain(E2, S2, R2, R2_unbounded, N2, analyzer, aec_state, + x, false, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), - [](float a) { EXPECT_NEAR(1.f, a, 0.001); }); + [](float a) { EXPECT_NEAR(1.0f, a, 0.001f); }); // Add a strong echo to one of the channels and ensure that it is suppressed. - E2[1].fill(1000000000.f); - R2[1].fill(10000000000000.f); + E2[1].fill(1000000000.0f); + R2[1].fill(10000000000000.0f); + R2_unbounded[1].fill(10000000000000.0f); for (int k = 0; k < 10; ++k) { - suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, false, - &high_bands_gain, &g); + suppression_gain.GetGain(E2, S2, R2, R2_unbounded, N2, analyzer, aec_state, + x, false, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), - [](float a) { EXPECT_NEAR(0.f, a, 0.001); }); + [](float a) { EXPECT_NEAR(0.0f, a, 0.001f); }); } } // namespace aec3