diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index 01a5fc585e..14b83e10be 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -23,49 +23,27 @@ namespace webrtc { namespace { // Computes delay of the adaptive filter. -rtc::Optional EstimateFilterDelay( +int EstimateFilterDelay( const std::vector>& adaptive_filter_frequency_response) { const auto& H2 = adaptive_filter_frequency_response; - - size_t reliable_delays_sum = 0; - size_t num_reliable_delays = 0; - constexpr size_t kUpperBin = kFftLengthBy2 - 5; - constexpr float kMinPeakMargin = 10.f; - const size_t kTailPartition = H2.size() - 1; + RTC_DCHECK_GE(kAdaptiveFilterLength, H2.size()); + std::array delays; + delays.fill(0); for (size_t k = 1; k < kUpperBin; ++k) { // Find the maximum of H2[j]. - int peak = 0; + size_t peak = 0; for (size_t j = 0; j < H2.size(); ++j) { if (H2[j][k] > H2[peak][k]) { peak = j; } } - - // Count the peak as a delay only if the peak is sufficiently larger than - // the tail. - if (kMinPeakMargin * H2[kTailPartition][k] < H2[peak][k]) { - reliable_delays_sum += peak; - ++num_reliable_delays; - } + ++delays[peak]; } - // Return no delay if not sufficient delays have been found. - if (num_reliable_delays < 21) { - return rtc::Optional(); - } - - const size_t delay = reliable_delays_sum / num_reliable_delays; - // Sanity check that the peak is not caused by a false strong DC-component in - // the filter. - for (size_t k = 1; k < kUpperBin; ++k) { - if (H2[delay][k] > H2[delay][0]) { - RTC_DCHECK_GT(H2.size(), delay); - return rtc::Optional(delay); - } - } - return rtc::Optional(); + return std::distance(delays.begin(), + std::max_element(delays.begin(), delays.end())); } } // namespace @@ -130,14 +108,15 @@ void AecState::Update(const std::vector>& force_zero_gain_ = (++force_zero_gain_counter_) < kNumBlocksPerSecond / 5; // Estimate delays. - filter_delay_ = EstimateFilterDelay(adaptive_filter_frequency_response); + filter_delay_ = rtc::Optional( + EstimateFilterDelay(adaptive_filter_frequency_response)); external_delay_ = external_delay_samples ? rtc::Optional(*external_delay_samples / kBlockSize) : rtc::Optional(); // Update the ERL and ERLE measures. - if (filter_delay_ && capture_block_counter_ >= 2 * kNumBlocksPerSecond) { + if (converged_filter && capture_block_counter_ >= 2 * kNumBlocksPerSecond) { const auto& X2 = render_buffer.Spectrum(*filter_delay_); erle_estimator_.Update(X2, Y2, E2_main); erl_estimator_.Update(X2, Y2); @@ -171,8 +150,7 @@ void AecState::Update(const std::vector>& // Flag whether the linear filter estimate is usable. usable_linear_estimate_ = (!echo_saturation_) && (converged_filter || SufficientFilterUpdates()) && - filter_delay_ && capture_block_counter_ >= 2 * kNumBlocksPerSecond && - external_delay_; + capture_block_counter_ >= 2 * kNumBlocksPerSecond && external_delay_; // After an amount of active render samples for which an echo should have been // detected in the capture signal if the ERL was not infinite, flag that a diff --git a/modules/audio_processing/aec3/aec_state_unittest.cc b/modules/audio_processing/aec3/aec_state_unittest.cc index 9a84ef6136..4956456a8c 100644 --- a/modules/audio_processing/aec3/aec_state_unittest.cc +++ b/modules/audio_processing/aec3/aec_state_unittest.cc @@ -161,35 +161,6 @@ TEST(AecState, NormalUsage) { } } -// Verifies the a non-significant delay is correctly identified. -TEST(AecState, NonSignificantDelay) { - AecState state(AudioProcessing::Config::EchoCanceller3{}); - RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, - std::vector(1, 30)); - std::array E2_main; - std::array Y2; - std::array x; - EchoPathVariability echo_path_variability(false, false); - std::array s; - s.fill(100.f); - x.fill(0.f); - - std::vector> frequency_response(30); - for (auto& v : frequency_response) { - v.fill(0.01f); - } - - std::array impulse_response; - impulse_response.fill(0.f); - - // Verify that a non-significant filter delay is identified correctly. - state.HandleEchoPathChange(echo_path_variability); - state.Update(frequency_response, impulse_response, true, - rtc::Optional(), render_buffer, E2_main, Y2, x, s, - false); - EXPECT_FALSE(state.FilterDelay()); -} - // Verifies the delay for a converged filter is correctly identified. TEST(AecState, ConvergedFilterDelay) { constexpr int kFilterLength = 10; @@ -243,7 +214,8 @@ TEST(AecState, ExternalDelay) { x.fill(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); - std::vector> frequency_response(30); + std::vector> frequency_response( + kAdaptiveFilterLength); for (auto& v : frequency_response) { v.fill(0.01f); }