blob: 5b31e3cb9f714fbd024a84f5fa89af4bcf61c1e1 [file] [log] [blame]
peah522d71b2017-02-23 05:16:26 -08001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/aec_state.h"
peah522d71b2017-02-23 05:16:26 -080012
13#include <math.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey988cc082018-10-23 12:03:01 +020015#include <algorithm>
peah522d71b2017-02-23 05:16:26 -080016#include <numeric>
17#include <vector>
18
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +020019#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/array_view.h"
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +020021#include "modules/audio_processing/aec3/aec3_common.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/audio_processing/logging/apm_data_dumper.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/atomic_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/checks.h"
Per Åhgrend8d09c32020-04-01 17:30:18 +020025#include "system_wrappers/include/field_trial.h"
peah522d71b2017-02-23 05:16:26 -080026
27namespace webrtc {
28namespace {
29
Per Åhgrend8d09c32020-04-01 17:30:18 +020030bool DeactivateInitialStateResetAtEchoPathChange() {
31 return field_trial::IsEnabled(
32 "WebRTC-Aec3DeactivateInitialStateResetKillSwitch");
33}
34
35bool FullResetAtEchoPathChange() {
36 return !field_trial::IsEnabled("WebRTC-Aec3AecStateFullResetKillSwitch");
37}
38
39bool SubtractorAnalyzerResetAtEchoPathChange() {
40 return !field_trial::IsEnabled(
41 "WebRTC-Aec3AecStateSubtractorAnalyzerResetKillSwitch");
42}
43
Per Åhgren8718afb2019-10-15 10:31:35 +020044void ComputeAvgRenderReverb(
Per Åhgren1d3008b2019-10-09 12:54:43 +020045 const SpectrumBuffer& spectrum_buffer,
46 int delay_blocks,
47 float reverb_decay,
48 ReverbModel* reverb_model,
49 rtc::ArrayView<float, kFftLengthBy2Plus1> reverb_power_spectrum) {
50 RTC_DCHECK(reverb_model);
51 const size_t num_render_channels = spectrum_buffer.buffer[0].size();
52 int idx_at_delay =
53 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
54 int idx_past = spectrum_buffer.IncIndex(idx_at_delay);
55
56 std::array<float, kFftLengthBy2Plus1> X2_data;
57 rtc::ArrayView<const float> X2;
58 if (num_render_channels > 1) {
Per Åhgren785d4c42019-10-17 14:40:54 +020059 auto average_channels =
Per Åhgren1d3008b2019-10-09 12:54:43 +020060 [](size_t num_render_channels,
Sam Zackrisson98872dc2019-10-18 08:20:09 +020061 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>>
62 spectrum_band_0,
Per Åhgren1d3008b2019-10-09 12:54:43 +020063 rtc::ArrayView<float, kFftLengthBy2Plus1> render_power) {
64 std::fill(render_power.begin(), render_power.end(), 0.f);
65 for (size_t ch = 0; ch < num_render_channels; ++ch) {
Per Åhgren1d3008b2019-10-09 12:54:43 +020066 for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
67 render_power[k] += spectrum_band_0[ch][k];
68 }
69 }
Per Åhgren785d4c42019-10-17 14:40:54 +020070 const float normalizer = 1.f / num_render_channels;
71 for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
72 render_power[k] *= normalizer;
73 }
Per Åhgren1d3008b2019-10-09 12:54:43 +020074 };
Per Åhgren785d4c42019-10-17 14:40:54 +020075 average_channels(num_render_channels, spectrum_buffer.buffer[idx_past],
76 X2_data);
Per Åhgren1d3008b2019-10-09 12:54:43 +020077 reverb_model->UpdateReverbNoFreqShaping(
78 X2_data, /*power_spectrum_scaling=*/1.0f, reverb_decay);
79
Per Åhgren785d4c42019-10-17 14:40:54 +020080 average_channels(num_render_channels, spectrum_buffer.buffer[idx_at_delay],
81 X2_data);
Per Åhgren1d3008b2019-10-09 12:54:43 +020082 X2 = X2_data;
83 } else {
84 reverb_model->UpdateReverbNoFreqShaping(
85 spectrum_buffer.buffer[idx_past][/*channel=*/0],
86 /*power_spectrum_scaling=*/1.0f, reverb_decay);
87
88 X2 = spectrum_buffer.buffer[idx_at_delay][/*channel=*/0];
89 }
90
91 rtc::ArrayView<const float, kFftLengthBy2Plus1> reverb_power =
92 reverb_model->reverb();
93 for (size_t k = 0; k < X2.size(); ++k) {
94 reverb_power_spectrum[k] = X2[k] + reverb_power[k];
95 }
96}
97
peah522d71b2017-02-23 05:16:26 -080098} // namespace
99
100int AecState::instance_count_ = 0;
101
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200102void AecState::GetResidualEchoScaling(
103 rtc::ArrayView<float> residual_scaling) const {
104 bool filter_has_had_time_to_converge;
105 if (config_.filter.conservative_initial_phase) {
106 filter_has_had_time_to_converge =
107 strong_not_saturated_render_blocks_ >= 1.5f * kNumBlocksPerSecond;
108 } else {
109 filter_has_had_time_to_converge =
110 strong_not_saturated_render_blocks_ >= 0.8f * kNumBlocksPerSecond;
111 }
112 echo_audibility_.GetResidualEchoScaling(filter_has_had_time_to_converge,
113 residual_scaling);
114}
115
116absl::optional<float> AecState::ErleUncertainty() const {
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100117 if (SaturatedEcho()) {
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200118 return 1.f;
119 }
120
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200121 return absl::nullopt;
122}
123
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200124AecState::AecState(const EchoCanceller3Config& config,
125 size_t num_capture_channels)
peah522d71b2017-02-23 05:16:26 -0800126 : data_dumper_(
127 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
peah8cee56f2017-08-24 22:36:53 -0700128 config_(config),
Per Åhgren785d4c42019-10-17 14:40:54 +0200129 num_capture_channels_(num_capture_channels),
Per Åhgrend8d09c32020-04-01 17:30:18 +0200130 deactivate_initial_state_reset_at_echo_path_change_(
131 DeactivateInitialStateResetAtEchoPathChange()),
132 full_reset_at_echo_path_change_(FullResetAtEchoPathChange()),
133 subtractor_analyzer_reset_at_echo_path_change_(
134 SubtractorAnalyzerResetAtEchoPathChange()),
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200135 initial_state_(config_),
Per Åhgren785d4c42019-10-17 14:40:54 +0200136 delay_state_(config_, num_capture_channels_),
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200137 transparent_state_(TransparentMode::Create(config_)),
Per Åhgren785d4c42019-10-17 14:40:54 +0200138 filter_quality_state_(config_, num_capture_channels_),
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200139 erl_estimator_(2 * kNumBlocksPerSecond),
Per Åhgren785d4c42019-10-17 14:40:54 +0200140 erle_estimator_(2 * kNumBlocksPerSecond, config_, num_capture_channels_),
141 filter_analyzer_(config_, num_capture_channels_),
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +0200142 echo_audibility_(
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200143 config_.echo_audibility.use_stationarity_properties_at_init),
Per Åhgren785d4c42019-10-17 14:40:54 +0200144 reverb_model_estimator_(config_, num_capture_channels_),
145 subtractor_output_analyzer_(num_capture_channels_) {}
peah522d71b2017-02-23 05:16:26 -0800146
147AecState::~AecState() = default;
148
peah86afe9d2017-04-06 15:45:32 -0700149void AecState::HandleEchoPathChange(
150 const EchoPathVariability& echo_path_variability) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100151 const auto full_reset = [&]() {
Per Åhgren8be669f2019-10-11 23:02:26 +0200152 filter_analyzer_.Reset();
peah86afe9d2017-04-06 15:45:32 -0700153 capture_signal_saturation_ = false;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200154 strong_not_saturated_render_blocks_ = 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100155 blocks_with_active_render_ = 0;
Per Åhgrend8d09c32020-04-01 17:30:18 +0200156 if (!deactivate_initial_state_reset_at_echo_path_change_) {
157 initial_state_.Reset();
158 }
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200159 if (transparent_state_) {
160 transparent_state_->Reset();
161 }
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200162 erle_estimator_.Reset(true);
163 erl_estimator_.Reset();
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200164 filter_quality_state_.Reset();
Per Åhgren8ba58612017-12-01 23:01:44 +0100165 };
peah6d822ad2017-04-10 13:52:14 -0700166
Per Åhgren8ba58612017-12-01 23:01:44 +0100167 // TODO(peah): Refine the reset scheme according to the type of gain and
168 // delay adjustment.
Per Åhgren8ba58612017-12-01 23:01:44 +0100169
Per Åhgrend8d09c32020-04-01 17:30:18 +0200170 if (full_reset_at_echo_path_change_ &&
171 echo_path_variability.delay_change !=
172 EchoPathVariability::DelayAdjustment::kNone) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100173 full_reset();
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100174 } else if (echo_path_variability.gain_change) {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200175 erle_estimator_.Reset(false);
Per Åhgrend2650d12018-10-02 17:00:59 +0200176 }
Per Åhgrend8d09c32020-04-01 17:30:18 +0200177 if (subtractor_analyzer_reset_at_echo_path_change_) {
178 subtractor_output_analyzer_.HandleEchoPathChange();
179 }
peah86afe9d2017-04-06 15:45:32 -0700180}
181
Per Åhgren09a718a2017-12-11 22:28:45 +0100182void AecState::Update(
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200183 const absl::optional<DelayEstimate>& external_delay,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200184 rtc::ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
Per Åhgren8be669f2019-10-11 23:02:26 +0200185 adaptive_filter_frequency_responses,
186 rtc::ArrayView<const std::vector<float>> adaptive_filter_impulse_responses,
Per Åhgren09a718a2017-12-11 22:28:45 +0100187 const RenderBuffer& render_buffer,
Per Åhgrenff045112020-03-20 11:20:39 +0100188 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2_refined,
Per Åhgrenf9807252019-10-09 13:57:07 +0200189 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200190 rtc::ArrayView<const SubtractorOutput> subtractor_output) {
Per Åhgren785d4c42019-10-17 14:40:54 +0200191 RTC_DCHECK_EQ(num_capture_channels_, Y2.size());
192 RTC_DCHECK_EQ(num_capture_channels_, subtractor_output.size());
193 RTC_DCHECK_EQ(num_capture_channels_,
Per Åhgren8be669f2019-10-11 23:02:26 +0200194 adaptive_filter_frequency_responses.size());
Per Åhgren785d4c42019-10-17 14:40:54 +0200195 RTC_DCHECK_EQ(num_capture_channels_,
196 adaptive_filter_impulse_responses.size());
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200197
Sam Zackrisson46b01402019-10-08 16:17:48 +0200198 // Analyze the filter outputs and filters.
Per Åhgren785d4c42019-10-17 14:40:54 +0200199 bool any_filter_converged;
Gustaf Ullberg7481ba02020-10-21 11:44:18 +0200200 bool any_coarse_filter_converged;
Per Åhgren785d4c42019-10-17 14:40:54 +0200201 bool all_filters_diverged;
202 subtractor_output_analyzer_.Update(subtractor_output, &any_filter_converged,
Gustaf Ullberg7481ba02020-10-21 11:44:18 +0200203 &any_coarse_filter_converged,
Per Åhgren785d4c42019-10-17 14:40:54 +0200204 &all_filters_diverged);
205
Per Åhgren8be669f2019-10-11 23:02:26 +0200206 bool any_filter_consistent;
207 float max_echo_path_gain;
208 filter_analyzer_.Update(adaptive_filter_impulse_responses, render_buffer,
209 &any_filter_consistent, &max_echo_path_gain);
peah86afe9d2017-04-06 15:45:32 -0700210
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200211 // Estimate the direct path delay of the filter.
Gustaf Ullberg9466b662019-04-15 09:53:03 +0200212 if (config_.filter.use_linear_filter) {
Per Åhgren8be669f2019-10-11 23:02:26 +0200213 delay_state_.Update(filter_analyzer_.FilterDelaysBlocks(), external_delay,
Gustaf Ullberg9466b662019-04-15 09:53:03 +0200214 strong_not_saturated_render_blocks_);
215 }
Per Åhgren5c532d32018-03-22 00:29:25 +0100216
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200217 const std::vector<std::vector<float>>& aligned_render_block =
Per Åhgren88d662a2019-10-16 15:32:39 +0200218 render_buffer.Block(-delay_state_.MinDirectPathFilterDelay())[0];
Per Åhgren5c532d32018-03-22 00:29:25 +0100219
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200220 // Update render counters.
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200221 bool active_render = false;
222 for (size_t ch = 0; ch < aligned_render_block.size(); ++ch) {
223 const float render_energy = std::inner_product(
224 aligned_render_block[ch].begin(), aligned_render_block[ch].end(),
225 aligned_render_block[ch].begin(), 0.f);
226 if (render_energy > (config_.render_levels.active_render_limit *
227 config_.render_levels.active_render_limit) *
228 kFftLengthBy2) {
229 active_render = true;
230 break;
231 }
232 }
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200233 blocks_with_active_render_ += active_render ? 1 : 0;
234 strong_not_saturated_render_blocks_ +=
235 active_render && !SaturatedCapture() ? 1 : 0;
Per Åhgren0e6d2f52017-12-20 22:19:56 +0100236
Per Åhgren8718afb2019-10-15 10:31:35 +0200237 std::array<float, kFftLengthBy2Plus1> avg_render_spectrum_with_reverb;
Per Åhgren1d3008b2019-10-09 12:54:43 +0200238
Per Åhgren8718afb2019-10-15 10:31:35 +0200239 ComputeAvgRenderReverb(render_buffer.GetSpectrumBuffer(),
240 delay_state_.MinDirectPathFilterDelay(), ReverbDecay(),
241 &avg_render_reverb_, avg_render_spectrum_with_reverb);
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200242
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200243 if (config_.echo_audibility.use_stationarity_properties) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200244 // Update the echo audibility evaluator.
Per Åhgren8718afb2019-10-15 10:31:35 +0200245 echo_audibility_.Update(render_buffer, avg_render_reverb_.reverb(),
246 delay_state_.MinDirectPathFilterDelay(),
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200247 delay_state_.ExternalDelayReported());
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200248 }
249
peah86afe9d2017-04-06 15:45:32 -0700250 // Update the ERL and ERLE measures.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200251 if (initial_state_.TransitionTriggered()) {
252 erle_estimator_.Reset(false);
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200253 }
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200254
Per Åhgren785d4c42019-10-17 14:40:54 +0200255 erle_estimator_.Update(render_buffer, adaptive_filter_frequency_responses,
Per Åhgrenff045112020-03-20 11:20:39 +0100256 avg_render_spectrum_with_reverb, Y2, E2_refined,
Per Åhgren785d4c42019-10-17 14:40:54 +0200257 subtractor_output_analyzer_.ConvergedFilters());
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200258
Sam Zackrisson6e5433c2019-10-18 16:49:13 +0200259 erl_estimator_.Update(
260 subtractor_output_analyzer_.ConvergedFilters(),
261 render_buffer.Spectrum(delay_state_.MinDirectPathFilterDelay()), Y2);
peah86afe9d2017-04-06 15:45:32 -0700262
Per Åhgren63b494d2017-12-06 11:32:38 +0100263 // Detect and flag echo saturation.
Per Åhgrend8d09c32020-04-01 17:30:18 +0200264 if (config_.ep_strength.echo_can_saturate) {
265 saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
266 UsableLinearEstimate(), subtractor_output,
267 max_echo_path_gain);
268 } else {
269 RTC_DCHECK(!saturation_detector_.SaturatedEcho());
270 }
peah86afe9d2017-04-06 15:45:32 -0700271
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200272 // Update the decision on whether to use the initial state parameter set.
273 initial_state_.Update(active_render, SaturatedCapture());
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100274
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200275 // Detect whether the transparent mode should be activated.
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200276 if (transparent_state_) {
Gustaf Ullberg7481ba02020-10-21 11:44:18 +0200277 transparent_state_->Update(
278 delay_state_.MinDirectPathFilterDelay(), any_filter_consistent,
279 any_filter_converged, any_coarse_filter_converged, all_filters_diverged,
280 active_render, SaturatedCapture());
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200281 }
Per Åhgren5c532d32018-03-22 00:29:25 +0100282
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200283 // Analyze the quality of the filter.
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200284 filter_quality_state_.Update(active_render, TransparentModeActive(),
Sam Zackrisson46b01402019-10-08 16:17:48 +0200285 SaturatedCapture(), external_delay,
286 any_filter_converged);
Per Åhgrena98c8072018-01-15 19:17:16 +0100287
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200288 // Update the reverb estimate.
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200289 const bool stationary_block =
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200290 config_.echo_audibility.use_stationarity_properties &&
Per Åhgrenf4801a12018-09-27 13:14:02 +0200291 echo_audibility_.IsBlockStationary();
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200292
Per Åhgren8be669f2019-10-11 23:02:26 +0200293 reverb_model_estimator_.Update(
294 filter_analyzer_.GetAdjustedFilters(),
295 adaptive_filter_frequency_responses,
296 erle_estimator_.GetInstLinearQualityEstimates(),
297 delay_state_.DirectPathFilterDelays(),
298 filter_quality_state_.UsableLinearFilterOutputs(), stationary_block);
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200299
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200300 erle_estimator_.Dump(data_dumper_);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200301 reverb_model_estimator_.Dump(data_dumper_.get());
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200302 data_dumper_->DumpRaw("aec3_active_render", active_render);
Per Åhgren5c532d32018-03-22 00:29:25 +0100303 data_dumper_->DumpRaw("aec3_erl", Erl());
Per Åhgren5c532d32018-03-22 00:29:25 +0100304 data_dumper_->DumpRaw("aec3_erl_time_domain", ErlTimeDomain());
Per Åhgrenb4161d32019-10-08 12:35:47 +0200305 data_dumper_->DumpRaw("aec3_erle", Erle()[0]);
Per Åhgren5c532d32018-03-22 00:29:25 +0100306 data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200307 data_dumper_->DumpRaw("aec3_transparent_mode", TransparentModeActive());
Sam Zackrisson46b01402019-10-08 16:17:48 +0200308 data_dumper_->DumpRaw("aec3_filter_delay",
Per Åhgren8be669f2019-10-11 23:02:26 +0200309 filter_analyzer_.MinFilterDelayBlocks());
Per Åhgren5c532d32018-03-22 00:29:25 +0100310
Sam Zackrisson46b01402019-10-08 16:17:48 +0200311 data_dumper_->DumpRaw("aec3_any_filter_consistent", any_filter_consistent);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200312 data_dumper_->DumpRaw("aec3_initial_state",
313 initial_state_.InitialStateActive());
Per Åhgren5c532d32018-03-22 00:29:25 +0100314 data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200315 data_dumper_->DumpRaw("aec3_echo_saturation", SaturatedEcho());
Sam Zackrisson46b01402019-10-08 16:17:48 +0200316 data_dumper_->DumpRaw("aec3_any_filter_converged", any_filter_converged);
Gustaf Ullberg7481ba02020-10-21 11:44:18 +0200317 data_dumper_->DumpRaw("aec3_any_coarse_filter_converged",
318 any_coarse_filter_converged);
Sam Zackrisson46b01402019-10-08 16:17:48 +0200319 data_dumper_->DumpRaw("aec3_all_filters_diverged", all_filters_diverged);
Per Åhgren5c532d32018-03-22 00:29:25 +0100320
321 data_dumper_->DumpRaw("aec3_external_delay_avaliable",
322 external_delay ? 1 : 0);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200323 data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
324 GetReverbFrequencyResponse());
Gustaf Ullberg992a96f2020-12-08 13:03:55 +0100325 data_dumper_->DumpRaw("aec3_subtractor_y2", subtractor_output[0].y2);
326 data_dumper_->DumpRaw("aec3_subtractor_e2_coarse",
327 subtractor_output[0].e2_coarse);
328 data_dumper_->DumpRaw("aec3_subtractor_e2_refined",
329 subtractor_output[0].e2_refined);
peah29103572017-07-11 02:54:02 -0700330}
331
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200332AecState::InitialState::InitialState(const EchoCanceller3Config& config)
333 : conservative_initial_phase_(config.filter.conservative_initial_phase),
334 initial_state_seconds_(config.filter.initial_state_seconds) {
335 Reset();
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100336}
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200337void AecState::InitialState::InitialState::Reset() {
338 initial_state_ = true;
339 strong_not_saturated_render_blocks_ = 0;
340}
341void AecState::InitialState::InitialState::Update(bool active_render,
342 bool saturated_capture) {
343 strong_not_saturated_render_blocks_ +=
344 active_render && !saturated_capture ? 1 : 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100345
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200346 // Flag whether the initial state is still active.
347 bool prev_initial_state = initial_state_;
348 if (conservative_initial_phase_) {
349 initial_state_ =
350 strong_not_saturated_render_blocks_ < 5 * kNumBlocksPerSecond;
Per Åhgren31122d62018-04-10 16:33:55 +0200351 } else {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200352 initial_state_ = strong_not_saturated_render_blocks_ <
353 initial_state_seconds_ * kNumBlocksPerSecond;
Per Åhgren31122d62018-04-10 16:33:55 +0200354 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100355
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200356 // Flag whether the transition from the initial state has started.
357 transition_triggered_ = !initial_state_ && prev_initial_state;
358}
359
Per Åhgren8be669f2019-10-11 23:02:26 +0200360AecState::FilterDelay::FilterDelay(const EchoCanceller3Config& config,
361 size_t num_capture_channels)
Sam Zackrissonfa292792020-10-05 15:23:04 +0200362 : delay_headroom_blocks_(config.delay.delay_headroom_samples / kBlockSize),
363 filter_delays_blocks_(num_capture_channels, delay_headroom_blocks_),
364 min_filter_delay_(delay_headroom_blocks_) {}
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200365
366void AecState::FilterDelay::Update(
Per Åhgren8be669f2019-10-11 23:02:26 +0200367 rtc::ArrayView<const int> analyzer_filter_delay_estimates_blocks,
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200368 const absl::optional<DelayEstimate>& external_delay,
369 size_t blocks_with_proper_filter_adaptation) {
370 // Update the delay based on the external delay.
371 if (external_delay &&
372 (!external_delay_ || external_delay_->delay != external_delay->delay)) {
373 external_delay_ = external_delay;
374 external_delay_reported_ = true;
375 }
376
377 // Override the estimated delay if it is not certain that the filter has had
378 // time to converge.
379 const bool delay_estimator_may_not_have_converged =
380 blocks_with_proper_filter_adaptation < 2 * kNumBlocksPerSecond;
381 if (delay_estimator_may_not_have_converged && external_delay_) {
Sam Zackrissonfa292792020-10-05 15:23:04 +0200382 const int delay_guess = delay_headroom_blocks_;
Per Åhgren8be669f2019-10-11 23:02:26 +0200383 std::fill(filter_delays_blocks_.begin(), filter_delays_blocks_.end(),
384 delay_guess);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200385 } else {
Per Åhgren8be669f2019-10-11 23:02:26 +0200386 RTC_DCHECK_EQ(filter_delays_blocks_.size(),
387 analyzer_filter_delay_estimates_blocks.size());
388 std::copy(analyzer_filter_delay_estimates_blocks.begin(),
389 analyzer_filter_delay_estimates_blocks.end(),
390 filter_delays_blocks_.begin());
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200391 }
Per Åhgren8718afb2019-10-15 10:31:35 +0200392
393 min_filter_delay_ = *std::min_element(filter_delays_blocks_.begin(),
394 filter_delays_blocks_.end());
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200395}
396
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200397AecState::FilteringQualityAnalyzer::FilteringQualityAnalyzer(
Per Åhgren8be669f2019-10-11 23:02:26 +0200398 const EchoCanceller3Config& config,
399 size_t num_capture_channels)
400 : use_linear_filter_(config.filter.use_linear_filter),
401 usable_linear_filter_estimates_(num_capture_channels, false) {}
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200402
403void AecState::FilteringQualityAnalyzer::Reset() {
Per Åhgren8be669f2019-10-11 23:02:26 +0200404 std::fill(usable_linear_filter_estimates_.begin(),
405 usable_linear_filter_estimates_.end(), false);
406 overall_usable_linear_estimates_ = false;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200407 filter_update_blocks_since_reset_ = 0;
408}
409
410void AecState::FilteringQualityAnalyzer::Update(
411 bool active_render,
412 bool transparent_mode,
413 bool saturated_capture,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200414 const absl::optional<DelayEstimate>& external_delay,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200415 bool any_filter_converged) {
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200416 // Update blocks counter.
417 const bool filter_update = active_render && !saturated_capture;
418 filter_update_blocks_since_reset_ += filter_update ? 1 : 0;
419 filter_update_blocks_since_start_ += filter_update ? 1 : 0;
420
421 // Store convergence flag when observed.
Sam Zackrisson46b01402019-10-08 16:17:48 +0200422 convergence_seen_ = convergence_seen_ || any_filter_converged;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200423
424 // Verify requirements for achieving a decent filter. The requirements for
425 // filter adaptation at call startup are more restrictive than after an
426 // in-call reset.
427 const bool sufficient_data_to_converge_at_startup =
428 filter_update_blocks_since_start_ > kNumBlocksPerSecond * 0.4f;
429 const bool sufficient_data_to_converge_at_reset =
430 sufficient_data_to_converge_at_startup &&
431 filter_update_blocks_since_reset_ > kNumBlocksPerSecond * 0.2f;
432
Per Åhgren8be669f2019-10-11 23:02:26 +0200433 // The linear filter can only be used if it has had time to converge.
434 overall_usable_linear_estimates_ = sufficient_data_to_converge_at_startup &&
435 sufficient_data_to_converge_at_reset;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200436
437 // The linear filter can only be used if an external delay or convergence have
438 // been identified
Per Åhgren8be669f2019-10-11 23:02:26 +0200439 overall_usable_linear_estimates_ =
440 overall_usable_linear_estimates_ && (external_delay || convergence_seen_);
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200441
442 // If transparent mode is on, deactivate usign the linear filter.
Per Åhgren8be669f2019-10-11 23:02:26 +0200443 overall_usable_linear_estimates_ =
444 overall_usable_linear_estimates_ && !transparent_mode;
445
446 if (use_linear_filter_) {
447 std::fill(usable_linear_filter_estimates_.begin(),
448 usable_linear_filter_estimates_.end(),
449 overall_usable_linear_estimates_);
450 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200451}
452
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200453void AecState::SaturationDetector::Update(
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200454 rtc::ArrayView<const std::vector<float>> x,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200455 bool saturated_capture,
456 bool usable_linear_estimate,
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200457 rtc::ArrayView<const SubtractorOutput> subtractor_output,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200458 float echo_path_gain) {
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200459 saturated_echo_ = false;
460 if (!saturated_capture) {
461 return;
462 }
463
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200464 if (usable_linear_estimate) {
465 constexpr float kSaturationThreshold = 20000.f;
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200466 for (size_t ch = 0; ch < subtractor_output.size(); ++ch) {
467 saturated_echo_ =
468 saturated_echo_ ||
Per Åhgrenff045112020-03-20 11:20:39 +0100469 (subtractor_output[ch].s_refined_max_abs > kSaturationThreshold ||
Per Åhgren9d661982020-03-20 11:26:48 +0100470 subtractor_output[ch].s_coarse_max_abs > kSaturationThreshold);
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200471 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200472 } else {
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200473 float max_sample = 0.f;
474 for (auto& channel : x) {
475 for (float sample : channel) {
476 max_sample = std::max(max_sample, fabsf(sample));
477 }
478 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200479
480 const float kMargin = 10.f;
481 float peak_echo_amplitude = max_sample * echo_path_gain * kMargin;
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200482 saturated_echo_ = saturated_echo_ || peak_echo_amplitude > 32000;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200483 }
484}
485
peah522d71b2017-02-23 05:16:26 -0800486} // namespace webrtc