blob: 365ec9e5c7e809a4a582dbfe3d4830858377ed22 [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"
peah522d71b2017-02-23 05:16:26 -080025
26namespace webrtc {
27namespace {
28
Per Åhgren5c532d32018-03-22 00:29:25 +010029constexpr size_t kBlocksSinceConvergencedFilterInit = 10000;
30constexpr size_t kBlocksSinceConsistentEstimateInit = 10000;
31
Per Åhgren8718afb2019-10-15 10:31:35 +020032void ComputeAvgRenderReverb(
Per Åhgren1d3008b2019-10-09 12:54:43 +020033 const SpectrumBuffer& spectrum_buffer,
34 int delay_blocks,
35 float reverb_decay,
36 ReverbModel* reverb_model,
37 rtc::ArrayView<float, kFftLengthBy2Plus1> reverb_power_spectrum) {
38 RTC_DCHECK(reverb_model);
39 const size_t num_render_channels = spectrum_buffer.buffer[0].size();
40 int idx_at_delay =
41 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
42 int idx_past = spectrum_buffer.IncIndex(idx_at_delay);
43
44 std::array<float, kFftLengthBy2Plus1> X2_data;
45 rtc::ArrayView<const float> X2;
46 if (num_render_channels > 1) {
Per Åhgren785d4c42019-10-17 14:40:54 +020047 auto average_channels =
Per Åhgren1d3008b2019-10-09 12:54:43 +020048 [](size_t num_render_channels,
Sam Zackrisson98872dc2019-10-18 08:20:09 +020049 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>>
50 spectrum_band_0,
Per Åhgren1d3008b2019-10-09 12:54:43 +020051 rtc::ArrayView<float, kFftLengthBy2Plus1> render_power) {
52 std::fill(render_power.begin(), render_power.end(), 0.f);
53 for (size_t ch = 0; ch < num_render_channels; ++ch) {
Per Åhgren1d3008b2019-10-09 12:54:43 +020054 for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
55 render_power[k] += spectrum_band_0[ch][k];
56 }
57 }
Per Åhgren785d4c42019-10-17 14:40:54 +020058 const float normalizer = 1.f / num_render_channels;
59 for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
60 render_power[k] *= normalizer;
61 }
Per Åhgren1d3008b2019-10-09 12:54:43 +020062 };
Per Åhgren785d4c42019-10-17 14:40:54 +020063 average_channels(num_render_channels, spectrum_buffer.buffer[idx_past],
64 X2_data);
Per Åhgren1d3008b2019-10-09 12:54:43 +020065 reverb_model->UpdateReverbNoFreqShaping(
66 X2_data, /*power_spectrum_scaling=*/1.0f, reverb_decay);
67
Per Åhgren785d4c42019-10-17 14:40:54 +020068 average_channels(num_render_channels, spectrum_buffer.buffer[idx_at_delay],
69 X2_data);
Per Åhgren1d3008b2019-10-09 12:54:43 +020070 X2 = X2_data;
71 } else {
72 reverb_model->UpdateReverbNoFreqShaping(
73 spectrum_buffer.buffer[idx_past][/*channel=*/0],
74 /*power_spectrum_scaling=*/1.0f, reverb_decay);
75
76 X2 = spectrum_buffer.buffer[idx_at_delay][/*channel=*/0];
77 }
78
79 rtc::ArrayView<const float, kFftLengthBy2Plus1> reverb_power =
80 reverb_model->reverb();
81 for (size_t k = 0; k < X2.size(); ++k) {
82 reverb_power_spectrum[k] = X2[k] + reverb_power[k];
83 }
84}
85
peah522d71b2017-02-23 05:16:26 -080086} // namespace
87
88int AecState::instance_count_ = 0;
89
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020090void AecState::GetResidualEchoScaling(
91 rtc::ArrayView<float> residual_scaling) const {
92 bool filter_has_had_time_to_converge;
93 if (config_.filter.conservative_initial_phase) {
94 filter_has_had_time_to_converge =
95 strong_not_saturated_render_blocks_ >= 1.5f * kNumBlocksPerSecond;
96 } else {
97 filter_has_had_time_to_converge =
98 strong_not_saturated_render_blocks_ >= 0.8f * kNumBlocksPerSecond;
99 }
100 echo_audibility_.GetResidualEchoScaling(filter_has_had_time_to_converge,
101 residual_scaling);
102}
103
104absl::optional<float> AecState::ErleUncertainty() const {
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100105 if (SaturatedEcho()) {
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200106 return 1.f;
107 }
108
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200109 return absl::nullopt;
110}
111
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200112AecState::AecState(const EchoCanceller3Config& config,
113 size_t num_capture_channels)
peah522d71b2017-02-23 05:16:26 -0800114 : data_dumper_(
115 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
peah8cee56f2017-08-24 22:36:53 -0700116 config_(config),
Per Åhgren785d4c42019-10-17 14:40:54 +0200117 num_capture_channels_(num_capture_channels),
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200118 initial_state_(config_),
Per Åhgren785d4c42019-10-17 14:40:54 +0200119 delay_state_(config_, num_capture_channels_),
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200120 transparent_state_(config_),
Per Åhgren785d4c42019-10-17 14:40:54 +0200121 filter_quality_state_(config_, num_capture_channels_),
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200122 erl_estimator_(2 * kNumBlocksPerSecond),
Per Åhgren785d4c42019-10-17 14:40:54 +0200123 erle_estimator_(2 * kNumBlocksPerSecond, config_, num_capture_channels_),
124 filter_analyzer_(config_, num_capture_channels_),
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +0200125 echo_audibility_(
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200126 config_.echo_audibility.use_stationarity_properties_at_init),
Per Åhgren785d4c42019-10-17 14:40:54 +0200127 reverb_model_estimator_(config_, num_capture_channels_),
128 subtractor_output_analyzer_(num_capture_channels_) {}
peah522d71b2017-02-23 05:16:26 -0800129
130AecState::~AecState() = default;
131
peah86afe9d2017-04-06 15:45:32 -0700132void AecState::HandleEchoPathChange(
133 const EchoPathVariability& echo_path_variability) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100134 const auto full_reset = [&]() {
Per Åhgren8be669f2019-10-11 23:02:26 +0200135 filter_analyzer_.Reset();
peah86afe9d2017-04-06 15:45:32 -0700136 capture_signal_saturation_ = false;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200137 strong_not_saturated_render_blocks_ = 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100138 blocks_with_active_render_ = 0;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200139 initial_state_.Reset();
140 transparent_state_.Reset();
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200141 erle_estimator_.Reset(true);
142 erl_estimator_.Reset();
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200143 filter_quality_state_.Reset();
Per Åhgren8ba58612017-12-01 23:01:44 +0100144 };
peah6d822ad2017-04-10 13:52:14 -0700145
Per Åhgren8ba58612017-12-01 23:01:44 +0100146 // TODO(peah): Refine the reset scheme according to the type of gain and
147 // delay adjustment.
Per Åhgren8ba58612017-12-01 23:01:44 +0100148
149 if (echo_path_variability.delay_change !=
Per Åhgren88cf0502018-07-16 17:08:41 +0200150 EchoPathVariability::DelayAdjustment::kNone) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100151 full_reset();
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100152 } else if (echo_path_variability.gain_change) {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200153 erle_estimator_.Reset(false);
Per Åhgrend2650d12018-10-02 17:00:59 +0200154 }
Per Åhgren785d4c42019-10-17 14:40:54 +0200155 subtractor_output_analyzer_.HandleEchoPathChange();
peah86afe9d2017-04-06 15:45:32 -0700156}
157
Per Åhgren09a718a2017-12-11 22:28:45 +0100158void AecState::Update(
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200159 const absl::optional<DelayEstimate>& external_delay,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200160 rtc::ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
Per Åhgren8be669f2019-10-11 23:02:26 +0200161 adaptive_filter_frequency_responses,
162 rtc::ArrayView<const std::vector<float>> adaptive_filter_impulse_responses,
Per Åhgren09a718a2017-12-11 22:28:45 +0100163 const RenderBuffer& render_buffer,
Per Åhgrenf9807252019-10-09 13:57:07 +0200164 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2_main,
165 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200166 rtc::ArrayView<const SubtractorOutput> subtractor_output) {
Per Åhgren785d4c42019-10-17 14:40:54 +0200167 RTC_DCHECK_EQ(num_capture_channels_, Y2.size());
168 RTC_DCHECK_EQ(num_capture_channels_, subtractor_output.size());
169 RTC_DCHECK_EQ(num_capture_channels_,
Per Åhgren8be669f2019-10-11 23:02:26 +0200170 adaptive_filter_frequency_responses.size());
Per Åhgren785d4c42019-10-17 14:40:54 +0200171 RTC_DCHECK_EQ(num_capture_channels_,
172 adaptive_filter_impulse_responses.size());
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200173
Sam Zackrisson46b01402019-10-08 16:17:48 +0200174 // Analyze the filter outputs and filters.
Per Åhgren785d4c42019-10-17 14:40:54 +0200175 bool any_filter_converged;
176 bool all_filters_diverged;
177 subtractor_output_analyzer_.Update(subtractor_output, &any_filter_converged,
178 &all_filters_diverged);
179
Per Åhgren8be669f2019-10-11 23:02:26 +0200180 bool any_filter_consistent;
181 float max_echo_path_gain;
182 filter_analyzer_.Update(adaptive_filter_impulse_responses, render_buffer,
183 &any_filter_consistent, &max_echo_path_gain);
peah86afe9d2017-04-06 15:45:32 -0700184
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200185 // Estimate the direct path delay of the filter.
Gustaf Ullberg9466b662019-04-15 09:53:03 +0200186 if (config_.filter.use_linear_filter) {
Per Åhgren8be669f2019-10-11 23:02:26 +0200187 delay_state_.Update(filter_analyzer_.FilterDelaysBlocks(), external_delay,
Gustaf Ullberg9466b662019-04-15 09:53:03 +0200188 strong_not_saturated_render_blocks_);
189 }
Per Åhgren5c532d32018-03-22 00:29:25 +0100190
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200191 const std::vector<std::vector<float>>& aligned_render_block =
Per Åhgren88d662a2019-10-16 15:32:39 +0200192 render_buffer.Block(-delay_state_.MinDirectPathFilterDelay())[0];
Per Åhgren5c532d32018-03-22 00:29:25 +0100193
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200194 // Update render counters.
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200195 bool active_render = false;
196 for (size_t ch = 0; ch < aligned_render_block.size(); ++ch) {
197 const float render_energy = std::inner_product(
198 aligned_render_block[ch].begin(), aligned_render_block[ch].end(),
199 aligned_render_block[ch].begin(), 0.f);
200 if (render_energy > (config_.render_levels.active_render_limit *
201 config_.render_levels.active_render_limit) *
202 kFftLengthBy2) {
203 active_render = true;
204 break;
205 }
206 }
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200207 blocks_with_active_render_ += active_render ? 1 : 0;
208 strong_not_saturated_render_blocks_ +=
209 active_render && !SaturatedCapture() ? 1 : 0;
Per Åhgren0e6d2f52017-12-20 22:19:56 +0100210
Per Åhgren8718afb2019-10-15 10:31:35 +0200211 std::array<float, kFftLengthBy2Plus1> avg_render_spectrum_with_reverb;
Per Åhgren1d3008b2019-10-09 12:54:43 +0200212
Per Åhgren8718afb2019-10-15 10:31:35 +0200213 ComputeAvgRenderReverb(render_buffer.GetSpectrumBuffer(),
214 delay_state_.MinDirectPathFilterDelay(), ReverbDecay(),
215 &avg_render_reverb_, avg_render_spectrum_with_reverb);
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200216
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200217 if (config_.echo_audibility.use_stationarity_properties) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200218 // Update the echo audibility evaluator.
Per Åhgren8718afb2019-10-15 10:31:35 +0200219 echo_audibility_.Update(render_buffer, avg_render_reverb_.reverb(),
220 delay_state_.MinDirectPathFilterDelay(),
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200221 delay_state_.ExternalDelayReported());
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200222 }
223
peah86afe9d2017-04-06 15:45:32 -0700224 // Update the ERL and ERLE measures.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200225 if (initial_state_.TransitionTriggered()) {
226 erle_estimator_.Reset(false);
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200227 }
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200228
Per Åhgren785d4c42019-10-17 14:40:54 +0200229 erle_estimator_.Update(render_buffer, adaptive_filter_frequency_responses,
230 avg_render_spectrum_with_reverb, Y2, E2_main,
231 subtractor_output_analyzer_.ConvergedFilters());
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +0200232
Sam Zackrisson6e5433c2019-10-18 16:49:13 +0200233 erl_estimator_.Update(
234 subtractor_output_analyzer_.ConvergedFilters(),
235 render_buffer.Spectrum(delay_state_.MinDirectPathFilterDelay()), Y2);
peah86afe9d2017-04-06 15:45:32 -0700236
Per Åhgren63b494d2017-12-06 11:32:38 +0100237 // Detect and flag echo saturation.
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100238 saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
239 UsableLinearEstimate(), subtractor_output,
Sam Zackrisson0169a3e2019-10-09 08:00:29 +0200240 max_echo_path_gain);
peah86afe9d2017-04-06 15:45:32 -0700241
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200242 // Update the decision on whether to use the initial state parameter set.
243 initial_state_.Update(active_render, SaturatedCapture());
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100244
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200245 // Detect whether the transparent mode should be activated.
Per Åhgren88d662a2019-10-16 15:32:39 +0200246 transparent_state_.Update(delay_state_.MinDirectPathFilterDelay(),
Sam Zackrisson46b01402019-10-08 16:17:48 +0200247 any_filter_consistent, any_filter_converged,
248 all_filters_diverged, active_render,
249 SaturatedCapture());
Per Åhgren5c532d32018-03-22 00:29:25 +0100250
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200251 // Analyze the quality of the filter.
Sam Zackrisson46b01402019-10-08 16:17:48 +0200252 filter_quality_state_.Update(active_render, TransparentMode(),
253 SaturatedCapture(), external_delay,
254 any_filter_converged);
Per Åhgrena98c8072018-01-15 19:17:16 +0100255
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200256 // Update the reverb estimate.
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200257 const bool stationary_block =
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +0200258 config_.echo_audibility.use_stationarity_properties &&
Per Åhgrenf4801a12018-09-27 13:14:02 +0200259 echo_audibility_.IsBlockStationary();
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200260
Per Åhgren8be669f2019-10-11 23:02:26 +0200261 reverb_model_estimator_.Update(
262 filter_analyzer_.GetAdjustedFilters(),
263 adaptive_filter_frequency_responses,
264 erle_estimator_.GetInstLinearQualityEstimates(),
265 delay_state_.DirectPathFilterDelays(),
266 filter_quality_state_.UsableLinearFilterOutputs(), stationary_block);
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200267
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200268 erle_estimator_.Dump(data_dumper_);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200269 reverb_model_estimator_.Dump(data_dumper_.get());
Per Åhgren5c532d32018-03-22 00:29:25 +0100270 data_dumper_->DumpRaw("aec3_erl", Erl());
Per Åhgren5c532d32018-03-22 00:29:25 +0100271 data_dumper_->DumpRaw("aec3_erl_time_domain", ErlTimeDomain());
Per Åhgrenb4161d32019-10-08 12:35:47 +0200272 data_dumper_->DumpRaw("aec3_erle", Erle()[0]);
Per Åhgren5c532d32018-03-22 00:29:25 +0100273 data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200274 data_dumper_->DumpRaw("aec3_transparent_mode", TransparentMode());
Sam Zackrisson46b01402019-10-08 16:17:48 +0200275 data_dumper_->DumpRaw("aec3_filter_delay",
Per Åhgren8be669f2019-10-11 23:02:26 +0200276 filter_analyzer_.MinFilterDelayBlocks());
Per Åhgren5c532d32018-03-22 00:29:25 +0100277
Sam Zackrisson46b01402019-10-08 16:17:48 +0200278 data_dumper_->DumpRaw("aec3_any_filter_consistent", any_filter_consistent);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200279 data_dumper_->DumpRaw("aec3_initial_state",
280 initial_state_.InitialStateActive());
Per Åhgren5c532d32018-03-22 00:29:25 +0100281 data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200282 data_dumper_->DumpRaw("aec3_echo_saturation", SaturatedEcho());
Sam Zackrisson46b01402019-10-08 16:17:48 +0200283 data_dumper_->DumpRaw("aec3_any_filter_converged", any_filter_converged);
284 data_dumper_->DumpRaw("aec3_all_filters_diverged", all_filters_diverged);
Per Åhgren5c532d32018-03-22 00:29:25 +0100285
286 data_dumper_->DumpRaw("aec3_external_delay_avaliable",
287 external_delay ? 1 : 0);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200288 data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
289 GetReverbFrequencyResponse());
peah29103572017-07-11 02:54:02 -0700290}
291
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200292AecState::InitialState::InitialState(const EchoCanceller3Config& config)
293 : conservative_initial_phase_(config.filter.conservative_initial_phase),
294 initial_state_seconds_(config.filter.initial_state_seconds) {
295 Reset();
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100296}
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200297void AecState::InitialState::InitialState::Reset() {
298 initial_state_ = true;
299 strong_not_saturated_render_blocks_ = 0;
300}
301void AecState::InitialState::InitialState::Update(bool active_render,
302 bool saturated_capture) {
303 strong_not_saturated_render_blocks_ +=
304 active_render && !saturated_capture ? 1 : 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100305
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200306 // Flag whether the initial state is still active.
307 bool prev_initial_state = initial_state_;
308 if (conservative_initial_phase_) {
309 initial_state_ =
310 strong_not_saturated_render_blocks_ < 5 * kNumBlocksPerSecond;
Per Åhgren31122d62018-04-10 16:33:55 +0200311 } else {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200312 initial_state_ = strong_not_saturated_render_blocks_ <
313 initial_state_seconds_ * kNumBlocksPerSecond;
Per Åhgren31122d62018-04-10 16:33:55 +0200314 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100315
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200316 // Flag whether the transition from the initial state has started.
317 transition_triggered_ = !initial_state_ && prev_initial_state;
318}
319
Per Åhgren8be669f2019-10-11 23:02:26 +0200320AecState::FilterDelay::FilterDelay(const EchoCanceller3Config& config,
321 size_t num_capture_channels)
322 : delay_headroom_samples_(config.delay.delay_headroom_samples),
323 filter_delays_blocks_(num_capture_channels, 0) {}
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200324
325void AecState::FilterDelay::Update(
Per Åhgren8be669f2019-10-11 23:02:26 +0200326 rtc::ArrayView<const int> analyzer_filter_delay_estimates_blocks,
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200327 const absl::optional<DelayEstimate>& external_delay,
328 size_t blocks_with_proper_filter_adaptation) {
329 // Update the delay based on the external delay.
330 if (external_delay &&
331 (!external_delay_ || external_delay_->delay != external_delay->delay)) {
332 external_delay_ = external_delay;
333 external_delay_reported_ = true;
334 }
335
336 // Override the estimated delay if it is not certain that the filter has had
337 // time to converge.
338 const bool delay_estimator_may_not_have_converged =
339 blocks_with_proper_filter_adaptation < 2 * kNumBlocksPerSecond;
340 if (delay_estimator_may_not_have_converged && external_delay_) {
Per Åhgren8be669f2019-10-11 23:02:26 +0200341 int delay_guess = delay_headroom_samples_ / kBlockSize;
342 std::fill(filter_delays_blocks_.begin(), filter_delays_blocks_.end(),
343 delay_guess);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200344 } else {
Per Åhgren8be669f2019-10-11 23:02:26 +0200345 RTC_DCHECK_EQ(filter_delays_blocks_.size(),
346 analyzer_filter_delay_estimates_blocks.size());
347 std::copy(analyzer_filter_delay_estimates_blocks.begin(),
348 analyzer_filter_delay_estimates_blocks.end(),
349 filter_delays_blocks_.begin());
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200350 }
Per Åhgren8718afb2019-10-15 10:31:35 +0200351
352 min_filter_delay_ = *std::min_element(filter_delays_blocks_.begin(),
353 filter_delays_blocks_.end());
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200354}
355
356AecState::TransparentMode::TransparentMode(const EchoCanceller3Config& config)
357 : bounded_erl_(config.ep_strength.bounded_erl),
358 linear_and_stable_echo_path_(
359 config.echo_removal_control.linear_and_stable_echo_path),
360 active_blocks_since_sane_filter_(kBlocksSinceConsistentEstimateInit),
361 non_converged_sequence_size_(kBlocksSinceConvergencedFilterInit) {}
362
363void AecState::TransparentMode::Reset() {
364 non_converged_sequence_size_ = kBlocksSinceConvergencedFilterInit;
365 diverged_sequence_size_ = 0;
366 strong_not_saturated_render_blocks_ = 0;
367 if (linear_and_stable_echo_path_) {
368 recent_convergence_during_activity_ = false;
369 }
370}
371
372void AecState::TransparentMode::Update(int filter_delay_blocks,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200373 bool any_filter_consistent,
374 bool any_filter_converged,
375 bool all_filters_diverged,
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200376 bool active_render,
377 bool saturated_capture) {
378 ++capture_block_counter_;
379 strong_not_saturated_render_blocks_ +=
380 active_render && !saturated_capture ? 1 : 0;
381
Sam Zackrisson46b01402019-10-08 16:17:48 +0200382 if (any_filter_consistent && filter_delay_blocks < 5) {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200383 sane_filter_observed_ = true;
384 active_blocks_since_sane_filter_ = 0;
385 } else if (active_render) {
386 ++active_blocks_since_sane_filter_;
387 }
388
389 bool sane_filter_recently_seen;
390 if (!sane_filter_observed_) {
391 sane_filter_recently_seen =
392 capture_block_counter_ <= 5 * kNumBlocksPerSecond;
393 } else {
394 sane_filter_recently_seen =
395 active_blocks_since_sane_filter_ <= 30 * kNumBlocksPerSecond;
396 }
397
Sam Zackrisson46b01402019-10-08 16:17:48 +0200398 if (any_filter_converged) {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200399 recent_convergence_during_activity_ = true;
400 active_non_converged_sequence_size_ = 0;
401 non_converged_sequence_size_ = 0;
402 ++num_converged_blocks_;
403 } else {
404 if (++non_converged_sequence_size_ > 20 * kNumBlocksPerSecond) {
405 num_converged_blocks_ = 0;
406 }
407
408 if (active_render &&
409 ++active_non_converged_sequence_size_ > 60 * kNumBlocksPerSecond) {
410 recent_convergence_during_activity_ = false;
411 }
412 }
413
Sam Zackrisson46b01402019-10-08 16:17:48 +0200414 if (!all_filters_diverged) {
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200415 diverged_sequence_size_ = 0;
416 } else if (++diverged_sequence_size_ >= 60) {
417 // TODO(peah): Change these lines to ensure proper triggering of usable
418 // filter.
419 non_converged_sequence_size_ = kBlocksSinceConvergencedFilterInit;
420 }
421
422 if (active_non_converged_sequence_size_ > 60 * kNumBlocksPerSecond) {
423 finite_erl_recently_detected_ = false;
424 }
425 if (num_converged_blocks_ > 50) {
426 finite_erl_recently_detected_ = true;
427 }
428
429 if (bounded_erl_) {
430 transparency_activated_ = false;
431 } else if (finite_erl_recently_detected_) {
432 transparency_activated_ = false;
433 } else if (sane_filter_recently_seen && recent_convergence_during_activity_) {
434 transparency_activated_ = false;
435 } else {
436 const bool filter_should_have_converged =
437 strong_not_saturated_render_blocks_ > 6 * kNumBlocksPerSecond;
438 transparency_activated_ = filter_should_have_converged;
439 }
440}
441
442AecState::FilteringQualityAnalyzer::FilteringQualityAnalyzer(
Per Åhgren8be669f2019-10-11 23:02:26 +0200443 const EchoCanceller3Config& config,
444 size_t num_capture_channels)
445 : use_linear_filter_(config.filter.use_linear_filter),
446 usable_linear_filter_estimates_(num_capture_channels, false) {}
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200447
448void AecState::FilteringQualityAnalyzer::Reset() {
Per Åhgren8be669f2019-10-11 23:02:26 +0200449 std::fill(usable_linear_filter_estimates_.begin(),
450 usable_linear_filter_estimates_.end(), false);
451 overall_usable_linear_estimates_ = false;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200452 filter_update_blocks_since_reset_ = 0;
453}
454
455void AecState::FilteringQualityAnalyzer::Update(
456 bool active_render,
457 bool transparent_mode,
458 bool saturated_capture,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200459 const absl::optional<DelayEstimate>& external_delay,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200460 bool any_filter_converged) {
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200461 // Update blocks counter.
462 const bool filter_update = active_render && !saturated_capture;
463 filter_update_blocks_since_reset_ += filter_update ? 1 : 0;
464 filter_update_blocks_since_start_ += filter_update ? 1 : 0;
465
466 // Store convergence flag when observed.
Sam Zackrisson46b01402019-10-08 16:17:48 +0200467 convergence_seen_ = convergence_seen_ || any_filter_converged;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200468
469 // Verify requirements for achieving a decent filter. The requirements for
470 // filter adaptation at call startup are more restrictive than after an
471 // in-call reset.
472 const bool sufficient_data_to_converge_at_startup =
473 filter_update_blocks_since_start_ > kNumBlocksPerSecond * 0.4f;
474 const bool sufficient_data_to_converge_at_reset =
475 sufficient_data_to_converge_at_startup &&
476 filter_update_blocks_since_reset_ > kNumBlocksPerSecond * 0.2f;
477
Per Åhgren8be669f2019-10-11 23:02:26 +0200478 // The linear filter can only be used if it has had time to converge.
479 overall_usable_linear_estimates_ = sufficient_data_to_converge_at_startup &&
480 sufficient_data_to_converge_at_reset;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200481
482 // The linear filter can only be used if an external delay or convergence have
483 // been identified
Per Åhgren8be669f2019-10-11 23:02:26 +0200484 overall_usable_linear_estimates_ =
485 overall_usable_linear_estimates_ && (external_delay || convergence_seen_);
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200486
487 // If transparent mode is on, deactivate usign the linear filter.
Per Åhgren8be669f2019-10-11 23:02:26 +0200488 overall_usable_linear_estimates_ =
489 overall_usable_linear_estimates_ && !transparent_mode;
490
491 if (use_linear_filter_) {
492 std::fill(usable_linear_filter_estimates_.begin(),
493 usable_linear_filter_estimates_.end(),
494 overall_usable_linear_estimates_);
495 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200496}
497
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200498void AecState::SaturationDetector::Update(
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200499 rtc::ArrayView<const std::vector<float>> x,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200500 bool saturated_capture,
501 bool usable_linear_estimate,
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200502 rtc::ArrayView<const SubtractorOutput> subtractor_output,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200503 float echo_path_gain) {
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200504 saturated_echo_ = false;
505 if (!saturated_capture) {
506 return;
507 }
508
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200509 if (usable_linear_estimate) {
510 constexpr float kSaturationThreshold = 20000.f;
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200511 for (size_t ch = 0; ch < subtractor_output.size(); ++ch) {
512 saturated_echo_ =
513 saturated_echo_ ||
514 (subtractor_output[ch].s_main_max_abs > kSaturationThreshold ||
515 subtractor_output[ch].s_shadow_max_abs > kSaturationThreshold);
516 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200517 } else {
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200518 float max_sample = 0.f;
519 for (auto& channel : x) {
520 for (float sample : channel) {
521 max_sample = std::max(max_sample, fabsf(sample));
522 }
523 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200524
525 const float kMargin = 10.f;
526 float peak_echo_amplitude = max_sample * echo_path_gain * kMargin;
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200527 saturated_echo_ = saturated_echo_ || peak_echo_amplitude > 32000;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200528 }
529}
530
peah522d71b2017-02-23 05:16:26 -0800531} // namespace webrtc