blob: a39325c8b85932e7bbab0e4da1341049d15372e1 [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#ifndef MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_
12#define MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_
peah522d71b2017-02-23 05:16:26 -080013
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stddef.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
Yves Gerey988cc082018-10-23 12:03:01 +020016#include <array>
Niels Möller7a669002022-06-27 09:47:02 +020017#include <atomic>
peah522d71b2017-02-23 05:16:26 -080018#include <memory>
19#include <vector>
20
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020021#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "api/array_view.h"
Gustaf Ullberg3646f972018-02-14 15:19:04 +010023#include "api/audio/echo_canceller3_config.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/audio_processing/aec3/aec3_common.h"
Per Åhgren3ab308f2018-02-21 08:46:03 +010025#include "modules/audio_processing/aec3/delay_estimate.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020026#include "modules/audio_processing/aec3/echo_audibility.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/audio_processing/aec3/echo_path_variability.h"
28#include "modules/audio_processing/aec3/erl_estimator.h"
29#include "modules/audio_processing/aec3/erle_estimator.h"
Per Åhgren5c532d32018-03-22 00:29:25 +010030#include "modules/audio_processing/aec3/filter_analyzer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "modules/audio_processing/aec3/render_buffer.h"
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +020032#include "modules/audio_processing/aec3/reverb_model_estimator.h"
Per Åhgrenb20b9372018-07-13 00:22:54 +020033#include "modules/audio_processing/aec3/subtractor_output.h"
34#include "modules/audio_processing/aec3/subtractor_output_analyzer.h"
Gustaf Ullbergafef7a72020-09-24 09:21:49 +020035#include "modules/audio_processing/aec3/transparent_mode.h"
peah522d71b2017-02-23 05:16:26 -080036
37namespace webrtc {
38
39class ApmDataDumper;
40
41// Handles the state and the conditions for the echo removal functionality.
42class AecState {
43 public:
Sam Zackrisson8f736c02019-10-01 12:47:53 +020044 AecState(const EchoCanceller3Config& config, size_t num_capture_channels);
peah522d71b2017-02-23 05:16:26 -080045 ~AecState();
46
Per Åhgren4b3bc0f2017-12-20 15:26:13 +010047 // Returns whether the echo subtractor can be used to determine the residual
48 // echo.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020049 bool UsableLinearEstimate() const {
Gustaf Ullberg52caa0e2019-04-11 14:43:17 +020050 return filter_quality_state_.LinearFilterUsable() &&
51 config_.filter.use_linear_filter;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020052 }
peah522d71b2017-02-23 05:16:26 -080053
Per Åhgren5c532d32018-03-22 00:29:25 +010054 // Returns whether the echo subtractor output should be used as output.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020055 bool UseLinearFilterOutput() const {
Gustaf Ullberg52caa0e2019-04-11 14:43:17 +020056 return filter_quality_state_.LinearFilterUsable() &&
57 config_.filter.use_linear_filter;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020058 }
Per Åhgren5c532d32018-03-22 00:29:25 +010059
peah522d71b2017-02-23 05:16:26 -080060 // Returns whether the render signal is currently active.
Per Åhgren4b3bc0f2017-12-20 15:26:13 +010061 bool ActiveRender() const { return blocks_with_active_render_ > 200; }
peahebe77782017-02-27 07:29:21 -080062
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020063 // Returns the appropriate scaling of the residual echo to match the
64 // audibility.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +020065 void GetResidualEchoScaling(rtc::ArrayView<float> residual_scaling) const;
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020066
67 // Returns whether the stationary properties of the signals are used in the
68 // aec.
Per Åhgrenb4161d32019-10-08 12:35:47 +020069 bool UseStationarityProperties() const {
Jesús de Vicente Peña70a59632019-04-16 12:32:15 +020070 return config_.echo_audibility.use_stationarity_properties;
Per Åhgrenf4801a12018-09-27 13:14:02 +020071 }
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020072
peah522d71b2017-02-23 05:16:26 -080073 // Returns the ERLE.
Gustaf Ullberg437d1292021-04-20 13:48:57 +020074 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Erle(
75 bool onset_compensated) const {
76 return erle_estimator_.Erle(onset_compensated);
peah522d71b2017-02-23 05:16:26 -080077 }
78
Gustaf Ullberga63d1522021-06-11 14:02:53 +020079 // Returns the non-capped ERLE.
80 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> ErleUnbounded()
81 const {
82 return erle_estimator_.ErleUnbounded();
83 }
84
Jesús de Vicente Peñae9a7e902018-09-27 11:49:39 +020085 // Returns the fullband ERLE estimate in log2 units.
86 float FullBandErleLog2() const { return erle_estimator_.FullbandErleLog2(); }
Gustaf Ullberg332150d2017-11-22 14:17:39 +010087
peah522d71b2017-02-23 05:16:26 -080088 // Returns the ERL.
89 const std::array<float, kFftLengthBy2Plus1>& Erl() const {
90 return erl_estimator_.Erl();
91 }
92
Gustaf Ullberg332150d2017-11-22 14:17:39 +010093 // Returns the time-domain ERL.
94 float ErlTimeDomain() const { return erl_estimator_.ErlTimeDomain(); }
95
peah522d71b2017-02-23 05:16:26 -080096 // Returns the delay estimate based on the linear filter.
Per Åhgren8718afb2019-10-15 10:31:35 +020097 int MinDirectPathFilterDelay() const {
98 return delay_state_.MinDirectPathFilterDelay();
Per Åhgren8be669f2019-10-11 23:02:26 +020099 }
peah522d71b2017-02-23 05:16:26 -0800100
peah522d71b2017-02-23 05:16:26 -0800101 // Returns whether the capture signal is saturated.
102 bool SaturatedCapture() const { return capture_signal_saturation_; }
103
peah86afe9d2017-04-06 15:45:32 -0700104 // Returns whether the echo signal is saturated.
Gustaf Ullberg68d6d442019-01-29 10:08:15 +0100105 bool SaturatedEcho() const { return saturation_detector_.SaturatedEcho(); }
peah86afe9d2017-04-06 15:45:32 -0700106
peah522d71b2017-02-23 05:16:26 -0800107 // Updates the capture signal saturation.
108 void UpdateCaptureSaturation(bool capture_signal_saturation) {
109 capture_signal_saturation_ = capture_signal_saturation;
110 }
111
Per Åhgren1b4059e2017-10-15 20:19:21 +0200112 // Returns whether the transparent mode is active
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200113 bool TransparentModeActive() const {
114 return transparent_state_ && transparent_state_->Active();
Per Åhgrend8d09c32020-04-01 17:30:18 +0200115 }
peah522d71b2017-02-23 05:16:26 -0800116
peah86afe9d2017-04-06 15:45:32 -0700117 // Takes appropriate action at an echo path change.
118 void HandleEchoPathChange(const EchoPathVariability& echo_path_variability);
119
Jesús de Vicente Peña7d0203c2021-09-08 10:44:55 +0200120 // Returns the decay factor for the echo reverberation. The parameter `mild`
121 // indicates which exponential decay to return. The default one or a milder
122 // one that can be used during nearend regions.
123 float ReverbDecay(bool mild) const {
124 return reverb_model_estimator_.ReverbDecay(mild);
125 }
peah89420452017-04-07 06:13:39 -0700126
Per Åhgrenef5d5af2018-07-31 00:03:46 +0200127 // Return the frequency response of the reverberant echo.
128 rtc::ArrayView<const float> GetReverbFrequencyResponse() const {
129 return reverb_model_estimator_.GetReverbFrequencyResponse();
130 }
131
Jesús de Vicente Peña02e9e442018-08-29 13:34:07 +0200132 // Returns whether the transition for going out of the initial stated has
133 // been triggered.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200134 bool TransitionTriggered() const {
135 return initial_state_.TransitionTriggered();
136 }
Per Åhgrena98c8072018-01-15 19:17:16 +0100137
peah522d71b2017-02-23 05:16:26 -0800138 // Updates the aec state.
Per Åhgren119e2192019-10-18 08:50:50 +0200139 // TODO(bugs.webrtc.org/10913): Compute multi-channel ERL.
Sam Zackrisson46b01402019-10-08 16:17:48 +0200140 void Update(
141 const absl::optional<DelayEstimate>& external_delay,
142 rtc::ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
Per Åhgren8be669f2019-10-11 23:02:26 +0200143 adaptive_filter_frequency_responses,
144 rtc::ArrayView<const std::vector<float>>
145 adaptive_filter_impulse_responses,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200146 const RenderBuffer& render_buffer,
Per Åhgrenff045112020-03-20 11:20:39 +0100147 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2_refined,
Per Åhgrenf9807252019-10-09 13:57:07 +0200148 rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200149 rtc::ArrayView<const SubtractorOutput> subtractor_output);
peah522d71b2017-02-23 05:16:26 -0800150
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200151 // Returns filter length in blocks.
152 int FilterLengthBlocks() const {
Sam Zackrisson46b01402019-10-08 16:17:48 +0200153 // All filters have the same length, so arbitrarily return channel 0 length.
Per Åhgren8be669f2019-10-11 23:02:26 +0200154 return filter_analyzer_.FilterLengthBlocks();
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +0200155 }
156
peah522d71b2017-02-23 05:16:26 -0800157 private:
Niels Möller7a669002022-06-27 09:47:02 +0200158 static std::atomic<int> instance_count_;
peah522d71b2017-02-23 05:16:26 -0800159 std::unique_ptr<ApmDataDumper> data_dumper_;
Per Åhgren90e3fbd2018-05-16 15:25:04 +0200160 const EchoCanceller3Config config_;
Per Åhgren785d4c42019-10-17 14:40:54 +0200161 const size_t num_capture_channels_;
Per Åhgrend8d09c32020-04-01 17:30:18 +0200162 const bool deactivate_initial_state_reset_at_echo_path_change_;
163 const bool full_reset_at_echo_path_change_;
164 const bool subtractor_analyzer_reset_at_echo_path_change_;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200165
166 // Class for controlling the transition from the intial state, which in turn
167 // controls when the filter parameters for the initial state should be used.
168 class InitialState {
169 public:
170 explicit InitialState(const EchoCanceller3Config& config);
171 // Resets the state to again begin in the initial state.
172 void Reset();
173
174 // Updates the state based on new data.
175 void Update(bool active_render, bool saturated_capture);
176
177 // Returns whether the initial state is active or not.
178 bool InitialStateActive() const { return initial_state_; }
179
180 // Returns that the transition from the initial state has was started.
181 bool TransitionTriggered() const { return transition_triggered_; }
182
183 private:
184 const bool conservative_initial_phase_;
185 const float initial_state_seconds_;
186 bool transition_triggered_ = false;
187 bool initial_state_ = true;
188 size_t strong_not_saturated_render_blocks_ = 0;
189 } initial_state_;
190
191 // Class for choosing the direct-path delay relative to the beginning of the
192 // filter, as well as any other data related to the delay used within
193 // AecState.
194 class FilterDelay {
195 public:
Per Åhgren8be669f2019-10-11 23:02:26 +0200196 FilterDelay(const EchoCanceller3Config& config,
197 size_t num_capture_channels);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200198
199 // Returns whether an external delay has been reported to the AecState (from
200 // the delay estimator).
201 bool ExternalDelayReported() const { return external_delay_reported_; }
202
203 // Returns the delay in blocks relative to the beginning of the filter that
204 // corresponds to the direct path of the echo.
Per Åhgren8be669f2019-10-11 23:02:26 +0200205 rtc::ArrayView<const int> DirectPathFilterDelays() const {
206 return filter_delays_blocks_;
207 }
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200208
Per Åhgren8718afb2019-10-15 10:31:35 +0200209 // Returns the minimum delay among the direct path delays relative to the
210 // beginning of the filter
211 int MinDirectPathFilterDelay() const { return min_filter_delay_; }
212
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200213 // Updates the delay estimates based on new data.
Sam Zackrisson46b01402019-10-08 16:17:48 +0200214 void Update(
Per Åhgren8be669f2019-10-11 23:02:26 +0200215 rtc::ArrayView<const int> analyzer_filter_delay_estimates_blocks,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200216 const absl::optional<DelayEstimate>& external_delay,
217 size_t blocks_with_proper_filter_adaptation);
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200218
219 private:
Sam Zackrissonfa292792020-10-05 15:23:04 +0200220 const int delay_headroom_blocks_;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200221 bool external_delay_reported_ = false;
Per Åhgren8be669f2019-10-11 23:02:26 +0200222 std::vector<int> filter_delays_blocks_;
Sam Zackrissonfa292792020-10-05 15:23:04 +0200223 int min_filter_delay_;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200224 absl::optional<DelayEstimate> external_delay_;
225 } delay_state_;
226
Gustaf Ullbergafef7a72020-09-24 09:21:49 +0200227 // Classifier for toggling transparent mode when there is no echo.
228 std::unique_ptr<TransparentMode> transparent_state_;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200229
230 // Class for analyzing how well the linear filter is, and can be expected to,
231 // perform on the current signals. The purpose of this is for using to
232 // select the echo suppression functionality as well as the input to the echo
233 // suppressor.
234 class FilteringQualityAnalyzer {
235 public:
Per Åhgren8be669f2019-10-11 23:02:26 +0200236 FilteringQualityAnalyzer(const EchoCanceller3Config& config,
237 size_t num_capture_channels);
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200238
Per Åhgren8be669f2019-10-11 23:02:26 +0200239 // Returns whether the linear filter can be used for the echo
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200240 // canceller output.
Per Åhgren8be669f2019-10-11 23:02:26 +0200241 bool LinearFilterUsable() const { return overall_usable_linear_estimates_; }
242
243 // Returns whether an individual filter output can be used for the echo
244 // canceller output.
245 const std::vector<bool>& UsableLinearFilterOutputs() const {
246 return usable_linear_filter_estimates_;
247 }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200248
249 // Resets the state of the analyzer.
250 void Reset();
251
252 // Updates the analysis based on new data.
253 void Update(bool active_render,
254 bool transparent_mode,
255 bool saturated_capture,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200256 const absl::optional<DelayEstimate>& external_delay,
Sam Zackrisson46b01402019-10-08 16:17:48 +0200257 bool any_filter_converged);
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200258
259 private:
Per Åhgren8be669f2019-10-11 23:02:26 +0200260 const bool use_linear_filter_;
261 bool overall_usable_linear_estimates_ = false;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200262 size_t filter_update_blocks_since_reset_ = 0;
263 size_t filter_update_blocks_since_start_ = 0;
264 bool convergence_seen_ = false;
Per Åhgren8be669f2019-10-11 23:02:26 +0200265 std::vector<bool> usable_linear_filter_estimates_;
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200266 } filter_quality_state_;
267
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200268 // Class for detecting whether the echo is to be considered to be
269 // saturated.
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200270 class SaturationDetector {
271 public:
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200272 // Returns whether the echo is to be considered saturated.
Nico Weber22f99252019-02-20 10:13:16 -0500273 bool SaturatedEcho() const { return saturated_echo_; }
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200274
275 // Updates the detection decision based on new data.
Gustaf Ullbergd3ead1a2022-05-23 10:39:53 +0200276 void Update(const Block& x,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200277 bool saturated_capture,
278 bool usable_linear_estimate,
Sam Zackrisson8f736c02019-10-01 12:47:53 +0200279 rtc::ArrayView<const SubtractorOutput> subtractor_output,
Per Åhgren3e7b7b12018-10-16 14:38:10 +0200280 float echo_path_gain);
281
282 private:
283 bool saturated_echo_ = false;
284 } saturation_detector_;
285
peah522d71b2017-02-23 05:16:26 -0800286 ErlEstimator erl_estimator_;
287 ErleEstimator erle_estimator_;
Per Åhgrenc5a38ad2018-10-04 15:37:54 +0200288 size_t strong_not_saturated_render_blocks_ = 0;
Per Åhgren4b3bc0f2017-12-20 15:26:13 +0100289 size_t blocks_with_active_render_ = 0;
peah522d71b2017-02-23 05:16:26 -0800290 bool capture_signal_saturation_ = false;
Per Åhgren8be669f2019-10-11 23:02:26 +0200291 FilterAnalyzer filter_analyzer_;
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200292 EchoAudibility echo_audibility_;
Jesús de Vicente Peña496cedf2018-07-04 11:02:09 +0200293 ReverbModelEstimator reverb_model_estimator_;
Per Åhgren8718afb2019-10-15 10:31:35 +0200294 ReverbModel avg_render_reverb_;
Per Åhgren785d4c42019-10-17 14:40:54 +0200295 SubtractorOutputAnalyzer subtractor_output_analyzer_;
peah522d71b2017-02-23 05:16:26 -0800296};
297
298} // namespace webrtc
299
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200300#endif // MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_