blob: 62232ac1046e432bf2bce8ce5c411e0041203df7 [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>
Raphael Kubo da Costa07438142017-10-16 17:00:02 +020014
peah522d71b2017-02-23 05:16:26 -080015#include <numeric>
16#include <vector>
17
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +020018#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "api/array_view.h"
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +020020#include "modules/audio_processing/aec3/aec3_common.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_processing/logging/apm_data_dumper.h"
22#include "rtc_base/atomicops.h"
23#include "rtc_base/checks.h"
Per Åhgrend18e87e2018-05-09 12:07:26 +020024#include "system_wrappers/include/field_trial.h"
peah522d71b2017-02-23 05:16:26 -080025
26namespace webrtc {
27namespace {
28
Per Åhgrend18e87e2018-05-09 12:07:26 +020029bool EnableTransparentMode() {
30 return !field_trial::IsEnabled("WebRTC-Aec3TransparentModeKillSwitch");
31}
32
Per Åhgren90e3fbd2018-05-16 15:25:04 +020033bool EnableStationaryRenderImprovements() {
34 return !field_trial::IsEnabled(
35 "WebRTC-Aec3StationaryRenderImprovementsKillSwitch");
36}
37
Per Åhgren05d8ee12018-06-07 15:59:59 +020038bool EnableEnforcingDelayAfterRealignment() {
39 return !field_trial::IsEnabled(
40 "WebRTC-Aec3EnforceDelayAfterRealignmentKillSwitch");
41}
42
Per Åhgrenf954ba52018-07-27 14:53:58 +020043bool EnableEarlyFilterUsage() {
44 return !field_trial::IsEnabled("WebRTC-Aec3EarlyLinearFilterUsageKillSwitch");
45}
46
47bool EnableShortInitialState() {
48 return !field_trial::IsEnabled("WebRTC-Aec3ShortInitialStateKillSwitch");
49}
50
Per Åhgren22754392018-08-10 18:37:38 +020051bool EnableUncertaintyUntilSufficientAdapted() {
52 return !field_trial::IsEnabled(
53 "WebRTC-Aec3ErleUncertaintyUntilSufficientlyAdaptedKillSwitch");
54}
55
Per Åhgren6204adf2018-08-19 11:12:00 +020056bool LowUncertaintyBeforeConvergence() {
57 return !field_trial::IsEnabled(
58 "WebRTC-Aec3LowUncertaintyBeforeConvergenceKillSwitch");
59}
60
61bool MediumUncertaintyBeforeConvergence() {
62 return !field_trial::IsEnabled(
63 "WebRTC-Aec3MediumUncertaintyBeforeConvergenceKillSwitch");
64}
65
66bool EarlyEntryToConvergedMode() {
67 return !field_trial::IsEnabled(
68 "WebRTC-Aec3EarlyEntryToConvergedModeKillSwitch");
69}
70
Per Åhgren6204adf2018-08-19 11:12:00 +020071bool UseEarlyLimiterDeactivation() {
72 return !field_trial::IsEnabled(
73 "WebRTC-Aec3EarlyLimiterDeactivationKillSwitch");
74}
75
Jesús de Vicente Peña7015bb42018-08-29 11:15:30 +020076bool ResetErleAfterEchoPathChanges() {
77 return !field_trial::IsEnabled(
78 "WebRTC-Aec3ResetErleAfterEchoPathChangesKillSwitch");
79}
80
Per Åhgren6204adf2018-08-19 11:12:00 +020081float UncertaintyBeforeConvergence() {
82 if (LowUncertaintyBeforeConvergence()) {
83 return 1.f;
84 } else if (MediumUncertaintyBeforeConvergence()) {
85 return 4.f;
86 } else {
87 return 10.f;
88 }
89}
90
Per Åhgrenb6b00dc2018-02-20 22:18:27 +010091float ComputeGainRampupIncrease(const EchoCanceller3Config& config) {
92 const auto& c = config.echo_removal_control.gain_rampup;
93 return powf(1.f / c.first_non_zero_gain, 1.f / c.non_zero_gain_blocks);
94}
95
Per Åhgren5c532d32018-03-22 00:29:25 +010096constexpr size_t kBlocksSinceConvergencedFilterInit = 10000;
97constexpr size_t kBlocksSinceConsistentEstimateInit = 10000;
98
peah522d71b2017-02-23 05:16:26 -080099} // namespace
100
101int AecState::instance_count_ = 0;
102
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200103AecState::AecState(const EchoCanceller3Config& config)
peah522d71b2017-02-23 05:16:26 -0800104 : data_dumper_(
105 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
peah8cee56f2017-08-24 22:36:53 -0700106 config_(config),
Per Åhgren90e3fbd2018-05-16 15:25:04 +0200107 allow_transparent_mode_(EnableTransparentMode()),
108 use_stationary_properties_(
109 EnableStationaryRenderImprovements() &&
110 config_.echo_audibility.use_stationary_properties),
Per Åhgren05d8ee12018-06-07 15:59:59 +0200111 enforce_delay_after_realignment_(EnableEnforcingDelayAfterRealignment()),
Jesús de Vicente Peña8459b172018-08-21 16:09:49 +0200112 early_filter_usage_activated_(EnableEarlyFilterUsage() &&
113 !config.filter.conservative_initial_phase),
114 use_short_initial_state_(EnableShortInitialState() &&
115 !config.filter.conservative_initial_phase),
116 convergence_trigger_linear_mode_(
Jesús de Vicente Peña8459b172018-08-21 16:09:49 +0200117 !config.filter.conservative_initial_phase),
118 no_alignment_required_for_linear_mode_(
Jesús de Vicente Peña8459b172018-08-21 16:09:49 +0200119 !config.filter.conservative_initial_phase),
Per Åhgren22754392018-08-10 18:37:38 +0200120 use_uncertainty_until_sufficiently_adapted_(
121 EnableUncertaintyUntilSufficientAdapted()),
Per Åhgren6204adf2018-08-19 11:12:00 +0200122 uncertainty_before_convergence_(UncertaintyBeforeConvergence()),
123 early_entry_to_converged_mode_(EarlyEntryToConvergedMode()),
Per Åhgren6204adf2018-08-19 11:12:00 +0200124 early_limiter_deactivation_(UseEarlyLimiterDeactivation()),
Jesús de Vicente Peña7015bb42018-08-29 11:15:30 +0200125 reset_erle_after_echo_path_changes_(ResetErleAfterEchoPathChanges()),
Per Åhgren90e3fbd2018-05-16 15:25:04 +0200126 erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
Per Åhgren08ea5892018-01-15 08:07:41 +0100127 max_render_(config_.filter.main.length_blocks, 0.f),
Per Åhgren12eb8582018-03-06 10:40:51 +0100128 gain_rampup_increase_(ComputeGainRampupIncrease(config_)),
Per Åhgren5c532d32018-03-22 00:29:25 +0100129 suppression_gain_limiter_(config_),
130 filter_analyzer_(config_),
131 blocks_since_converged_filter_(kBlocksSinceConvergencedFilterInit),
132 active_blocks_since_consistent_filter_estimate_(
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200133 kBlocksSinceConsistentEstimateInit),
134 reverb_model_estimator_(config) {}
peah522d71b2017-02-23 05:16:26 -0800135
136AecState::~AecState() = default;
137
peah86afe9d2017-04-06 15:45:32 -0700138void AecState::HandleEchoPathChange(
139 const EchoPathVariability& echo_path_variability) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100140 const auto full_reset = [&]() {
Per Åhgren5c532d32018-03-22 00:29:25 +0100141 filter_analyzer_.Reset();
Per Åhgren63b494d2017-12-06 11:32:38 +0100142 blocks_since_last_saturation_ = 0;
peah86afe9d2017-04-06 15:45:32 -0700143 usable_linear_estimate_ = false;
peah86afe9d2017-04-06 15:45:32 -0700144 capture_signal_saturation_ = false;
145 echo_saturation_ = false;
Per Åhgren09a718a2017-12-11 22:28:45 +0100146 std::fill(max_render_.begin(), max_render_.end(), 0.f);
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100147 blocks_with_proper_filter_adaptation_ = 0;
Per Åhgren5c532d32018-03-22 00:29:25 +0100148 blocks_since_reset_ = 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100149 filter_has_had_time_to_converge_ = false;
Per Åhgren8ba58612017-12-01 23:01:44 +0100150 render_received_ = false;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100151 blocks_with_active_render_ = 0;
Per Åhgrena98c8072018-01-15 19:17:16 +0100152 initial_state_ = true;
Per Åhgren12eb8582018-03-06 10:40:51 +0100153 suppression_gain_limiter_.Reset();
Per Åhgren5c532d32018-03-22 00:29:25 +0100154 blocks_since_converged_filter_ = kBlocksSinceConvergencedFilterInit;
155 diverged_blocks_ = 0;
Jesús de Vicente Peña7015bb42018-08-29 11:15:30 +0200156 if (reset_erle_after_echo_path_changes_) {
157 erle_estimator_.Reset();
158 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100159 };
peah6d822ad2017-04-10 13:52:14 -0700160
Per Åhgren8ba58612017-12-01 23:01:44 +0100161 // TODO(peah): Refine the reset scheme according to the type of gain and
162 // delay adjustment.
Per Åhgren8ba58612017-12-01 23:01:44 +0100163
164 if (echo_path_variability.delay_change !=
Per Åhgren88cf0502018-07-16 17:08:41 +0200165 EchoPathVariability::DelayAdjustment::kNone) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100166 full_reset();
peah86afe9d2017-04-06 15:45:32 -0700167 }
Per Åhgrenb20b9372018-07-13 00:22:54 +0200168
169 subtractor_output_analyzer_.HandleEchoPathChange();
peah86afe9d2017-04-06 15:45:32 -0700170}
171
Per Åhgren09a718a2017-12-11 22:28:45 +0100172void AecState::Update(
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200173 const absl::optional<DelayEstimate>& external_delay,
Per Åhgren09a718a2017-12-11 22:28:45 +0100174 const std::vector<std::array<float, kFftLengthBy2Plus1>>&
175 adaptive_filter_frequency_response,
176 const std::vector<float>& adaptive_filter_impulse_response,
Per Åhgren09a718a2017-12-11 22:28:45 +0100177 const RenderBuffer& render_buffer,
178 const std::array<float, kFftLengthBy2Plus1>& E2_main,
179 const std::array<float, kFftLengthBy2Plus1>& Y2,
Per Åhgrenb20b9372018-07-13 00:22:54 +0200180 const SubtractorOutput& subtractor_output,
181 rtc::ArrayView<const float> y) {
182 // Analyze the filter output.
Per Åhgrene4db6a12018-07-26 15:32:24 +0200183 subtractor_output_analyzer_.Update(subtractor_output);
Per Åhgrenb20b9372018-07-13 00:22:54 +0200184
185 const bool converged_filter = subtractor_output_analyzer_.ConvergedFilter();
186 const bool diverged_filter = subtractor_output_analyzer_.DivergedFilter();
187
Per Åhgren5c532d32018-03-22 00:29:25 +0100188 // Analyze the filter and compute the delays.
Jesús de Vicente Peñae58bd8a2018-06-26 17:19:15 +0200189 filter_analyzer_.Update(adaptive_filter_impulse_response,
190 adaptive_filter_frequency_response, render_buffer);
Per Åhgren5c532d32018-03-22 00:29:25 +0100191 filter_delay_blocks_ = filter_analyzer_.DelayBlocks();
Per Åhgren05d8ee12018-06-07 15:59:59 +0200192 if (enforce_delay_after_realignment_) {
193 if (external_delay &&
194 (!external_delay_ || external_delay_->delay != external_delay->delay)) {
195 frames_since_external_delay_change_ = 0;
196 external_delay_ = external_delay;
197 }
198 if (blocks_with_proper_filter_adaptation_ < 2 * kNumBlocksPerSecond &&
199 external_delay_) {
200 filter_delay_blocks_ = config_.delay.delay_headroom_blocks;
201 }
202 }
peah86afe9d2017-04-06 15:45:32 -0700203
Per Åhgren5c532d32018-03-22 00:29:25 +0100204 if (filter_analyzer_.Consistent()) {
205 internal_delay_ = filter_analyzer_.DelayBlocks();
206 } else {
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200207 internal_delay_ = absl::nullopt;
Per Åhgren5c532d32018-03-22 00:29:25 +0100208 }
209
210 external_delay_seen_ = external_delay_seen_ || external_delay;
211
212 const std::vector<float>& x = render_buffer.Block(-filter_delay_blocks_)[0];
Per Åhgren0e6d2f52017-12-20 22:19:56 +0100213
peah86afe9d2017-04-06 15:45:32 -0700214 // Update counters.
Per Åhgren1b4059e2017-10-15 20:19:21 +0200215 ++capture_block_counter_;
Per Åhgren5c532d32018-03-22 00:29:25 +0100216 ++blocks_since_reset_;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100217 const bool active_render_block = DetectActiveRender(x);
218 blocks_with_active_render_ += active_render_block ? 1 : 0;
219 blocks_with_proper_filter_adaptation_ +=
220 active_render_block && !SaturatedCapture() ? 1 : 0;
peah86afe9d2017-04-06 15:45:32 -0700221
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100222 // Update the limit on the echo suppression after an echo path change to avoid
223 // an initial echo burst.
Per Åhgren5c532d32018-03-22 00:29:25 +0100224 suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
225 transparent_mode_);
Per Åhgren6204adf2018-08-19 11:12:00 +0200226 if (converged_filter && early_limiter_deactivation_) {
227 suppression_gain_limiter_.Deactivate();
228 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100229
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +0200230 if (UseStationaryProperties()) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200231 // Update the echo audibility evaluator.
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200232 echo_audibility_.Update(
233 render_buffer, FilterDelayBlocks(), external_delay_seen_,
234 config_.ep_strength.reverb_based_on_render ? ReverbDecay() : 0.f);
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200235 }
236
peah86afe9d2017-04-06 15:45:32 -0700237 // Update the ERL and ERLE measures.
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200238 if (reset_erle_after_echo_path_changes_ && transition_triggered_) {
239 erle_estimator_.Reset();
240 }
Jesús de Vicente Peña666beca2018-05-21 15:23:48 +0200241 if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) {
Per Åhgren5c532d32018-03-22 00:29:25 +0100242 const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_);
Jesús de Vicente Peñaa6878122018-08-28 14:27:45 +0200243 erle_estimator_.Update(X2, Y2, E2_main, converged_filter,
244 config_.erle.onset_detection);
Jesús de Vicente Peña666beca2018-05-21 15:23:48 +0200245 if (converged_filter) {
246 erl_estimator_.Update(X2, Y2);
247 }
peah522d71b2017-02-23 05:16:26 -0800248 }
peah86afe9d2017-04-06 15:45:32 -0700249
Per Åhgren63b494d2017-12-06 11:32:38 +0100250 // Detect and flag echo saturation.
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200251 if (config_.ep_strength.echo_can_saturate) {
Per Åhgren31122d62018-04-10 16:33:55 +0200252 echo_saturation_ = DetectEchoSaturation(x, EchoPathGain());
Per Åhgren1b4059e2017-10-15 20:19:21 +0200253 }
peah86afe9d2017-04-06 15:45:32 -0700254
Per Åhgrenf954ba52018-07-27 14:53:58 +0200255 if (early_filter_usage_activated_) {
Per Åhgren22754392018-08-10 18:37:38 +0200256 filter_has_had_time_to_converge_ =
Per Åhgrenf954ba52018-07-27 14:53:58 +0200257 blocks_with_proper_filter_adaptation_ >= 0.8f * kNumBlocksPerSecond;
258 } else {
Per Åhgren22754392018-08-10 18:37:38 +0200259 filter_has_had_time_to_converge_ =
Per Åhgrenf954ba52018-07-27 14:53:58 +0200260 blocks_with_proper_filter_adaptation_ >= 1.5f * kNumBlocksPerSecond;
261 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100262
Per Åhgren6204adf2018-08-19 11:12:00 +0200263 if (converged_filter && early_entry_to_converged_mode_) {
264 filter_has_had_time_to_converge_ = true;
265 }
266
Per Åhgren5c532d32018-03-22 00:29:25 +0100267 if (!filter_should_have_converged_) {
268 filter_should_have_converged_ =
269 blocks_with_proper_filter_adaptation_ > 6 * kNumBlocksPerSecond;
270 }
271
272 // Flag whether the initial state is still active.
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200273 bool prev_initial_state = initial_state_;
Per Åhgrenf954ba52018-07-27 14:53:58 +0200274 if (use_short_initial_state_) {
Per Åhgrenc3da6712018-08-17 00:09:15 +0200275 initial_state_ = blocks_with_proper_filter_adaptation_ <
276 config_.filter.initial_state_seconds * kNumBlocksPerSecond;
Per Åhgrenf954ba52018-07-27 14:53:58 +0200277 } else {
278 initial_state_ =
279 blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond;
280 }
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200281 transition_triggered_ = !initial_state_ && prev_initial_state;
Per Åhgrena98c8072018-01-15 19:17:16 +0100282
Per Åhgren5c532d32018-03-22 00:29:25 +0100283 // Update counters for the filter divergence and convergence.
284 diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0;
285 if (diverged_blocks_ >= 60) {
286 blocks_since_converged_filter_ = kBlocksSinceConvergencedFilterInit;
287 } else {
288 blocks_since_converged_filter_ =
289 converged_filter ? 0 : blocks_since_converged_filter_ + 1;
290 }
Per Åhgren8131eb02018-03-28 18:13:41 +0200291 if (converged_filter) {
292 active_blocks_since_converged_filter_ = 0;
293 } else if (active_render_block) {
294 ++active_blocks_since_converged_filter_;
295 }
296
Per Åhgren5c532d32018-03-22 00:29:25 +0100297 bool recently_converged_filter =
298 blocks_since_converged_filter_ < 60 * kNumBlocksPerSecond;
299
Per Åhgrenf3e2bf12018-03-22 10:15:59 +0100300 if (blocks_since_converged_filter_ > 20 * kNumBlocksPerSecond) {
301 converged_filter_count_ = 0;
302 } else if (converged_filter) {
303 ++converged_filter_count_;
304 }
305 if (converged_filter_count_ > 50) {
306 finite_erl_ = true;
307 }
308
Per Åhgren5c532d32018-03-22 00:29:25 +0100309 if (filter_analyzer_.Consistent() && filter_delay_blocks_ < 5) {
310 consistent_filter_seen_ = true;
311 active_blocks_since_consistent_filter_estimate_ = 0;
312 } else if (active_render_block) {
313 ++active_blocks_since_consistent_filter_estimate_;
314 }
315
316 bool consistent_filter_estimate_not_seen;
317 if (!consistent_filter_seen_) {
318 consistent_filter_estimate_not_seen =
319 capture_block_counter_ > 5 * kNumBlocksPerSecond;
320 } else {
321 consistent_filter_estimate_not_seen =
322 active_blocks_since_consistent_filter_estimate_ >
323 30 * kNumBlocksPerSecond;
324 }
325
326 converged_filter_seen_ = converged_filter_seen_ || converged_filter;
Per Åhgren63b494d2017-12-06 11:32:38 +0100327
Per Åhgren8131eb02018-03-28 18:13:41 +0200328 // If no filter convergence is seen for a long time, reset the estimated
329 // properties of the echo path.
330 if (active_blocks_since_converged_filter_ > 60 * kNumBlocksPerSecond) {
331 converged_filter_seen_ = false;
332 finite_erl_ = false;
333 }
334
Per Åhgren63b494d2017-12-06 11:32:38 +0100335 // After an amount of active render samples for which an echo should have been
336 // detected in the capture signal if the ERL was not infinite, flag that a
337 // transparent mode should be entered.
Per Åhgrenf3e2bf12018-03-22 10:15:59 +0100338 transparent_mode_ = !config_.ep_strength.bounded_erl && !finite_erl_;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100339 transparent_mode_ =
Per Åhgren5c532d32018-03-22 00:29:25 +0100340 transparent_mode_ &&
341 (consistent_filter_estimate_not_seen || !converged_filter_seen_);
Per Åhgrend18e87e2018-05-09 12:07:26 +0200342 transparent_mode_ = transparent_mode_ && filter_should_have_converged_;
343 transparent_mode_ = transparent_mode_ && allow_transparent_mode_;
Per Åhgren5c532d32018-03-22 00:29:25 +0100344
345 usable_linear_estimate_ = !echo_saturation_;
Per Åhgrene3ca9912018-05-28 22:57:17 +0200346
Per Åhgren22754392018-08-10 18:37:38 +0200347 if (convergence_trigger_linear_mode_) {
348 usable_linear_estimate_ =
349 usable_linear_estimate_ &&
350 ((filter_has_had_time_to_converge_ && external_delay) ||
351 converged_filter_seen_);
352 } else {
353 usable_linear_estimate_ =
354 usable_linear_estimate_ && filter_has_had_time_to_converge_;
355 }
356
357 if (!no_alignment_required_for_linear_mode_) {
358 usable_linear_estimate_ = usable_linear_estimate_ && external_delay;
359 }
360
Per Åhgrene3ca9912018-05-28 22:57:17 +0200361 if (!config_.echo_removal_control.linear_and_stable_echo_path) {
362 usable_linear_estimate_ =
363 usable_linear_estimate_ && recently_converged_filter;
Per Åhgrene3ca9912018-05-28 22:57:17 +0200364 }
Gustaf Ullberg9ed97922018-08-27 14:38:28 +0200365 usable_linear_estimate_ = usable_linear_estimate_ && !TransparentMode();
Per Åhgren5c532d32018-03-22 00:29:25 +0100366
367 use_linear_filter_output_ = usable_linear_estimate_ && !TransparentMode();
Per Åhgren6204adf2018-08-19 11:12:00 +0200368
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200369 const bool stationary_block =
370 use_stationary_properties_ && echo_audibility_.IsBlockStationary();
371
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200372 reverb_model_estimator_.Update(
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200373 filter_analyzer_.GetAdjustedFilter(), adaptive_filter_frequency_response,
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200374 erle_estimator_.GetInstLinearQualityEstimate(), filter_delay_blocks_,
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200375 usable_linear_estimate_, stationary_block);
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200376
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200377 erle_estimator_.Dump(data_dumper_);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200378 reverb_model_estimator_.Dump(data_dumper_.get());
Per Åhgren5c532d32018-03-22 00:29:25 +0100379 data_dumper_->DumpRaw("aec3_erl", Erl());
Per Åhgren5c532d32018-03-22 00:29:25 +0100380 data_dumper_->DumpRaw("aec3_erl_time_domain", ErlTimeDomain());
381 data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
382 data_dumper_->DumpRaw("aec3_transparent_mode", transparent_mode_);
383 data_dumper_->DumpRaw("aec3_state_internal_delay",
384 internal_delay_ ? *internal_delay_ : -1);
385 data_dumper_->DumpRaw("aec3_filter_delay", filter_analyzer_.DelayBlocks());
386
387 data_dumper_->DumpRaw("aec3_consistent_filter",
388 filter_analyzer_.Consistent());
389 data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200390 data_dumper_->DumpRaw("aec3_initial_state", initial_state_);
Per Åhgren5c532d32018-03-22 00:29:25 +0100391 data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
392 data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_);
393 data_dumper_->DumpRaw("aec3_converged_filter", converged_filter);
394 data_dumper_->DumpRaw("aec3_diverged_filter", diverged_filter);
395
396 data_dumper_->DumpRaw("aec3_external_delay_avaliable",
397 external_delay ? 1 : 0);
398 data_dumper_->DumpRaw("aec3_consistent_filter_estimate_not_seen",
399 consistent_filter_estimate_not_seen);
400 data_dumper_->DumpRaw("aec3_filter_should_have_converged",
401 filter_should_have_converged_);
402 data_dumper_->DumpRaw("aec3_filter_has_had_time_to_converge",
Per Åhgren22754392018-08-10 18:37:38 +0200403 filter_has_had_time_to_converge_);
Per Åhgren5c532d32018-03-22 00:29:25 +0100404 data_dumper_->DumpRaw("aec3_recently_converged_filter",
405 recently_converged_filter);
Jesús de Vicente Peñadd092872018-05-25 16:55:11 +0200406 data_dumper_->DumpRaw("aec3_suppresion_gain_limiter_running",
407 IsSuppressionGainLimitActive());
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200408 data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
409 GetReverbFrequencyResponse());
peah29103572017-07-11 02:54:02 -0700410}
411
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100412bool AecState::DetectActiveRender(rtc::ArrayView<const float> x) const {
413 const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
414 return x_energy > (config_.render_levels.active_render_limit *
415 config_.render_levels.active_render_limit) *
416 kFftLengthBy2;
417}
418
Per Åhgren31122d62018-04-10 16:33:55 +0200419bool AecState::DetectEchoSaturation(rtc::ArrayView<const float> x,
420 float echo_path_gain) {
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100421 RTC_DCHECK_LT(0, x.size());
422 const float max_sample = fabs(*std::max_element(
423 x.begin(), x.end(), [](float a, float b) { return a * a < b * b; }));
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100424
425 // Set flag for potential presence of saturated echo
Per Åhgren31122d62018-04-10 16:33:55 +0200426 const float kMargin = 10.f;
427 float peak_echo_amplitude = max_sample * echo_path_gain * kMargin;
428 if (SaturatedCapture() && peak_echo_amplitude > 32000) {
429 blocks_since_last_saturation_ = 0;
430 } else {
431 ++blocks_since_last_saturation_;
432 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100433
Per Åhgren31122d62018-04-10 16:33:55 +0200434 return blocks_since_last_saturation_ < 5;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100435}
436
peah522d71b2017-02-23 05:16:26 -0800437} // namespace webrtc