subtractor.h (5751B)
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_SUBTRACTOR_H_ 12 #define MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_H_ 13 14 #include <array> 15 #include <cmath> 16 #include <cstddef> 17 #include <memory> 18 #include <vector> 19 20 #include "api/array_view.h" 21 #include "api/audio/echo_canceller3_config.h" 22 #include "api/environment/environment.h" 23 #include "modules/audio_processing/aec3/adaptive_fir_filter.h" 24 #include "modules/audio_processing/aec3/aec3_common.h" 25 #include "modules/audio_processing/aec3/aec3_fft.h" 26 #include "modules/audio_processing/aec3/aec_state.h" 27 #include "modules/audio_processing/aec3/block.h" 28 #include "modules/audio_processing/aec3/coarse_filter_update_gain.h" 29 #include "modules/audio_processing/aec3/echo_path_variability.h" 30 #include "modules/audio_processing/aec3/refined_filter_update_gain.h" 31 #include "modules/audio_processing/aec3/render_buffer.h" 32 #include "modules/audio_processing/aec3/render_signal_analyzer.h" 33 #include "modules/audio_processing/aec3/subtractor_output.h" 34 #include "modules/audio_processing/logging/apm_data_dumper.h" 35 #include "rtc_base/checks.h" 36 37 namespace webrtc { 38 39 // Proves linear echo cancellation functionality 40 class Subtractor { 41 public: 42 Subtractor(const Environment& env, 43 const EchoCanceller3Config& config, 44 size_t num_render_channels, 45 size_t num_capture_channels, 46 ApmDataDumper* data_dumper, 47 Aec3Optimization optimization); 48 ~Subtractor(); 49 Subtractor(const Subtractor&) = delete; 50 Subtractor& operator=(const Subtractor&) = delete; 51 52 // Performs the echo subtraction. 53 void Process(const RenderBuffer& render_buffer, 54 const Block& capture, 55 const RenderSignalAnalyzer& render_signal_analyzer, 56 const AecState& aec_state, 57 ArrayView<SubtractorOutput> outputs); 58 59 void HandleEchoPathChange(const EchoPathVariability& echo_path_variability); 60 61 // Exits the initial state. 62 void ExitInitialState(); 63 64 // Returns the block-wise frequency responses for the refined adaptive 65 // filters. 66 const std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>>& 67 FilterFrequencyResponses() const { 68 return refined_frequency_responses_; 69 } 70 71 // Returns the estimates of the impulse responses for the refined adaptive 72 // filters. 73 const std::vector<std::vector<float>>& FilterImpulseResponses() const { 74 return refined_impulse_responses_; 75 } 76 77 void DumpFilters() { 78 data_dumper_->DumpRaw( 79 "aec3_subtractor_h_refined", 80 ArrayView<const float>( 81 refined_impulse_responses_[0].data(), 82 GetTimeDomainLength( 83 refined_filters_[0]->max_filter_size_partitions()))); 84 if (ApmDataDumper::IsAvailable()) { 85 RTC_DCHECK_GT(coarse_impulse_responses_.size(), 0); 86 data_dumper_->DumpRaw( 87 "aec3_subtractor_h_coarse", 88 ArrayView<const float>( 89 coarse_impulse_responses_[0].data(), 90 GetTimeDomainLength( 91 coarse_filter_[0]->max_filter_size_partitions()))); 92 } 93 94 refined_filters_[0]->DumpFilter("aec3_subtractor_H_refined"); 95 coarse_filter_[0]->DumpFilter("aec3_subtractor_H_coarse"); 96 } 97 98 private: 99 class FilterMisadjustmentEstimator { 100 public: 101 FilterMisadjustmentEstimator() = default; 102 ~FilterMisadjustmentEstimator() = default; 103 // Update the misadjustment estimator. 104 void Update(const SubtractorOutput& output); 105 // GetMisadjustment() Returns a recommended scale for the filter so the 106 // prediction error energy gets closer to the energy that is seen at the 107 // microphone input. 108 float GetMisadjustment() const { 109 RTC_DCHECK_GT(inv_misadjustment_, 0.0f); 110 // It is not aiming to adjust all the estimated mismatch. Instead, 111 // it adjusts half of that estimated mismatch. 112 return 2.f / sqrtf(inv_misadjustment_); 113 } 114 // Returns true if the prediciton error energy is significantly larger 115 // than the microphone signal energy and, therefore, an adjustment is 116 // recommended. 117 bool IsAdjustmentNeeded() const { return inv_misadjustment_ > 10.f; } 118 void Reset(); 119 void Dump(ApmDataDumper* data_dumper) const; 120 121 private: 122 const int n_blocks_ = 4; 123 int n_blocks_acum_ = 0; 124 float e2_acum_ = 0.f; 125 float y2_acum_ = 0.f; 126 float inv_misadjustment_ = 0.f; 127 int overhang_ = 0.f; 128 }; 129 130 const Aec3Fft fft_; 131 ApmDataDumper* data_dumper_; 132 const Aec3Optimization optimization_; 133 const EchoCanceller3Config config_; 134 const size_t num_capture_channels_; 135 const bool use_coarse_filter_reset_hangover_; 136 137 std::vector<std::unique_ptr<AdaptiveFirFilter>> refined_filters_; 138 std::vector<std::unique_ptr<AdaptiveFirFilter>> coarse_filter_; 139 std::vector<std::unique_ptr<RefinedFilterUpdateGain>> refined_gains_; 140 std::vector<std::unique_ptr<CoarseFilterUpdateGain>> coarse_gains_; 141 std::vector<FilterMisadjustmentEstimator> filter_misadjustment_estimators_; 142 std::vector<size_t> poor_coarse_filter_counters_; 143 std::vector<int> coarse_filter_reset_hangover_; 144 std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>> 145 refined_frequency_responses_; 146 std::vector<std::vector<float>> refined_impulse_responses_; 147 std::vector<std::vector<float>> coarse_impulse_responses_; 148 }; 149 150 } // namespace webrtc 151 152 #endif // MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_H_