AEC3: Computation of comfort noise gains from suppression gains
This change corrects the computation of the comfort noise gains. Previously the comfort noise gain of band k, CG_k, was computed from suppression gain of band k, SG_k, as: CG_k = 1 - SG_k But since the two signals are uncorrelated (the comfort noise is randomly generated), the correct gain to maintain power is: CG_k = sqrt(1 - SG_k^2). Bug: webrtc:9967,chromium:902262 Change-Id: I393495742163d5e658bca4ab2f7a5067ab15af01 Reviewed-on: https://webrtc-review.googlesource.com/c/109580 Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org> Reviewed-by: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25525}
This commit is contained in:
parent
34fc346a0c
commit
83b00f020e
@ -178,7 +178,7 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
|
||||
subtractor_(config, data_dumper_.get(), optimization_),
|
||||
suppression_gain_(config_, optimization_, sample_rate_hz),
|
||||
cng_(optimization_),
|
||||
suppression_filter_(sample_rate_hz_),
|
||||
suppression_filter_(optimization_, sample_rate_hz_),
|
||||
render_signal_analyzer_(config_),
|
||||
residual_echo_estimator_(config_),
|
||||
aec_state_(config_) {
|
||||
|
||||
@ -11,10 +11,12 @@
|
||||
#include "modules/audio_processing/aec3/suppression_filter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
#include "modules/audio_processing/aec3/vector_math.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
|
||||
@ -58,8 +60,10 @@ const float kSqrtHanning[kFftLength] = {
|
||||
|
||||
} // namespace
|
||||
|
||||
SuppressionFilter::SuppressionFilter(int sample_rate_hz)
|
||||
: sample_rate_hz_(sample_rate_hz),
|
||||
SuppressionFilter::SuppressionFilter(Aec3Optimization optimization,
|
||||
int sample_rate_hz)
|
||||
: optimization_(optimization),
|
||||
sample_rate_hz_(sample_rate_hz),
|
||||
fft_(),
|
||||
e_output_old_(NumBandsForRate(sample_rate_hz_)) {
|
||||
RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
|
||||
@ -89,18 +93,17 @@ void SuppressionFilter::ApplyGain(
|
||||
std::transform(suppression_gain.begin(), suppression_gain.end(), E.im.begin(),
|
||||
E.im.begin(), std::multiplies<float>());
|
||||
|
||||
// Compute and add the comfort noise.
|
||||
std::array<float, kFftLengthBy2Plus1> scaled_comfort_noise;
|
||||
// Comfort noise gain is sqrt(1-g^2), where g is the suppression gain.
|
||||
std::array<float, kFftLengthBy2Plus1> noise_gain;
|
||||
std::transform(suppression_gain.begin(), suppression_gain.end(),
|
||||
comfort_noise.re.begin(), scaled_comfort_noise.begin(),
|
||||
[](float a, float b) { return std::max(1.f - a, 0.f) * b; });
|
||||
std::transform(scaled_comfort_noise.begin(), scaled_comfort_noise.end(),
|
||||
E.re.begin(), E.re.begin(), std::plus<float>());
|
||||
std::transform(suppression_gain.begin(), suppression_gain.end(),
|
||||
comfort_noise.im.begin(), scaled_comfort_noise.begin(),
|
||||
[](float a, float b) { return std::max(1.f - a, 0.f) * b; });
|
||||
std::transform(scaled_comfort_noise.begin(), scaled_comfort_noise.end(),
|
||||
E.im.begin(), E.im.begin(), std::plus<float>());
|
||||
noise_gain.begin(), [](float g) { return 1.f - g * g; });
|
||||
aec3::VectorMath(optimization_).Sqrt(noise_gain);
|
||||
|
||||
// Scale and add the comfort noise.
|
||||
for (size_t k = 0; k < kFftLengthBy2Plus1; k++) {
|
||||
E.re[k] += noise_gain[k] * comfort_noise.re[k];
|
||||
E.im[k] += noise_gain[k] * comfort_noise.im[k];
|
||||
}
|
||||
|
||||
// Synthesis filterbank.
|
||||
std::array<float, kFftLength> e_extended;
|
||||
@ -134,7 +137,7 @@ void SuppressionFilter::ApplyGain(
|
||||
|
||||
// Scale and apply the noise to the signals.
|
||||
const float high_bands_noise_scaling =
|
||||
0.4f * std::max(1.f - high_bands_gain, 0.f);
|
||||
0.4f * std::sqrt(1.f - high_bands_gain * high_bands_gain);
|
||||
|
||||
std::transform(
|
||||
(*e)[1].begin(), (*e)[1].end(), time_domain_high_band_noise.begin(),
|
||||
|
||||
@ -24,7 +24,7 @@ namespace webrtc {
|
||||
|
||||
class SuppressionFilter {
|
||||
public:
|
||||
explicit SuppressionFilter(int sample_rate_hz);
|
||||
SuppressionFilter(Aec3Optimization optimization, int sample_rate_hz);
|
||||
~SuppressionFilter();
|
||||
void ApplyGain(const FftData& comfort_noise,
|
||||
const FftData& comfort_noise_high_bands,
|
||||
@ -34,6 +34,7 @@ class SuppressionFilter {
|
||||
std::vector<std::vector<float>>* e);
|
||||
|
||||
private:
|
||||
const Aec3Optimization optimization_;
|
||||
const int sample_rate_hz_;
|
||||
const OouraFft ooura_fft_;
|
||||
const Aec3Fft fft_;
|
||||
|
||||
@ -45,21 +45,21 @@ TEST(SuppressionFilter, NullOutput) {
|
||||
FftData E;
|
||||
std::array<float, kFftLengthBy2Plus1> gain;
|
||||
|
||||
EXPECT_DEATH(SuppressionFilter(16000).ApplyGain(cn, cn_high_bands, gain, 1.0f,
|
||||
E, nullptr),
|
||||
EXPECT_DEATH(SuppressionFilter(Aec3Optimization::kNone, 16000)
|
||||
.ApplyGain(cn, cn_high_bands, gain, 1.0f, E, nullptr),
|
||||
"");
|
||||
}
|
||||
|
||||
// Verifies the check for allowed sample rate.
|
||||
TEST(SuppressionFilter, ProperSampleRate) {
|
||||
EXPECT_DEATH(SuppressionFilter(16001), "");
|
||||
EXPECT_DEATH(SuppressionFilter(Aec3Optimization::kNone, 16001), "");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Verifies that no comfort noise is added when the gain is 1.
|
||||
TEST(SuppressionFilter, ComfortNoiseInUnityGain) {
|
||||
SuppressionFilter filter(48000);
|
||||
SuppressionFilter filter(Aec3Optimization::kNone, 48000);
|
||||
FftData cn;
|
||||
FftData cn_high_bands;
|
||||
std::array<float, kFftLengthBy2Plus1> gain;
|
||||
@ -89,7 +89,7 @@ TEST(SuppressionFilter, ComfortNoiseInUnityGain) {
|
||||
|
||||
// Verifies that the suppressor is able to suppress a signal.
|
||||
TEST(SuppressionFilter, SignalSuppression) {
|
||||
SuppressionFilter filter(48000);
|
||||
SuppressionFilter filter(Aec3Optimization::kNone, 48000);
|
||||
FftData cn;
|
||||
FftData cn_high_bands;
|
||||
std::array<float, kFftLengthBy2> e_old_;
|
||||
@ -131,7 +131,7 @@ TEST(SuppressionFilter, SignalSuppression) {
|
||||
// Verifies that the suppressor is able to pass through a desired signal while
|
||||
// applying suppressing for some frequencies.
|
||||
TEST(SuppressionFilter, SignalTransparency) {
|
||||
SuppressionFilter filter(48000);
|
||||
SuppressionFilter filter(Aec3Optimization::kNone, 48000);
|
||||
FftData cn;
|
||||
std::array<float, kFftLengthBy2> e_old_;
|
||||
Aec3Fft fft;
|
||||
@ -171,7 +171,7 @@ TEST(SuppressionFilter, SignalTransparency) {
|
||||
|
||||
// Verifies that the suppressor delay.
|
||||
TEST(SuppressionFilter, Delay) {
|
||||
SuppressionFilter filter(48000);
|
||||
SuppressionFilter filter(Aec3Optimization::kNone, 48000);
|
||||
FftData cn;
|
||||
FftData cn_high_bands;
|
||||
std::array<float, kFftLengthBy2> e_old_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user