OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 #include "webrtc/modules/audio_processing/aec3/echo_remover.h" | 10 #include "webrtc/modules/audio_processing/aec3/echo_remover.h" |
11 | 11 |
12 #include <algorithm> | 12 #include <algorithm> |
13 #include <memory> | 13 #include <memory> |
14 #include <numeric> | 14 #include <numeric> |
15 #include <string> | 15 #include <string> |
16 | 16 |
17 #include "webrtc/base/array_view.h" | 17 #include "webrtc/base/array_view.h" |
18 #include "webrtc/base/atomicops.h" | 18 #include "webrtc/base/atomicops.h" |
19 #include "webrtc/base/constructormagic.h" | 19 #include "webrtc/base/constructormagic.h" |
20 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" | 20 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" |
21 #include "webrtc/modules/audio_processing/aec3/aec_state.h" | 21 #include "webrtc/modules/audio_processing/aec3/aec_state.h" |
22 #include "webrtc/modules/audio_processing/aec3/comfort_noise_generator.h" | 22 #include "webrtc/modules/audio_processing/aec3/comfort_noise_generator.h" |
23 #include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" | 23 #include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" |
24 #include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h" | 24 #include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h" |
25 #include "webrtc/modules/audio_processing/aec3/fft_buffer.h" | |
26 #include "webrtc/modules/audio_processing/aec3/fft_data.h" | 25 #include "webrtc/modules/audio_processing/aec3/fft_data.h" |
27 #include "webrtc/modules/audio_processing/aec3/output_selector.h" | 26 #include "webrtc/modules/audio_processing/aec3/output_selector.h" |
28 #include "webrtc/modules/audio_processing/aec3/power_echo_model.h" | 27 #include "webrtc/modules/audio_processing/aec3/power_echo_model.h" |
28 #include "webrtc/modules/audio_processing/aec3/render_buffer.h" | |
29 #include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" | 29 #include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" |
30 #include "webrtc/modules/audio_processing/aec3/residual_echo_estimator.h" | 30 #include "webrtc/modules/audio_processing/aec3/residual_echo_estimator.h" |
31 #include "webrtc/modules/audio_processing/aec3/subtractor.h" | 31 #include "webrtc/modules/audio_processing/aec3/subtractor.h" |
32 #include "webrtc/modules/audio_processing/aec3/suppression_filter.h" | 32 #include "webrtc/modules/audio_processing/aec3/suppression_filter.h" |
33 #include "webrtc/modules/audio_processing/aec3/suppression_gain.h" | 33 #include "webrtc/modules/audio_processing/aec3/suppression_gain.h" |
34 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | 34 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
35 | 35 |
36 namespace webrtc { | 36 namespace webrtc { |
37 | 37 |
38 namespace { | 38 namespace { |
(...skipping 14 matching lines...) Expand all Loading... | |
53 | 53 |
54 // Class for removing the echo from the capture signal. | 54 // Class for removing the echo from the capture signal. |
55 class EchoRemoverImpl final : public EchoRemover { | 55 class EchoRemoverImpl final : public EchoRemover { |
56 public: | 56 public: |
57 explicit EchoRemoverImpl(int sample_rate_hz); | 57 explicit EchoRemoverImpl(int sample_rate_hz); |
58 ~EchoRemoverImpl() override; | 58 ~EchoRemoverImpl() override; |
59 | 59 |
60 // Removes the echo from a block of samples from the capture signal. The | 60 // Removes the echo from a block of samples from the capture signal. The |
61 // supplied render signal is assumed to be pre-aligned with the capture | 61 // supplied render signal is assumed to be pre-aligned with the capture |
62 // signal. | 62 // signal. |
63 void ProcessBlock( | 63 void ProcessCapture( |
64 const rtc::Optional<size_t>& external_echo_path_delay_estimate, | 64 const rtc::Optional<size_t>& external_echo_path_delay_estimate, |
65 const EchoPathVariability& echo_path_variability, | 65 const EchoPathVariability& echo_path_variability, |
66 bool capture_signal_saturation, | 66 bool capture_signal_saturation, |
67 const std::vector<std::vector<float>>& render, | 67 const RenderBuffer& render_buffer, |
68 std::vector<std::vector<float>>* capture) override; | 68 std::vector<std::vector<float>>* capture) override; |
69 | 69 |
70 // Updates the status on whether echo leakage is detected in the output of the | 70 // Updates the status on whether echo leakage is detected in the output of the |
71 // echo remover. | 71 // echo remover. |
72 void UpdateEchoLeakageStatus(bool leakage_detected) override { | 72 void UpdateEchoLeakageStatus(bool leakage_detected) override { |
73 echo_leakage_detected_ = leakage_detected; | 73 echo_leakage_detected_ = leakage_detected; |
74 } | 74 } |
75 | 75 |
76 private: | 76 private: |
77 static int instance_count_; | 77 static int instance_count_; |
78 const Aec3Fft fft_; | 78 const Aec3Fft fft_; |
79 std::unique_ptr<ApmDataDumper> data_dumper_; | 79 std::unique_ptr<ApmDataDumper> data_dumper_; |
80 const Aec3Optimization optimization_; | 80 const Aec3Optimization optimization_; |
81 const int sample_rate_hz_; | 81 const int sample_rate_hz_; |
82 Subtractor subtractor_; | 82 Subtractor subtractor_; |
83 SuppressionGain suppression_gain_; | 83 SuppressionGain suppression_gain_; |
84 ComfortNoiseGenerator cng_; | 84 ComfortNoiseGenerator cng_; |
85 SuppressionFilter suppression_filter_; | 85 SuppressionFilter suppression_filter_; |
86 PowerEchoModel power_echo_model_; | 86 PowerEchoModel power_echo_model_; |
87 FftBuffer X_buffer_; | 87 RenderBuffer X_buffer_; |
88 RenderSignalAnalyzer render_signal_analyzer_; | 88 RenderSignalAnalyzer render_signal_analyzer_; |
89 OutputSelector output_selector_; | 89 OutputSelector output_selector_; |
90 ResidualEchoEstimator residual_echo_estimator_; | 90 ResidualEchoEstimator residual_echo_estimator_; |
91 bool echo_leakage_detected_ = false; | 91 bool echo_leakage_detected_ = false; |
92 std::array<float, kBlockSize> x_old_; | |
93 AecState aec_state_; | 92 AecState aec_state_; |
94 EchoRemoverMetrics metrics_; | 93 EchoRemoverMetrics metrics_; |
95 | 94 |
96 RTC_DISALLOW_COPY_AND_ASSIGN(EchoRemoverImpl); | 95 RTC_DISALLOW_COPY_AND_ASSIGN(EchoRemoverImpl); |
97 }; | 96 }; |
98 | 97 |
99 int EchoRemoverImpl::instance_count_ = 0; | 98 int EchoRemoverImpl::instance_count_ = 0; |
100 | 99 |
101 EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz) | 100 EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz) |
102 : fft_(), | 101 : fft_(), |
103 data_dumper_( | 102 data_dumper_( |
104 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), | 103 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), |
105 optimization_(DetectOptimization()), | 104 optimization_(DetectOptimization()), |
106 sample_rate_hz_(sample_rate_hz), | 105 sample_rate_hz_(sample_rate_hz), |
107 subtractor_(data_dumper_.get(), optimization_), | 106 subtractor_(data_dumper_.get(), optimization_), |
108 suppression_gain_(optimization_), | 107 suppression_gain_(optimization_), |
109 cng_(optimization_), | 108 cng_(optimization_), |
110 suppression_filter_(sample_rate_hz_), | 109 suppression_filter_(sample_rate_hz_), |
111 X_buffer_(optimization_, | 110 X_buffer_(optimization_, |
111 NumBandsForRate(sample_rate_hz_), | |
112 std::max(subtractor_.MinFarendBufferLength(), | 112 std::max(subtractor_.MinFarendBufferLength(), |
113 power_echo_model_.MinFarendBufferLength()), | 113 power_echo_model_.MinFarendBufferLength()), |
114 subtractor_.NumBlocksInRenderSums()) { | 114 subtractor_.NumBlocksInRenderSums()) { |
115 RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); | 115 RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); |
116 x_old_.fill(0.f); | |
117 } | 116 } |
118 | 117 |
119 EchoRemoverImpl::~EchoRemoverImpl() = default; | 118 EchoRemoverImpl::~EchoRemoverImpl() = default; |
120 | 119 |
121 void EchoRemoverImpl::ProcessBlock( | 120 void EchoRemoverImpl::ProcessCapture( |
122 const rtc::Optional<size_t>& echo_path_delay_samples, | 121 const rtc::Optional<size_t>& echo_path_delay_samples, |
123 const EchoPathVariability& echo_path_variability, | 122 const EchoPathVariability& echo_path_variability, |
124 bool capture_signal_saturation, | 123 bool capture_signal_saturation, |
125 const std::vector<std::vector<float>>& render, | 124 const RenderBuffer& render_buffer, |
126 std::vector<std::vector<float>>* capture) { | 125 std::vector<std::vector<float>>* capture) { |
127 const std::vector<std::vector<float>>& x = render; | 126 const std::vector<std::vector<float>>& x = render_buffer.MostRecentBlock(); |
128 std::vector<std::vector<float>>* y = capture; | 127 std::vector<std::vector<float>>* y = capture; |
129 | 128 |
130 RTC_DCHECK(y); | 129 RTC_DCHECK(y); |
131 RTC_DCHECK_EQ(x.size(), NumBandsForRate(sample_rate_hz_)); | 130 RTC_DCHECK_EQ(x.size(), NumBandsForRate(sample_rate_hz_)); |
132 RTC_DCHECK_EQ(y->size(), NumBandsForRate(sample_rate_hz_)); | 131 RTC_DCHECK_EQ(y->size(), NumBandsForRate(sample_rate_hz_)); |
133 RTC_DCHECK_EQ(x[0].size(), kBlockSize); | 132 RTC_DCHECK_EQ(x[0].size(), kBlockSize); |
134 RTC_DCHECK_EQ((*y)[0].size(), kBlockSize); | 133 RTC_DCHECK_EQ((*y)[0].size(), kBlockSize); |
135 const std::vector<float>& x0 = x[0]; | 134 const std::vector<float>& x0 = x[0]; |
136 std::vector<float>& y0 = (*y)[0]; | 135 std::vector<float>& y0 = (*y)[0]; |
137 | 136 |
138 data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize, &y0[0], | 137 data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize, &y0[0], |
139 LowestBandRate(sample_rate_hz_), 1); | 138 LowestBandRate(sample_rate_hz_), 1); |
140 data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize, &x0[0], | 139 data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize, &x0[0], |
141 LowestBandRate(sample_rate_hz_), 1); | 140 LowestBandRate(sample_rate_hz_), 1); |
142 | 141 |
143 aec_state_.UpdateCaptureSaturation(capture_signal_saturation); | 142 aec_state_.UpdateCaptureSaturation(capture_signal_saturation); |
144 | 143 |
145 if (echo_path_variability.AudioPathChanged()) { | 144 if (echo_path_variability.AudioPathChanged()) { |
146 subtractor_.HandleEchoPathChange(echo_path_variability); | 145 subtractor_.HandleEchoPathChange(echo_path_variability); |
147 power_echo_model_.HandleEchoPathChange(echo_path_variability); | |
peah-webrtc
2017/03/30 05:36:56
I removed this since it caused a build error, and
| |
148 residual_echo_estimator_.HandleEchoPathChange(echo_path_variability); | 146 residual_echo_estimator_.HandleEchoPathChange(echo_path_variability); |
149 } | 147 } |
150 | 148 |
151 std::array<float, kFftLengthBy2Plus1> Y2; | 149 std::array<float, kFftLengthBy2Plus1> Y2; |
152 std::array<float, kFftLengthBy2Plus1> S2_power; | 150 std::array<float, kFftLengthBy2Plus1> S2_power; |
153 std::array<float, kFftLengthBy2Plus1> R2; | 151 std::array<float, kFftLengthBy2Plus1> R2; |
154 std::array<float, kFftLengthBy2Plus1> S2_linear; | 152 std::array<float, kFftLengthBy2Plus1> S2_linear; |
155 std::array<float, kFftLengthBy2Plus1> G; | 153 std::array<float, kFftLengthBy2Plus1> G; |
156 FftData X; | |
157 FftData Y; | 154 FftData Y; |
158 FftData comfort_noise; | 155 FftData comfort_noise; |
159 FftData high_band_comfort_noise; | 156 FftData high_band_comfort_noise; |
160 SubtractorOutput subtractor_output; | 157 SubtractorOutput subtractor_output; |
161 FftData& E_main = subtractor_output.E_main; | 158 FftData& E_main = subtractor_output.E_main; |
162 auto& E2_main = subtractor_output.E2_main; | 159 auto& E2_main = subtractor_output.E2_main; |
163 auto& E2_shadow = subtractor_output.E2_shadow; | 160 auto& E2_shadow = subtractor_output.E2_shadow; |
164 auto& e_main = subtractor_output.e_main; | 161 auto& e_main = subtractor_output.e_main; |
165 auto& e_shadow = subtractor_output.e_shadow; | 162 auto& e_shadow = subtractor_output.e_shadow; |
166 | 163 |
167 // Update the render signal buffer. | |
168 fft_.PaddedFft(x0, x_old_, &X); | |
169 X_buffer_.Insert(X); | |
170 | |
171 // Analyze the render signal. | 164 // Analyze the render signal. |
172 render_signal_analyzer_.Update(X_buffer_, aec_state_.FilterDelay()); | 165 render_signal_analyzer_.Update(render_buffer, aec_state_.FilterDelay()); |
173 | 166 |
174 // Perform linear echo cancellation. | 167 // Perform linear echo cancellation. |
175 subtractor_.Process(X_buffer_, y0, render_signal_analyzer_, | 168 subtractor_.Process(render_buffer, y0, render_signal_analyzer_, |
176 aec_state_.SaturatedCapture(), &subtractor_output); | 169 aec_state_.SaturatedCapture(), &subtractor_output); |
177 | 170 |
178 // Compute spectra. | 171 // Compute spectra. |
179 fft_.ZeroPaddedFft(y0, &Y); | 172 fft_.ZeroPaddedFft(y0, &Y); |
180 LinearEchoPower(E_main, Y, &S2_linear); | 173 LinearEchoPower(E_main, Y, &S2_linear); |
181 Y.Spectrum(optimization_, &Y2); | 174 Y.Spectrum(optimization_, &Y2); |
182 | 175 |
183 // Update the AEC state information. | 176 // Update the AEC state information. |
184 aec_state_.Update(subtractor_.FilterFrequencyResponse(), | 177 aec_state_.Update(subtractor_.FilterFrequencyResponse(), |
185 echo_path_delay_samples, X_buffer_, E2_main, E2_shadow, Y2, | 178 echo_path_delay_samples, render_buffer, E2_main, E2_shadow, |
186 x0, echo_path_variability, echo_leakage_detected_); | 179 Y2, x0, echo_path_variability, echo_leakage_detected_); |
187 | 180 |
188 // Use the power model to estimate the echo. | 181 // Use the power model to estimate the echo. |
189 power_echo_model_.EstimateEcho(X_buffer_, Y2, aec_state_, &S2_power); | 182 // TODO(peah): Remove in upcoming CL. |
183 // power_echo_model_.EstimateEcho(render_buffer, Y2, aec_state_, &S2_power); | |
peah-webrtc
2017/03/30 05:36:56
This will be removed in the next CL.
| |
190 | 184 |
191 // Choose the linear output. | 185 // Choose the linear output. |
192 output_selector_.FormLinearOutput(e_main, y0); | 186 output_selector_.FormLinearOutput(e_main, y0); |
193 data_dumper_->DumpWav("aec3_output_linear", kBlockSize, &y0[0], | 187 data_dumper_->DumpWav("aec3_output_linear", kBlockSize, &y0[0], |
194 LowestBandRate(sample_rate_hz_), 1); | 188 LowestBandRate(sample_rate_hz_), 1); |
195 const auto& E2 = output_selector_.UseSubtractorOutput() ? E2_main : Y2; | 189 const auto& E2 = output_selector_.UseSubtractorOutput() ? E2_main : Y2; |
196 | 190 |
197 // Estimate the residual echo power. | 191 // Estimate the residual echo power. |
198 residual_echo_estimator_.Estimate( | 192 residual_echo_estimator_.Estimate( |
199 output_selector_.UseSubtractorOutput(), aec_state_, X_buffer_, | 193 output_selector_.UseSubtractorOutput(), aec_state_, render_buffer, |
200 subtractor_.FilterFrequencyResponse(), E2_main, E2_shadow, S2_linear, | 194 subtractor_.FilterFrequencyResponse(), E2_main, E2_shadow, S2_linear, |
201 S2_power, Y2, &R2); | 195 S2_power, Y2, &R2); |
202 | 196 |
203 // Estimate the comfort noise. | 197 // Estimate the comfort noise. |
204 cng_.Compute(aec_state_, Y2, &comfort_noise, &high_band_comfort_noise); | 198 cng_.Compute(aec_state_, Y2, &comfort_noise, &high_band_comfort_noise); |
205 | 199 |
206 // Detect basic doubletalk. | 200 // Detect basic doubletalk. |
207 const bool doubletalk = BlockPower(e_shadow) < BlockPower(e_main); | 201 const bool doubletalk = BlockPower(e_shadow) < BlockPower(e_main); |
208 | 202 |
209 // A choose and apply echo suppression gain. | 203 // A choose and apply echo suppression gain. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 aec_state_.SaturatedCapture() ? 1 : 0); | 243 aec_state_.SaturatedCapture() ? 1 : 0); |
250 } | 244 } |
251 | 245 |
252 } // namespace | 246 } // namespace |
253 | 247 |
254 EchoRemover* EchoRemover::Create(int sample_rate_hz) { | 248 EchoRemover* EchoRemover::Create(int sample_rate_hz) { |
255 return new EchoRemoverImpl(sample_rate_hz); | 249 return new EchoRemoverImpl(sample_rate_hz); |
256 } | 250 } |
257 | 251 |
258 } // namespace webrtc | 252 } // namespace webrtc |
OLD | NEW |