Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: webrtc/modules/audio_processing/aec3/suppression_gain.cc

Issue 2980493002: Add adaptive notch filter to remove narrowband echo components in AEC3 (Closed)
Patch Set: Fixed build error in debug mode Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 10
11 #include "webrtc/modules/audio_processing/aec3/suppression_gain.h" 11 #include "webrtc/modules/audio_processing/aec3/suppression_gain.h"
12 12
13 #include "webrtc/typedefs.h" 13 #include "webrtc/typedefs.h"
14 #if defined(WEBRTC_ARCH_X86_FAMILY) 14 #if defined(WEBRTC_ARCH_X86_FAMILY)
15 #include <emmintrin.h> 15 #include <emmintrin.h>
16 #endif 16 #endif
17 #include <math.h> 17 #include <math.h>
18 #include <algorithm> 18 #include <algorithm>
19 #include <functional> 19 #include <functional>
20 #include <numeric> 20 #include <numeric>
21 21
22 #include "webrtc/modules/audio_processing/aec3/vector_math.h" 22 #include "webrtc/modules/audio_processing/aec3/vector_math.h"
23 #include "webrtc/rtc_base/checks.h" 23 #include "webrtc/rtc_base/checks.h"
24 24
25 namespace webrtc { 25 namespace webrtc {
26 namespace { 26 namespace {
27 27
28 // Reduce gain to avoid narrow band echo leakage.
29 void NarrowBandAttenuation(int narrow_bin,
30 std::array<float, kFftLengthBy2Plus1>* gain) {
31 const int upper_bin =
32 std::min(narrow_bin + 6, static_cast<int>(kFftLengthBy2Plus1 - 1));
33 for (int k = std::max(0, narrow_bin - 6); k <= upper_bin; ++k) {
34 (*gain)[k] = std::min((*gain)[k], 0.001f);
35 }
36 }
37
28 // Adjust the gains according to the presence of known external filters. 38 // Adjust the gains according to the presence of known external filters.
29 void AdjustForExternalFilters(std::array<float, kFftLengthBy2Plus1>* gain) { 39 void AdjustForExternalFilters(std::array<float, kFftLengthBy2Plus1>* gain) {
30 // Limit the low frequency gains to avoid the impact of the high-pass filter 40 // Limit the low frequency gains to avoid the impact of the high-pass filter
31 // on the lower-frequency gain influencing the overall achieved gain. 41 // on the lower-frequency gain influencing the overall achieved gain.
32 (*gain)[0] = (*gain)[1] = std::min((*gain)[1], (*gain)[2]); 42 (*gain)[0] = (*gain)[1] = std::min((*gain)[1], (*gain)[2]);
33 43
34 // Limit the high frequency gains to avoid the impact of the anti-aliasing 44 // Limit the high frequency gains to avoid the impact of the anti-aliasing
35 // filter on the upper-frequency gains influencing the overall achieved 45 // filter on the upper-frequency gains influencing the overall achieved
36 // gain. TODO(peah): Update this when new anti-aliasing filters are 46 // gain. TODO(peah): Update this when new anti-aliasing filters are
37 // implemented. 47 // implemented.
38 constexpr size_t kAntiAliasingImpactLimit = (64 * 2000) / 8000; 48 constexpr size_t kAntiAliasingImpactLimit = (64 * 2000) / 8000;
39 const float min_upper_gain = (*gain)[kAntiAliasingImpactLimit]; 49 const float min_upper_gain = (*gain)[kAntiAliasingImpactLimit];
40 std::for_each( 50 std::for_each(
41 gain->begin() + kAntiAliasingImpactLimit, gain->end() - 1, 51 gain->begin() + kAntiAliasingImpactLimit, gain->end() - 1,
42 [min_upper_gain](float& a) { a = std::min(a, min_upper_gain); }); 52 [min_upper_gain](float& a) { a = std::min(a, min_upper_gain); });
43 (*gain)[kFftLengthBy2] = (*gain)[kFftLengthBy2Minus1]; 53 (*gain)[kFftLengthBy2] = (*gain)[kFftLengthBy2Minus1];
44 } 54 }
45 55
46 // Computes the gain to apply for the bands beyond the first band. 56 // Computes the gain to apply for the bands beyond the first band.
47 float UpperBandsGain( 57 float UpperBandsGain(
58 const rtc::Optional<int>& narrow_peak_band,
48 bool saturated_echo, 59 bool saturated_echo,
49 const std::vector<std::vector<float>>& render, 60 const std::vector<std::vector<float>>& render,
50 const std::array<float, kFftLengthBy2Plus1>& low_band_gain) { 61 const std::array<float, kFftLengthBy2Plus1>& low_band_gain) {
51 RTC_DCHECK_LT(0, render.size()); 62 RTC_DCHECK_LT(0, render.size());
52 if (render.size() == 1) { 63 if (render.size() == 1) {
53 return 1.f; 64 return 1.f;
54 } 65 }
55 66
67 if (narrow_peak_band &&
68 (*narrow_peak_band > static_cast<int>(kFftLengthBy2Plus1 - 10))) {
69 return 0.001f;
70 }
71
56 constexpr size_t kLowBandGainLimit = kFftLengthBy2 / 2; 72 constexpr size_t kLowBandGainLimit = kFftLengthBy2 / 2;
57 const float gain_below_8_khz = *std::min_element( 73 const float gain_below_8_khz = *std::min_element(
58 low_band_gain.begin() + kLowBandGainLimit, low_band_gain.end()); 74 low_band_gain.begin() + kLowBandGainLimit, low_band_gain.end());
59 75
60 // Always attenuate the upper bands when there is saturated echo. 76 // Always attenuate the upper bands when there is saturated echo.
61 if (saturated_echo) { 77 if (saturated_echo) {
62 return std::min(0.001f, gain_below_8_khz); 78 return std::min(0.001f, gain_below_8_khz);
63 } 79 }
64 80
65 // Compute the upper and lower band energies. 81 // Compute the upper and lower band energies.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 for (size_t k = 1; k < gain.size() - 1; ++k) { 202 for (size_t k = 1; k < gain.size() - 1; ++k) {
187 (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]); 203 (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]);
188 } 204 }
189 } 205 }
190 206
191 } // namespace 207 } // namespace
192 208
193 // TODO(peah): Add further optimizations, in particular for the divisions. 209 // TODO(peah): Add further optimizations, in particular for the divisions.
194 void SuppressionGain::LowerBandGain( 210 void SuppressionGain::LowerBandGain(
195 bool low_noise_render, 211 bool low_noise_render,
212 const rtc::Optional<int>& narrow_peak_band,
196 bool saturated_echo, 213 bool saturated_echo,
197 const std::array<float, kFftLengthBy2Plus1>& nearend, 214 const std::array<float, kFftLengthBy2Plus1>& nearend,
198 const std::array<float, kFftLengthBy2Plus1>& echo, 215 const std::array<float, kFftLengthBy2Plus1>& echo,
199 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, 216 const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
200 std::array<float, kFftLengthBy2Plus1>* gain) { 217 std::array<float, kFftLengthBy2Plus1>* gain) {
201 // Count the number of blocks since saturation. 218 // Count the number of blocks since saturation.
202 no_saturation_counter_ = saturated_echo ? 0 : no_saturation_counter_ + 1; 219 no_saturation_counter_ = saturated_echo ? 0 : no_saturation_counter_ + 1;
203 220
204 // Precompute 1/echo (note that when the echo is zero, the precomputed value 221 // Precompute 1/echo (note that when the echo is zero, the precomputed value
205 // is never used). 222 // is never used).
(...skipping 25 matching lines...) Expand all
231 248
232 // Iteratively compute the gain required to attenuate the echo to a non 249 // Iteratively compute the gain required to attenuate the echo to a non
233 // noticeable level. 250 // noticeable level.
234 gain->fill(0.f); 251 gain->fill(0.f);
235 for (int k = 0; k < 2; ++k) { 252 for (int k = 0; k < 2; ++k) {
236 std::array<float, kFftLengthBy2Plus1> masker; 253 std::array<float, kFftLengthBy2Plus1> masker;
237 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker); 254 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker);
238 GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker, 255 GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker,
239 min_gain, max_gain, one_by_echo, gain); 256 min_gain, max_gain, one_by_echo, gain);
240 AdjustForExternalFilters(gain); 257 AdjustForExternalFilters(gain);
258 if (narrow_peak_band) {
259 NarrowBandAttenuation(*narrow_peak_band, gain);
260 }
241 } 261 }
242 262
243 // Update the allowed maximum gain increase. 263 // Update the allowed maximum gain increase.
244 UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_, 264 UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_,
245 echo, last_gain_, *gain, &gain_increase_); 265 echo, last_gain_, *gain, &gain_increase_);
246 266
247 // Store data required for the gain computation of the next block. 267 // Store data required for the gain computation of the next block.
248 std::copy(echo.begin(), echo.end(), last_echo_.begin()); 268 std::copy(echo.begin(), echo.end(), last_echo_.begin());
249 std::copy(gain->begin(), gain->end(), last_gain_.begin()); 269 std::copy(gain->begin(), gain->end(), last_gain_.begin());
250 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_); 270 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_);
251 aec3::VectorMath(optimization_).Sqrt(*gain); 271 aec3::VectorMath(optimization_).Sqrt(*gain);
252 } 272 }
253 273
254 SuppressionGain::SuppressionGain(Aec3Optimization optimization) 274 SuppressionGain::SuppressionGain(Aec3Optimization optimization)
255 : optimization_(optimization) { 275 : optimization_(optimization) {
256 last_gain_.fill(1.f); 276 last_gain_.fill(1.f);
257 last_masker_.fill(0.f); 277 last_masker_.fill(0.f);
258 gain_increase_.fill(1.f); 278 gain_increase_.fill(1.f);
259 last_echo_.fill(0.f); 279 last_echo_.fill(0.f);
260 } 280 }
261 281
262 void SuppressionGain::GetGain( 282 void SuppressionGain::GetGain(
263 const std::array<float, kFftLengthBy2Plus1>& nearend, 283 const std::array<float, kFftLengthBy2Plus1>& nearend,
264 const std::array<float, kFftLengthBy2Plus1>& echo, 284 const std::array<float, kFftLengthBy2Plus1>& echo,
265 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, 285 const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
286 const RenderSignalAnalyzer& render_signal_analyzer,
266 bool saturated_echo, 287 bool saturated_echo,
267 const std::vector<std::vector<float>>& render, 288 const std::vector<std::vector<float>>& render,
268 bool force_zero_gain, 289 bool force_zero_gain,
269 float* high_bands_gain, 290 float* high_bands_gain,
270 std::array<float, kFftLengthBy2Plus1>* low_band_gain) { 291 std::array<float, kFftLengthBy2Plus1>* low_band_gain) {
271 RTC_DCHECK(high_bands_gain); 292 RTC_DCHECK(high_bands_gain);
272 RTC_DCHECK(low_band_gain); 293 RTC_DCHECK(low_band_gain);
273 294
274 if (force_zero_gain) { 295 if (force_zero_gain) {
275 last_gain_.fill(0.f); 296 last_gain_.fill(0.f);
276 std::copy(comfort_noise.begin(), comfort_noise.end(), last_masker_.begin()); 297 std::copy(comfort_noise.begin(), comfort_noise.end(), last_masker_.begin());
277 low_band_gain->fill(0.f); 298 low_band_gain->fill(0.f);
278 gain_increase_.fill(1.f); 299 gain_increase_.fill(1.f);
279 *high_bands_gain = 0.f; 300 *high_bands_gain = 0.f;
280 return; 301 return;
281 } 302 }
282 303
283 bool low_noise_render = low_render_detector_.Detect(render); 304 bool low_noise_render = low_render_detector_.Detect(render);
284 305
285 // Compute gain for the lower band. 306 // Compute gain for the lower band.
286 LowerBandGain(low_noise_render, saturated_echo, nearend, echo, comfort_noise, 307 const rtc::Optional<int> narrow_peak_band =
287 low_band_gain); 308 render_signal_analyzer.NarrowPeakBand();
309 LowerBandGain(low_noise_render, narrow_peak_band, saturated_echo, nearend,
310 echo, comfort_noise, low_band_gain);
288 311
289 // Compute the gain for the upper bands. 312 // Compute the gain for the upper bands.
290 *high_bands_gain = UpperBandsGain(saturated_echo, render, *low_band_gain); 313 *high_bands_gain =
314 UpperBandsGain(narrow_peak_band, saturated_echo, render, *low_band_gain);
291 } 315 }
292 316
293 // Detects when the render signal can be considered to have low power and 317 // Detects when the render signal can be considered to have low power and
294 // consist of stationary noise. 318 // consist of stationary noise.
295 bool SuppressionGain::LowNoiseRenderDetector::Detect( 319 bool SuppressionGain::LowNoiseRenderDetector::Detect(
296 const std::vector<std::vector<float>>& render) { 320 const std::vector<std::vector<float>>& render) {
297 float x2_sum = 0.f; 321 float x2_sum = 0.f;
298 float x2_max = 0.f; 322 float x2_max = 0.f;
299 for (auto x_k : render[0]) { 323 for (auto x_k : render[0]) {
300 const float x2 = x_k * x_k; 324 const float x2 = x_k * x_k;
301 x2_sum += x2; 325 x2_sum += x2;
302 x2_max = std::max(x2_max, x2); 326 x2_max = std::max(x2_max, x2);
303 } 327 }
304 328
305 constexpr float kThreshold = 50.f * 50.f * 64.f; 329 constexpr float kThreshold = 50.f * 50.f * 64.f;
306 const bool low_noise_render = 330 const bool low_noise_render =
307 average_power_ < kThreshold && x2_max < 3 * average_power_; 331 average_power_ < kThreshold && x2_max < 3 * average_power_;
308 average_power_ = average_power_ * 0.9f + x2_sum * 0.1f; 332 average_power_ = average_power_ * 0.9f + x2_sum * 0.1f;
309 return low_noise_render; 333 return low_noise_render;
310 } 334 }
311 335
312 } // namespace webrtc 336 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698