AEC3: Average the spectrum of multiple nearend frames in the suppressor.

Reduce noise of the nearend spectrum estimation by averaging multiple
frames.

Bug: webrtc:9420,chromium:853699
Change-Id: Iad7e68b1209a369e263b2d892791943e42bfbb3f
Reviewed-on: https://webrtc-review.googlesource.com/83960
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23655}
This commit is contained in:
Gustaf Ullberg
2018-06-19 12:31:33 +02:00
committed by Commit Bot
parent 5d848f3ad6
commit 8406c43795
7 changed files with 123 additions and 2 deletions

View File

@ -69,6 +69,8 @@ rtc_static_library("aec3") {
"matched_filter_lag_aggregator.h",
"matrix_buffer.cc",
"matrix_buffer.h",
"moving_average.cc",
"moving_average.h",
"render_buffer.cc",
"render_buffer.h",
"render_delay_buffer.cc",

View File

@ -41,6 +41,11 @@ bool EnableReverbModelling() {
return !field_trial::IsEnabled("WebRTC-Aec3ReverbModellingKillSwitch");
}
bool EnableSuppressorNearendAveraging() {
return !field_trial::IsEnabled(
"WebRTC-Aec3SuppressorNearendAveragingKillSwitch");
}
// Method for adjusting config parameter dependencies..
EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
EchoCanceller3Config adjusted_cfg = config;
@ -89,6 +94,10 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
adjusted_cfg.ep_strength.reverb_based_on_render = false;
}
if (!EnableSuppressorNearendAveraging()) {
adjusted_cfg.suppressor.nearend_average_blocks = 1;
}
return adjusted_cfg;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_processing/aec3/moving_average.h"
#include <algorithm>
#include <functional>
namespace webrtc {
namespace aec3 {
MovingAverage::MovingAverage(size_t num_elem, size_t mem_len)
: num_elem_(num_elem),
mem_len_(mem_len - 1),
scaling_(1.0f / static_cast<float>(mem_len)),
memory_(num_elem * mem_len_, 0.f),
mem_index_(0) {
RTC_DCHECK(num_elem_ > 0);
RTC_DCHECK(mem_len > 0);
}
MovingAverage::~MovingAverage() = default;
void MovingAverage::Average(rtc::ArrayView<const float> input,
rtc::ArrayView<float> output) {
RTC_DCHECK(input.size() == num_elem_);
RTC_DCHECK(output.size() == num_elem_);
// Sum all contributions.
std::copy(input.begin(), input.end(), output.begin());
for (auto i = memory_.begin(); i < memory_.end(); i += num_elem_) {
std::transform(i, i + num_elem_, output.begin(), output.begin(),
std::plus<float>());
}
// Divide by mem_len_.
for (float& o : output) {
o *= scaling_;
}
// Update memory.
if (mem_len_ > 0) {
std::copy(input.begin(), input.end(),
memory_.begin() + mem_index_ * num_elem_);
mem_index_ = (mem_index_ + 1) % mem_len_;
}
}
} // namespace aec3
} // namespace webrtc

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_PROCESSING_AEC3_MOVING_AVERAGE_H_
#define MODULES_AUDIO_PROCESSING_AEC3_MOVING_AVERAGE_H_
#include <vector>
#include "api/array_view.h"
namespace webrtc {
namespace aec3 {
class MovingAverage {
public:
// Creates an instance of MovingAverage that accepts inputs of length num_elem
// and averages over mem_len inputs.
MovingAverage(size_t num_elem, size_t mem_len);
~MovingAverage();
// Computes the average of input and mem_len-1 previous inputs and stores the
// result in output.
void Average(rtc::ArrayView<const float> input, rtc::ArrayView<float> output);
private:
const size_t num_elem_;
const size_t mem_len_;
const float scaling_;
std::vector<float> memory_;
size_t mem_index_;
};
} // namespace aec3
} // namespace webrtc
#endif // MODULES_AUDIO_PROCESSING_AEC3_MOVING_AVERAGE_H_

View File

@ -20,6 +20,7 @@
#include <functional>
#include <numeric>
#include "modules/audio_processing/aec3/moving_average.h"
#include "modules/audio_processing/aec3/vector_math.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/atomicops.h"
@ -386,7 +387,9 @@ SuppressionGain::SuppressionGain(const EchoCanceller3Config& config,
static_cast<int>(config_.filter.config_change_duration_blocks)),
coherence_gain_(sample_rate_hz,
config_.suppressor.bands_with_reliable_coherence),
enable_transparency_improvements_(EnableTransparencyImprovements()) {
enable_transparency_improvements_(EnableTransparencyImprovements()),
moving_average_(kFftLengthBy2Plus1,
config.suppressor.nearend_average_blocks) {
RTC_DCHECK_LT(0, state_change_duration_blocks_);
one_by_state_change_duration_blocks_ = 1.f / state_change_duration_blocks_;
last_gain_.fill(1.f);
@ -413,11 +416,14 @@ void SuppressionGain::GetGain(
RTC_DCHECK(high_bands_gain);
RTC_DCHECK(low_band_gain);
std::array<float, kFftLengthBy2Plus1> nearend_average;
moving_average_.Average(nearend_spectrum, nearend_average);
// Compute gain for the lower band.
bool low_noise_render = low_render_detector_.Detect(render);
const absl::optional<int> narrow_peak_band =
render_signal_analyzer.NarrowPeakBand();
LowerBandGain(low_noise_render, aec_state, nearend_spectrum, echo_spectrum,
LowerBandGain(low_noise_render, aec_state, nearend_average, echo_spectrum,
comfort_noise_spectrum, low_band_gain);
// Adjust the gain for bands where the coherence indicates not echo.

View File

@ -18,6 +18,7 @@
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/aec_state.h"
#include "modules/audio_processing/aec3/coherence_gain.h"
#include "modules/audio_processing/aec3/moving_average.h"
#include "modules/audio_processing/aec3/render_signal_analyzer.h"
#include "rtc_base/constructormagic.h"
@ -85,6 +86,7 @@ class SuppressionGain {
int initial_state_change_counter_ = 0;
CoherenceGain coherence_gain_;
const bool enable_transparency_improvements_;
aec3::MovingAverage moving_average_;
RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
};