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}
This commit is contained in:
@ -226,6 +226,8 @@ bool EchoCanceller3Config::Validate(EchoCanceller3Config* config) {
|
||||
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 &
|
||||
|
||||
@ -154,6 +154,10 @@ struct RTC_EXPORT EchoCanceller3Config {
|
||||
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);
|
||||
|
||||
@ -312,6 +312,10 @@ void Aec3ConfigFromJsonString(absl::string_view json_string,
|
||||
&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 @@ std::string Aec3ConfigToJsonString(const EchoCanceller3Config& config) {
|
||||
<< 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 << ",";
|
||||
|
||||
@ -23,6 +23,7 @@ TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
|
||||
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 @@ TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
|
||||
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,
|
||||
|
||||
@ -31,6 +31,13 @@ namespace webrtc {
|
||||
|
||||
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 @@ void GenerateComfortNoise(Aec3Optimization optimization,
|
||||
|
||||
} // 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 @@ void ComfortNoiseGenerator::Compute(
|
||||
}
|
||||
}
|
||||
|
||||
// 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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,8 @@ void EstimateComfortNoise(const std::array<float, kFftLengthBy2Plus1>& N2,
|
||||
// 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 @@ class ComfortNoiseGenerator {
|
||||
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_;
|
||||
|
||||
@ -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 @@ float Power(const FftData& N) {
|
||||
|
||||
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);
|
||||
|
||||
@ -200,7 +200,7 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
|
||||
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_),
|
||||
|
||||
Reference in New Issue
Block a user