aec_state.h (11537B)
1 /* 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 11 #ifndef MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_ 12 #define MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_ 13 14 #include <stddef.h> 15 16 #include <array> 17 #include <atomic> 18 #include <memory> 19 #include <optional> 20 #include <vector> 21 22 #include "api/array_view.h" 23 #include "api/audio/echo_canceller3_config.h" 24 #include "api/environment/environment.h" 25 #include "modules/audio_processing/aec3/aec3_common.h" 26 #include "modules/audio_processing/aec3/block.h" 27 #include "modules/audio_processing/aec3/delay_estimate.h" 28 #include "modules/audio_processing/aec3/echo_audibility.h" 29 #include "modules/audio_processing/aec3/echo_path_variability.h" 30 #include "modules/audio_processing/aec3/erl_estimator.h" 31 #include "modules/audio_processing/aec3/erle_estimator.h" 32 #include "modules/audio_processing/aec3/filter_analyzer.h" 33 #include "modules/audio_processing/aec3/render_buffer.h" 34 #include "modules/audio_processing/aec3/reverb_model.h" 35 #include "modules/audio_processing/aec3/reverb_model_estimator.h" 36 #include "modules/audio_processing/aec3/subtractor_output.h" 37 #include "modules/audio_processing/aec3/subtractor_output_analyzer.h" 38 #include "modules/audio_processing/aec3/transparent_mode.h" 39 40 namespace webrtc { 41 42 class ApmDataDumper; 43 44 // Handles the state and the conditions for the echo removal functionality. 45 class AecState { 46 public: 47 AecState(const Environment& env, 48 const EchoCanceller3Config& config, 49 size_t num_capture_channels); 50 ~AecState(); 51 52 // Returns whether the echo subtractor can be used to determine the residual 53 // echo. 54 bool UsableLinearEstimate() const { 55 return filter_quality_state_.LinearFilterUsable() && 56 config_.filter.use_linear_filter; 57 } 58 59 // Returns whether the echo subtractor output should be used as output. 60 bool UseLinearFilterOutput() const { 61 return filter_quality_state_.LinearFilterUsable() && 62 config_.filter.use_linear_filter; 63 } 64 65 // Returns whether the render signal is currently active. 66 bool ActiveRender() const { return blocks_with_active_render_ > 200; } 67 68 // Returns the appropriate scaling of the residual echo to match the 69 // audibility. 70 void GetResidualEchoScaling(ArrayView<float> residual_scaling) const; 71 72 // Returns whether the stationary properties of the signals are used in the 73 // aec. 74 bool UseStationarityProperties() const { 75 return config_.echo_audibility.use_stationarity_properties; 76 } 77 78 // Returns the ERLE. 79 ArrayView<const std::array<float, kFftLengthBy2Plus1>> Erle( 80 bool onset_compensated) const { 81 return erle_estimator_.Erle(onset_compensated); 82 } 83 84 // Returns the non-capped ERLE. 85 ArrayView<const std::array<float, kFftLengthBy2Plus1>> ErleUnbounded() const { 86 return erle_estimator_.ErleUnbounded(); 87 } 88 89 // Returns the fullband ERLE estimate in log2 units. 90 float FullBandErleLog2() const { return erle_estimator_.FullbandErleLog2(); } 91 92 // Returns the ERL. 93 const std::array<float, kFftLengthBy2Plus1>& Erl() const { 94 return erl_estimator_.Erl(); 95 } 96 97 // Returns the time-domain ERL. 98 float ErlTimeDomain() const { return erl_estimator_.ErlTimeDomain(); } 99 100 // Returns the delay estimate based on the linear filter. 101 int MinDirectPathFilterDelay() const { 102 return delay_state_.MinDirectPathFilterDelay(); 103 } 104 105 // Returns whether the capture signal is saturated. 106 bool SaturatedCapture() const { return capture_signal_saturation_; } 107 108 // Returns whether the echo signal is saturated. 109 bool SaturatedEcho() const { return saturation_detector_.SaturatedEcho(); } 110 111 // Updates the capture signal saturation. 112 void UpdateCaptureSaturation(bool capture_signal_saturation) { 113 capture_signal_saturation_ = capture_signal_saturation; 114 } 115 116 // Returns whether the transparent mode is active 117 bool TransparentModeActive() const { 118 return transparent_state_ && transparent_state_->Active(); 119 } 120 121 // Takes appropriate action at an echo path change. 122 void HandleEchoPathChange(const EchoPathVariability& echo_path_variability); 123 124 // Returns the decay factor for the echo reverberation. The parameter `mild` 125 // indicates which exponential decay to return. The default one or a milder 126 // one that can be used during nearend regions. 127 float ReverbDecay(bool mild) const { 128 return reverb_model_estimator_.ReverbDecay(mild); 129 } 130 131 // Return the frequency response of the reverberant echo. 132 ArrayView<const float> GetReverbFrequencyResponse() const { 133 return reverb_model_estimator_.GetReverbFrequencyResponse(); 134 } 135 136 // Returns whether the transition for going out of the initial stated has 137 // been triggered. 138 bool TransitionTriggered() const { 139 return initial_state_.TransitionTriggered(); 140 } 141 142 // Updates the aec state. 143 // TODO(bugs.webrtc.org/10913): Compute multi-channel ERL. 144 void Update( 145 const std::optional<DelayEstimate>& external_delay, 146 ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>> 147 adaptive_filter_frequency_responses, 148 ArrayView<const std::vector<float>> adaptive_filter_impulse_responses, 149 const RenderBuffer& render_buffer, 150 ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2_refined, 151 ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2, 152 ArrayView<const SubtractorOutput> subtractor_output); 153 154 // Returns filter length in blocks. 155 int FilterLengthBlocks() const { 156 // All filters have the same length, so arbitrarily return channel 0 length. 157 return filter_analyzer_.FilterLengthBlocks(); 158 } 159 160 std::optional<DelayEstimate> ExternalDelayBlocks() const { 161 return delay_state_.ExternalDelayBlocks(); 162 } 163 164 private: 165 static std::atomic<int> instance_count_; 166 std::unique_ptr<ApmDataDumper> data_dumper_; 167 const EchoCanceller3Config config_; 168 const size_t num_capture_channels_; 169 const bool deactivate_initial_state_reset_at_echo_path_change_; 170 const bool full_reset_at_echo_path_change_; 171 const bool subtractor_analyzer_reset_at_echo_path_change_; 172 173 // Class for controlling the transition from the intial state, which in turn 174 // controls when the filter parameters for the initial state should be used. 175 class InitialState { 176 public: 177 explicit InitialState(const EchoCanceller3Config& config); 178 // Resets the state to again begin in the initial state. 179 void Reset(); 180 181 // Updates the state based on new data. 182 void Update(bool active_render, bool saturated_capture); 183 184 // Returns whether the initial state is active or not. 185 bool InitialStateActive() const { return initial_state_; } 186 187 // Returns that the transition from the initial state has was started. 188 bool TransitionTriggered() const { return transition_triggered_; } 189 190 private: 191 const bool conservative_initial_phase_; 192 const float initial_state_seconds_; 193 bool transition_triggered_ = false; 194 bool initial_state_ = true; 195 size_t strong_not_saturated_render_blocks_ = 0; 196 } initial_state_; 197 198 // Class for choosing the direct-path delay relative to the beginning of the 199 // filter, as well as any other data related to the delay used within 200 // AecState. 201 class FilterDelay { 202 public: 203 FilterDelay(const EchoCanceller3Config& config, 204 size_t num_capture_channels); 205 206 // Returns whether an external delay has been reported to the AecState (from 207 // the delay estimator). 208 bool ExternalDelayReported() const { return external_delay_.has_value(); } 209 210 // Returns the external delay reported to the AecState (from the delay 211 // estimator). 212 std::optional<DelayEstimate> ExternalDelayBlocks() const { 213 return external_delay_; 214 } 215 216 // Returns the delay in blocks relative to the beginning of the filter that 217 // corresponds to the direct path of the echo. 218 ArrayView<const int> DirectPathFilterDelays() const { 219 return filter_delays_blocks_; 220 } 221 222 // Returns the minimum delay among the direct path delays relative to the 223 // beginning of the filter 224 int MinDirectPathFilterDelay() const { return min_filter_delay_; } 225 226 // Updates the delay estimates based on new data. 227 void Update(ArrayView<const int> analyzer_filter_delay_estimates_blocks, 228 const std::optional<DelayEstimate>& external_delay, 229 size_t blocks_with_proper_filter_adaptation); 230 231 private: 232 const int delay_headroom_blocks_; 233 std::vector<int> filter_delays_blocks_; 234 int min_filter_delay_; 235 std::optional<DelayEstimate> external_delay_; 236 } delay_state_; 237 238 // Classifier for toggling transparent mode when there is no echo. 239 std::unique_ptr<TransparentMode> transparent_state_; 240 241 // Class for analyzing how well the linear filter is, and can be expected to, 242 // perform on the current signals. The purpose of this is for using to 243 // select the echo suppression functionality as well as the input to the echo 244 // suppressor. 245 class FilteringQualityAnalyzer { 246 public: 247 FilteringQualityAnalyzer(const EchoCanceller3Config& config, 248 size_t num_capture_channels); 249 250 // Returns whether the linear filter can be used for the echo 251 // canceller output. 252 bool LinearFilterUsable() const { return overall_usable_linear_estimates_; } 253 254 // Returns whether an individual filter output can be used for the echo 255 // canceller output. 256 const std::vector<bool>& UsableLinearFilterOutputs() const { 257 return usable_linear_filter_estimates_; 258 } 259 260 // Resets the state of the analyzer. 261 void Reset(); 262 263 // Updates the analysis based on new data. 264 void Update(bool active_render, 265 bool transparent_mode, 266 bool saturated_capture, 267 const std::optional<DelayEstimate>& external_delay, 268 bool any_filter_converged); 269 270 private: 271 const bool use_linear_filter_; 272 bool overall_usable_linear_estimates_ = false; 273 size_t filter_update_blocks_since_reset_ = 0; 274 size_t filter_update_blocks_since_start_ = 0; 275 bool convergence_seen_ = false; 276 std::vector<bool> usable_linear_filter_estimates_; 277 } filter_quality_state_; 278 279 // Class for detecting whether the echo is to be considered to be 280 // saturated. 281 class SaturationDetector { 282 public: 283 // Returns whether the echo is to be considered saturated. 284 bool SaturatedEcho() const { return saturated_echo_; } 285 286 // Updates the detection decision based on new data. 287 void Update(const Block& x, 288 bool saturated_capture, 289 bool usable_linear_estimate, 290 ArrayView<const SubtractorOutput> subtractor_output, 291 float echo_path_gain); 292 293 private: 294 bool saturated_echo_ = false; 295 } saturation_detector_; 296 297 ErlEstimator erl_estimator_; 298 ErleEstimator erle_estimator_; 299 size_t strong_not_saturated_render_blocks_ = 0; 300 size_t blocks_with_active_render_ = 0; 301 bool capture_signal_saturation_ = false; 302 FilterAnalyzer filter_analyzer_; 303 EchoAudibility echo_audibility_; 304 ReverbModelEstimator reverb_model_estimator_; 305 ReverbModel avg_render_reverb_; 306 SubtractorOutputAnalyzer subtractor_output_analyzer_; 307 }; 308 309 } // namespace webrtc 310 311 #endif // MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_