blob: ffd81b3c11d12c267ab845cd3a586edcbb3dba48 [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),
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +0200134 echo_audibility_(
135 config.echo_audibility.use_stationarity_properties_at_init),
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200136 reverb_model_estimator_(config) {}
peah522d71b2017-02-23 05:16:26 -0800137
138AecState::~AecState() = default;
139
peah86afe9d2017-04-06 15:45:32 -0700140void AecState::HandleEchoPathChange(
141 const EchoPathVariability& echo_path_variability) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100142 const auto full_reset = [&]() {
Per Åhgren5c532d32018-03-22 00:29:25 +0100143 filter_analyzer_.Reset();
Per Åhgren63b494d2017-12-06 11:32:38 +0100144 blocks_since_last_saturation_ = 0;
peah86afe9d2017-04-06 15:45:32 -0700145 usable_linear_estimate_ = false;
peah86afe9d2017-04-06 15:45:32 -0700146 capture_signal_saturation_ = false;
147 echo_saturation_ = false;
Per Åhgren09a718a2017-12-11 22:28:45 +0100148 std::fill(max_render_.begin(), max_render_.end(), 0.f);
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100149 blocks_with_proper_filter_adaptation_ = 0;
Per Åhgren5c532d32018-03-22 00:29:25 +0100150 blocks_since_reset_ = 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100151 filter_has_had_time_to_converge_ = false;
Per Åhgren8ba58612017-12-01 23:01:44 +0100152 render_received_ = false;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100153 blocks_with_active_render_ = 0;
Per Åhgrena98c8072018-01-15 19:17:16 +0100154 initial_state_ = true;
Per Åhgren12eb8582018-03-06 10:40:51 +0100155 suppression_gain_limiter_.Reset();
Per Åhgren5c532d32018-03-22 00:29:25 +0100156 blocks_since_converged_filter_ = kBlocksSinceConvergencedFilterInit;
157 diverged_blocks_ = 0;
Jesús de Vicente Peña7015bb42018-08-29 11:15:30 +0200158 if (reset_erle_after_echo_path_changes_) {
159 erle_estimator_.Reset();
160 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100161 };
peah6d822ad2017-04-10 13:52:14 -0700162
Per Åhgren8ba58612017-12-01 23:01:44 +0100163 // TODO(peah): Refine the reset scheme according to the type of gain and
164 // delay adjustment.
Per Åhgren8ba58612017-12-01 23:01:44 +0100165
166 if (echo_path_variability.delay_change !=
Per Åhgren88cf0502018-07-16 17:08:41 +0200167 EchoPathVariability::DelayAdjustment::kNone) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100168 full_reset();
peah86afe9d2017-04-06 15:45:32 -0700169 }
Per Åhgrenb20b9372018-07-13 00:22:54 +0200170
171 subtractor_output_analyzer_.HandleEchoPathChange();
peah86afe9d2017-04-06 15:45:32 -0700172}
173
Per Åhgren09a718a2017-12-11 22:28:45 +0100174void AecState::Update(
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200175 const absl::optional<DelayEstimate>& external_delay,
Per Åhgren09a718a2017-12-11 22:28:45 +0100176 const std::vector<std::array<float, kFftLengthBy2Plus1>>&
177 adaptive_filter_frequency_response,
178 const std::vector<float>& adaptive_filter_impulse_response,
Per Åhgren09a718a2017-12-11 22:28:45 +0100179 const RenderBuffer& render_buffer,
180 const std::array<float, kFftLengthBy2Plus1>& E2_main,
181 const std::array<float, kFftLengthBy2Plus1>& Y2,
Per Åhgrenb20b9372018-07-13 00:22:54 +0200182 const SubtractorOutput& subtractor_output,
183 rtc::ArrayView<const float> y) {
184 // Analyze the filter output.
Per Åhgrene4db6a12018-07-26 15:32:24 +0200185 subtractor_output_analyzer_.Update(subtractor_output);
Per Åhgrenb20b9372018-07-13 00:22:54 +0200186
187 const bool converged_filter = subtractor_output_analyzer_.ConvergedFilter();
188 const bool diverged_filter = subtractor_output_analyzer_.DivergedFilter();
189
Per Åhgren5c532d32018-03-22 00:29:25 +0100190 // Analyze the filter and compute the delays.
Jesús de Vicente Peñae58bd8a2018-06-26 17:19:15 +0200191 filter_analyzer_.Update(adaptive_filter_impulse_response,
192 adaptive_filter_frequency_response, render_buffer);
Per Åhgren5c532d32018-03-22 00:29:25 +0100193 filter_delay_blocks_ = filter_analyzer_.DelayBlocks();
Per Åhgren05d8ee12018-06-07 15:59:59 +0200194 if (enforce_delay_after_realignment_) {
195 if (external_delay &&
196 (!external_delay_ || external_delay_->delay != external_delay->delay)) {
197 frames_since_external_delay_change_ = 0;
198 external_delay_ = external_delay;
199 }
200 if (blocks_with_proper_filter_adaptation_ < 2 * kNumBlocksPerSecond &&
201 external_delay_) {
202 filter_delay_blocks_ = config_.delay.delay_headroom_blocks;
203 }
204 }
peah86afe9d2017-04-06 15:45:32 -0700205
Per Åhgren5c532d32018-03-22 00:29:25 +0100206 if (filter_analyzer_.Consistent()) {
207 internal_delay_ = filter_analyzer_.DelayBlocks();
208 } else {
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200209 internal_delay_ = absl::nullopt;
Per Åhgren5c532d32018-03-22 00:29:25 +0100210 }
211
212 external_delay_seen_ = external_delay_seen_ || external_delay;
213
214 const std::vector<float>& x = render_buffer.Block(-filter_delay_blocks_)[0];
Per Åhgren0e6d2f52017-12-20 22:19:56 +0100215
peah86afe9d2017-04-06 15:45:32 -0700216 // Update counters.
Per Åhgren1b4059e2017-10-15 20:19:21 +0200217 ++capture_block_counter_;
Per Åhgren5c532d32018-03-22 00:29:25 +0100218 ++blocks_since_reset_;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100219 const bool active_render_block = DetectActiveRender(x);
220 blocks_with_active_render_ += active_render_block ? 1 : 0;
221 blocks_with_proper_filter_adaptation_ +=
222 active_render_block && !SaturatedCapture() ? 1 : 0;
peah86afe9d2017-04-06 15:45:32 -0700223
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100224 // Update the limit on the echo suppression after an echo path change to avoid
225 // an initial echo burst.
Per Åhgren5c532d32018-03-22 00:29:25 +0100226 suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
227 transparent_mode_);
Per Åhgren6204adf2018-08-19 11:12:00 +0200228 if (converged_filter && early_limiter_deactivation_) {
229 suppression_gain_limiter_.Deactivate();
230 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100231
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +0200232 if (UseStationaryProperties()) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200233 // Update the echo audibility evaluator.
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200234 echo_audibility_.Update(
235 render_buffer, FilterDelayBlocks(), external_delay_seen_,
236 config_.ep_strength.reverb_based_on_render ? ReverbDecay() : 0.f);
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200237 }
238
peah86afe9d2017-04-06 15:45:32 -0700239 // Update the ERL and ERLE measures.
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200240 if (reset_erle_after_echo_path_changes_ && transition_triggered_) {
241 erle_estimator_.Reset();
242 }
Jesús de Vicente Peña666beca2018-05-21 15:23:48 +0200243 if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) {
Per Åhgren5c532d32018-03-22 00:29:25 +0100244 const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_);
Jesús de Vicente Peñaa6878122018-08-28 14:27:45 +0200245 erle_estimator_.Update(X2, Y2, E2_main, converged_filter,
246 config_.erle.onset_detection);
Jesús de Vicente Peña666beca2018-05-21 15:23:48 +0200247 if (converged_filter) {
248 erl_estimator_.Update(X2, Y2);
249 }
peah522d71b2017-02-23 05:16:26 -0800250 }
peah86afe9d2017-04-06 15:45:32 -0700251
Per Åhgren63b494d2017-12-06 11:32:38 +0100252 // Detect and flag echo saturation.
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200253 if (config_.ep_strength.echo_can_saturate) {
Per Åhgren31122d62018-04-10 16:33:55 +0200254 echo_saturation_ = DetectEchoSaturation(x, EchoPathGain());
Per Åhgren1b4059e2017-10-15 20:19:21 +0200255 }
peah86afe9d2017-04-06 15:45:32 -0700256
Per Åhgrenf954ba52018-07-27 14:53:58 +0200257 if (early_filter_usage_activated_) {
Per Åhgren22754392018-08-10 18:37:38 +0200258 filter_has_had_time_to_converge_ =
Per Åhgrenf954ba52018-07-27 14:53:58 +0200259 blocks_with_proper_filter_adaptation_ >= 0.8f * kNumBlocksPerSecond;
260 } else {
Per Åhgren22754392018-08-10 18:37:38 +0200261 filter_has_had_time_to_converge_ =
Per Åhgrenf954ba52018-07-27 14:53:58 +0200262 blocks_with_proper_filter_adaptation_ >= 1.5f * kNumBlocksPerSecond;
263 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100264
Per Åhgren6204adf2018-08-19 11:12:00 +0200265 if (converged_filter && early_entry_to_converged_mode_) {
266 filter_has_had_time_to_converge_ = true;
267 }
268
Per Åhgren5c532d32018-03-22 00:29:25 +0100269 if (!filter_should_have_converged_) {
270 filter_should_have_converged_ =
271 blocks_with_proper_filter_adaptation_ > 6 * kNumBlocksPerSecond;
272 }
273
274 // Flag whether the initial state is still active.
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200275 bool prev_initial_state = initial_state_;
Per Åhgrenf954ba52018-07-27 14:53:58 +0200276 if (use_short_initial_state_) {
Per Åhgrenc3da6712018-08-17 00:09:15 +0200277 initial_state_ = blocks_with_proper_filter_adaptation_ <
278 config_.filter.initial_state_seconds * kNumBlocksPerSecond;
Per Åhgrenf954ba52018-07-27 14:53:58 +0200279 } else {
280 initial_state_ =
281 blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond;
282 }
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200283 transition_triggered_ = !initial_state_ && prev_initial_state;
Per Åhgrena98c8072018-01-15 19:17:16 +0100284
Per Åhgren5c532d32018-03-22 00:29:25 +0100285 // Update counters for the filter divergence and convergence.
286 diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0;
287 if (diverged_blocks_ >= 60) {
288 blocks_since_converged_filter_ = kBlocksSinceConvergencedFilterInit;
289 } else {
290 blocks_since_converged_filter_ =
291 converged_filter ? 0 : blocks_since_converged_filter_ + 1;
292 }
Per Åhgren8131eb02018-03-28 18:13:41 +0200293 if (converged_filter) {
294 active_blocks_since_converged_filter_ = 0;
295 } else if (active_render_block) {
296 ++active_blocks_since_converged_filter_;
297 }
298
Per Åhgren5c532d32018-03-22 00:29:25 +0100299 bool recently_converged_filter =
300 blocks_since_converged_filter_ < 60 * kNumBlocksPerSecond;
301
Per Åhgrenf3e2bf12018-03-22 10:15:59 +0100302 if (blocks_since_converged_filter_ > 20 * kNumBlocksPerSecond) {
303 converged_filter_count_ = 0;
304 } else if (converged_filter) {
305 ++converged_filter_count_;
306 }
307 if (converged_filter_count_ > 50) {
308 finite_erl_ = true;
309 }
310
Per Åhgren5c532d32018-03-22 00:29:25 +0100311 if (filter_analyzer_.Consistent() && filter_delay_blocks_ < 5) {
312 consistent_filter_seen_ = true;
313 active_blocks_since_consistent_filter_estimate_ = 0;
314 } else if (active_render_block) {
315 ++active_blocks_since_consistent_filter_estimate_;
316 }
317
318 bool consistent_filter_estimate_not_seen;
319 if (!consistent_filter_seen_) {
320 consistent_filter_estimate_not_seen =
321 capture_block_counter_ > 5 * kNumBlocksPerSecond;
322 } else {
323 consistent_filter_estimate_not_seen =
324 active_blocks_since_consistent_filter_estimate_ >
325 30 * kNumBlocksPerSecond;
326 }
327
328 converged_filter_seen_ = converged_filter_seen_ || converged_filter;
Per Åhgren63b494d2017-12-06 11:32:38 +0100329
Per Åhgren8131eb02018-03-28 18:13:41 +0200330 // If no filter convergence is seen for a long time, reset the estimated
331 // properties of the echo path.
332 if (active_blocks_since_converged_filter_ > 60 * kNumBlocksPerSecond) {
333 converged_filter_seen_ = false;
334 finite_erl_ = false;
335 }
336
Per Åhgren63b494d2017-12-06 11:32:38 +0100337 // After an amount of active render samples for which an echo should have been
338 // detected in the capture signal if the ERL was not infinite, flag that a
339 // transparent mode should be entered.
Per Åhgrenf3e2bf12018-03-22 10:15:59 +0100340 transparent_mode_ = !config_.ep_strength.bounded_erl && !finite_erl_;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100341 transparent_mode_ =
Per Åhgren5c532d32018-03-22 00:29:25 +0100342 transparent_mode_ &&
343 (consistent_filter_estimate_not_seen || !converged_filter_seen_);
Per Åhgrend18e87e2018-05-09 12:07:26 +0200344 transparent_mode_ = transparent_mode_ && filter_should_have_converged_;
345 transparent_mode_ = transparent_mode_ && allow_transparent_mode_;
Per Åhgren5c532d32018-03-22 00:29:25 +0100346
347 usable_linear_estimate_ = !echo_saturation_;
Per Åhgrene3ca9912018-05-28 22:57:17 +0200348
Per Åhgren22754392018-08-10 18:37:38 +0200349 if (convergence_trigger_linear_mode_) {
350 usable_linear_estimate_ =
351 usable_linear_estimate_ &&
352 ((filter_has_had_time_to_converge_ && external_delay) ||
353 converged_filter_seen_);
354 } else {
355 usable_linear_estimate_ =
356 usable_linear_estimate_ && filter_has_had_time_to_converge_;
357 }
358
359 if (!no_alignment_required_for_linear_mode_) {
360 usable_linear_estimate_ = usable_linear_estimate_ && external_delay;
361 }
362
Per Åhgrene3ca9912018-05-28 22:57:17 +0200363 if (!config_.echo_removal_control.linear_and_stable_echo_path) {
364 usable_linear_estimate_ =
365 usable_linear_estimate_ && recently_converged_filter;
Per Åhgrene3ca9912018-05-28 22:57:17 +0200366 }
Gustaf Ullberg9ed97922018-08-27 14:38:28 +0200367 usable_linear_estimate_ = usable_linear_estimate_ && !TransparentMode();
Per Åhgren5c532d32018-03-22 00:29:25 +0100368
369 use_linear_filter_output_ = usable_linear_estimate_ && !TransparentMode();
Per Åhgren6204adf2018-08-19 11:12:00 +0200370
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200371 const bool stationary_block =
372 use_stationary_properties_ && echo_audibility_.IsBlockStationary();
373
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200374 reverb_model_estimator_.Update(
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200375 filter_analyzer_.GetAdjustedFilter(), adaptive_filter_frequency_response,
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200376 erle_estimator_.GetInstLinearQualityEstimate(), filter_delay_blocks_,
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200377 usable_linear_estimate_, stationary_block);
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200378
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200379 erle_estimator_.Dump(data_dumper_);
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200380 reverb_model_estimator_.Dump(data_dumper_.get());
Per Åhgren5c532d32018-03-22 00:29:25 +0100381 data_dumper_->DumpRaw("aec3_erl", Erl());
Per Åhgren5c532d32018-03-22 00:29:25 +0100382 data_dumper_->DumpRaw("aec3_erl_time_domain", ErlTimeDomain());
383 data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
384 data_dumper_->DumpRaw("aec3_transparent_mode", transparent_mode_);
385 data_dumper_->DumpRaw("aec3_state_internal_delay",
386 internal_delay_ ? *internal_delay_ : -1);
387 data_dumper_->DumpRaw("aec3_filter_delay", filter_analyzer_.DelayBlocks());
388
389 data_dumper_->DumpRaw("aec3_consistent_filter",
390 filter_analyzer_.Consistent());
391 data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200392 data_dumper_->DumpRaw("aec3_initial_state", initial_state_);
Per Åhgren5c532d32018-03-22 00:29:25 +0100393 data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
394 data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_);
395 data_dumper_->DumpRaw("aec3_converged_filter", converged_filter);
396 data_dumper_->DumpRaw("aec3_diverged_filter", diverged_filter);
397
398 data_dumper_->DumpRaw("aec3_external_delay_avaliable",
399 external_delay ? 1 : 0);
400 data_dumper_->DumpRaw("aec3_consistent_filter_estimate_not_seen",
401 consistent_filter_estimate_not_seen);
402 data_dumper_->DumpRaw("aec3_filter_should_have_converged",
403 filter_should_have_converged_);
404 data_dumper_->DumpRaw("aec3_filter_has_had_time_to_converge",
Per Åhgren22754392018-08-10 18:37:38 +0200405 filter_has_had_time_to_converge_);
Per Åhgren5c532d32018-03-22 00:29:25 +0100406 data_dumper_->DumpRaw("aec3_recently_converged_filter",
407 recently_converged_filter);
Jesús de Vicente Peñadd092872018-05-25 16:55:11 +0200408 data_dumper_->DumpRaw("aec3_suppresion_gain_limiter_running",
409 IsSuppressionGainLimitActive());
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200410 data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
411 GetReverbFrequencyResponse());
peah29103572017-07-11 02:54:02 -0700412}
413
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100414bool AecState::DetectActiveRender(rtc::ArrayView<const float> x) const {
415 const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
416 return x_energy > (config_.render_levels.active_render_limit *
417 config_.render_levels.active_render_limit) *
418 kFftLengthBy2;
419}
420
Per Åhgren31122d62018-04-10 16:33:55 +0200421bool AecState::DetectEchoSaturation(rtc::ArrayView<const float> x,
422 float echo_path_gain) {
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100423 RTC_DCHECK_LT(0, x.size());
424 const float max_sample = fabs(*std::max_element(
425 x.begin(), x.end(), [](float a, float b) { return a * a < b * b; }));
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100426
427 // Set flag for potential presence of saturated echo
Per Åhgren31122d62018-04-10 16:33:55 +0200428 const float kMargin = 10.f;
429 float peak_echo_amplitude = max_sample * echo_path_gain * kMargin;
430 if (SaturatedCapture() && peak_echo_amplitude > 32000) {
431 blocks_since_last_saturation_ = 0;
432 } else {
433 ++blocks_since_last_saturation_;
434 }
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100435
Per Åhgren31122d62018-04-10 16:33:55 +0200436 return blocks_since_last_saturation_ < 5;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100437}
438
peah522d71b2017-02-23 05:16:26 -0800439} // namespace webrtc