AEC3: Added parametrization of the comfort noise floor
Bug: webrtc:8671
Change-Id: I2431b1dd8dbe35fc8742c0640c3b35166e8ef6b7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/171480
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30876}
diff --git a/api/audio/echo_canceller3_config.cc b/api/audio/echo_canceller3_config.cc
index 2438738..17af8f8 100644
--- a/api/audio/echo_canceller3_config.cc
+++ b/api/audio/echo_canceller3_config.cc
@@ -226,6 +226,8 @@
res = res & Limit(&c->echo_model.render_pre_window_size, 0, 100);
res = res & Limit(&c->echo_model.render_post_window_size, 0, 100);
+ res = res & Limit(&c->comfort_noise.noise_floor_dbfs, -200.f, 0.f);
+
res = res & Limit(&c->suppressor.nearend_average_blocks, 1, 5000);
res = res &
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index 523cf94..421b25b 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -154,6 +154,10 @@
size_t render_post_window_size = 1;
} echo_model;
+ struct ComfortNoise {
+ float noise_floor_dbfs = -96.03406f;
+ } comfort_noise;
+
struct Suppressor {
Suppressor();
Suppressor(const Suppressor& e);
diff --git a/api/audio/echo_canceller3_config_json.cc b/api/audio/echo_canceller3_config_json.cc
index 7734e32..06b8f27 100644
--- a/api/audio/echo_canceller3_config_json.cc
+++ b/api/audio/echo_canceller3_config_json.cc
@@ -312,6 +312,10 @@
&cfg.echo_model.render_post_window_size);
}
+ if (rtc::GetValueFromJsonObject(aec3_root, "comfort_noise", §ion)) {
+ ReadParam(section, "noise_floor_dbfs", &cfg.comfort_noise.noise_floor_dbfs);
+ }
+
Json::Value subsection;
if (rtc::GetValueFromJsonObject(aec3_root, "suppressor", §ion)) {
ReadParam(section, "nearend_average_blocks",
@@ -626,6 +630,10 @@
<< config.echo_model.render_post_window_size;
ost << "},";
+ ost << "\"comfort_noise\": {";
+ ost << "\"noise_floor_dbfs\": " << config.comfort_noise.noise_floor_dbfs;
+ ost << "},";
+
ost << "\"suppressor\": {";
ost << "\"nearend_average_blocks\": "
<< config.suppressor.nearend_average_blocks << ",";
diff --git a/api/audio/test/echo_canceller3_config_json_unittest.cc b/api/audio/test/echo_canceller3_config_json_unittest.cc
index f5c2675..b63f233 100644
--- a/api/audio/test/echo_canceller3_config_json_unittest.cc
+++ b/api/audio/test/echo_canceller3_config_json_unittest.cc
@@ -23,6 +23,7 @@
cfg.filter.refined.error_floor = 2.f;
cfg.filter.shadow_initial.length_blocks = 7u;
cfg.filter.coarse_initial.length_blocks = 3u;
+ cfg.comfort_noise.noise_floor_dbfs = 100.f;
cfg.suppressor.normal_tuning.mask_hf.enr_suppress = .5f;
cfg.suppressor.subband_nearend_detection.nearend_average_blocks = 3;
cfg.suppressor.subband_nearend_detection.subband1 = {1, 3};
@@ -51,6 +52,8 @@
cfg_transformed.filter.main.error_floor);
EXPECT_EQ(cfg.filter.refined.error_floor,
cfg_transformed.filter.refined.error_floor);
+ EXPECT_EQ(cfg.comfort_noise.noise_floor_dbfs,
+ cfg_transformed.comfort_noise.noise_floor_dbfs);
EXPECT_EQ(cfg.suppressor.normal_tuning.mask_hf.enr_suppress,
cfg_transformed.suppressor.normal_tuning.mask_hf.enr_suppress);
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.nearend_average_blocks,
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.cc b/modules/audio_processing/aec3/comfort_noise_generator.cc
index 16c4a2b..de5227c 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator.cc
@@ -31,6 +31,13 @@
namespace {
+// Computes the noise floor value that matches a WGN input of noise_floor_dbfs.
+float GetNoiseFloorFactor(float noise_floor_dbfs) {
+ // kdBfsNormalization = 20.f*log10(32768.f).
+ constexpr float kdBfsNormalization = 90.30899869919436f;
+ return 64.f * powf(10.f, (kdBfsNormalization + noise_floor_dbfs) * 0.1f);
+}
+
// Table of sqrt(2) * sin(2*pi*i/32).
constexpr float kSqrt2Sin[32] = {
+0.0000000f, +0.2758994f, +0.5411961f, +0.7856950f, +1.0000000f,
@@ -92,11 +99,13 @@
} // namespace
-ComfortNoiseGenerator::ComfortNoiseGenerator(Aec3Optimization optimization,
+ComfortNoiseGenerator::ComfortNoiseGenerator(const EchoCanceller3Config& config,
+ Aec3Optimization optimization,
size_t num_capture_channels)
: optimization_(optimization),
seed_(42),
num_capture_channels_(num_capture_channels),
+ noise_floor_(GetNoiseFloorFactor(config.comfort_noise.noise_floor_dbfs)),
N2_initial_(
std::make_unique<std::vector<std::array<float, kFftLengthBy2Plus1>>>(
num_capture_channels_)),
@@ -153,16 +162,13 @@
}
}
- // Limit the noise to a floor matching a WGN input of -96 dBFS.
- constexpr float kNoiseFloor = 17.1267f;
-
for (size_t ch = 0; ch < num_capture_channels_; ++ch) {
for (auto& n : N2_[ch]) {
- n = std::max(n, kNoiseFloor);
+ n = std::max(n, noise_floor_);
}
if (N2_initial_) {
for (auto& n : (*N2_initial_)[ch]) {
- n = std::max(n, kNoiseFloor);
+ n = std::max(n, noise_floor_);
}
}
}
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.h b/modules/audio_processing/aec3/comfort_noise_generator.h
index 776ed1b..16eaf355 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.h
+++ b/modules/audio_processing/aec3/comfort_noise_generator.h
@@ -41,7 +41,8 @@
// Generates the comfort noise.
class ComfortNoiseGenerator {
public:
- ComfortNoiseGenerator(Aec3Optimization optimization,
+ ComfortNoiseGenerator(const EchoCanceller3Config& config,
+ Aec3Optimization optimization,
size_t num_capture_channels);
ComfortNoiseGenerator() = delete;
~ComfortNoiseGenerator();
@@ -64,6 +65,7 @@
const Aec3Optimization optimization_;
uint32_t seed_;
const size_t num_capture_channels_;
+ const float noise_floor_;
std::unique_ptr<std::vector<std::array<float, kFftLengthBy2Plus1>>>
N2_initial_;
std::vector<std::array<float, kFftLengthBy2Plus1>> Y2_smoothed_;
diff --git a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
index 02c26cc..a9da175 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
@@ -13,6 +13,7 @@
#include <algorithm>
#include <numeric>
+#include "api/audio/echo_canceller3_config.h"
#include "modules/audio_processing/aec3/aec_state.h"
#include "rtc_base/random.h"
#include "rtc_base/system/arch.h"
@@ -33,8 +34,9 @@
TEST(ComfortNoiseGenerator, CorrectLevel) {
constexpr size_t kNumChannels = 5;
- ComfortNoiseGenerator cng(DetectOptimization(), kNumChannels);
- AecState aec_state(EchoCanceller3Config{}, kNumChannels);
+ EchoCanceller3Config config;
+ ComfortNoiseGenerator cng(config, DetectOptimization(), kNumChannels);
+ AecState aec_state(config, kNumChannels);
std::vector<std::array<float, kFftLengthBy2Plus1>> N2(kNumChannels);
std::vector<FftData> n_lower(kNumChannels);
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index 06f3b45..a3cd22f 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -200,7 +200,7 @@
optimization_,
sample_rate_hz,
num_capture_channels),
- cng_(optimization_, num_capture_channels_),
+ cng_(config_, optimization_, num_capture_channels_),
suppression_filter_(optimization_,
sample_rate_hz_,
num_capture_channels_),