Separated the NLP behavior in AEC3 for different echo estimates.
This CL separates the NLP gain computation for the different variants of echo estimation. This simplifies the setting of tuning parameters, with resulting transparency improvements and increased echo removal performance. Bug: webrtc:8359 Change-Id: I9b97064396fb6f6e2f418ce534573f68694390a1 Reviewed-on: https://webrtc-review.googlesource.com/7613 Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20209}
This commit is contained in:
parent
920b653c31
commit
c65ce78027
@ -92,6 +92,12 @@ class AecState {
|
||||
echo_audibility_.UpdateWithOutput(e);
|
||||
}
|
||||
|
||||
// Returns whether the echo subtractor can be used to determine the residual
|
||||
// echo.
|
||||
bool LinearEchoEstimate() const {
|
||||
return UsableLinearEstimate() && !HeadsetDetected();
|
||||
}
|
||||
|
||||
// Updates the aec state.
|
||||
void Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
|
||||
adaptive_filter_frequency_response,
|
||||
|
||||
@ -183,18 +183,17 @@ void EchoRemoverImpl::ProcessCapture(
|
||||
const auto& E2 = output_selector_.UseSubtractorOutput() ? E2_main : Y2;
|
||||
|
||||
// Estimate the residual echo power.
|
||||
residual_echo_estimator_.Estimate(output_selector_.UseSubtractorOutput(),
|
||||
aec_state_, render_buffer, S2_linear, Y2,
|
||||
residual_echo_estimator_.Estimate(aec_state_, render_buffer, S2_linear, Y2,
|
||||
&R2);
|
||||
|
||||
// Estimate the comfort noise.
|
||||
cng_.Compute(aec_state_, Y2, &comfort_noise, &high_band_comfort_noise);
|
||||
|
||||
// A choose and apply echo suppression gain.
|
||||
suppression_gain_.GetGain(E2, R2, cng_.NoiseSpectrum(),
|
||||
render_signal_analyzer_, aec_state_.SaturatedEcho(),
|
||||
x, aec_state_.ForcedZeroGain(), &high_bands_gain,
|
||||
&G);
|
||||
suppression_gain_.GetGain(
|
||||
E2, R2, cng_.NoiseSpectrum(), render_signal_analyzer_,
|
||||
aec_state_.SaturatedEcho(), x, aec_state_.ForcedZeroGain(),
|
||||
aec_state_.LinearEchoEstimate(), &high_bands_gain, &G);
|
||||
suppression_filter_.ApplyGain(comfort_noise, high_band_comfort_noise, G,
|
||||
high_bands_gain, y);
|
||||
|
||||
|
||||
@ -88,7 +88,6 @@ ResidualEchoEstimator::ResidualEchoEstimator(
|
||||
ResidualEchoEstimator::~ResidualEchoEstimator() = default;
|
||||
|
||||
void ResidualEchoEstimator::Estimate(
|
||||
bool using_subtractor_output,
|
||||
const AecState& aec_state,
|
||||
const RenderBuffer& render_buffer,
|
||||
const std::array<float, kFftLengthBy2Plus1>& S2_linear,
|
||||
@ -106,9 +105,8 @@ void ResidualEchoEstimator::Estimate(
|
||||
RenderNoisePower(render_buffer, &X2_noise_floor_, &X2_noise_floor_counter_);
|
||||
|
||||
// Estimate the residual echo power.
|
||||
const bool use_linear_echo_power =
|
||||
aec_state.UsableLinearEstimate() && using_subtractor_output;
|
||||
if (use_linear_echo_power && !aec_state.HeadsetDetected()) {
|
||||
|
||||
if (aec_state.LinearEchoEstimate()) {
|
||||
RTC_DCHECK(aec_state.FilterDelay());
|
||||
const int filter_delay = *aec_state.FilterDelay();
|
||||
LinearEstimate(S2_linear, aec_state.Erle(), filter_delay, R2);
|
||||
|
||||
@ -30,8 +30,7 @@ class ResidualEchoEstimator {
|
||||
const AudioProcessing::Config::EchoCanceller3& config);
|
||||
~ResidualEchoEstimator();
|
||||
|
||||
void Estimate(bool using_subtractor_output,
|
||||
const AecState& aec_state,
|
||||
void Estimate(const AecState& aec_state,
|
||||
const RenderBuffer& render_buffer,
|
||||
const std::array<float, kFftLengthBy2Plus1>& S2_linear,
|
||||
const std::array<float, kFftLengthBy2Plus1>& Y2,
|
||||
|
||||
@ -29,10 +29,9 @@ TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
|
||||
std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
|
||||
std::array<float, kFftLengthBy2Plus1> S2_linear;
|
||||
std::array<float, kFftLengthBy2Plus1> Y2;
|
||||
EXPECT_DEATH(
|
||||
ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{})
|
||||
.Estimate(true, aec_state, render_buffer, S2_linear, Y2, nullptr),
|
||||
"");
|
||||
EXPECT_DEATH(ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{})
|
||||
.Estimate(aec_state, render_buffer, S2_linear, Y2, nullptr),
|
||||
"");
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -87,7 +86,7 @@ TEST(ResidualEchoEstimator, BasicTest) {
|
||||
aec_state.Update(H2, h, rtc::Optional<size_t>(2), render_buffer, E2_main,
|
||||
Y2, x[0], s, false);
|
||||
|
||||
estimator.Estimate(true, aec_state, render_buffer, S2_linear, Y2, &R2);
|
||||
estimator.Estimate(aec_state, render_buffer, S2_linear, Y2, &R2);
|
||||
}
|
||||
std::for_each(R2.begin(), R2.end(),
|
||||
[&](float a) { EXPECT_NEAR(kLevel, a, 0.1f); });
|
||||
|
||||
@ -112,6 +112,7 @@ void UpdateMaxGainIncrease(
|
||||
const AudioProcessing::Config::EchoCanceller3& config,
|
||||
size_t no_saturation_counter,
|
||||
bool low_noise_render,
|
||||
bool linear_echo_estimate,
|
||||
const std::array<float, kFftLengthBy2Plus1>& last_echo,
|
||||
const std::array<float, kFftLengthBy2Plus1>& echo,
|
||||
const std::array<float, kFftLengthBy2Plus1>& last_gain,
|
||||
@ -125,7 +126,14 @@ void UpdateMaxGainIncrease(
|
||||
float min_decreasing;
|
||||
|
||||
auto& param = config.param.gain_updates;
|
||||
if (low_noise_render) {
|
||||
if (!linear_echo_estimate) {
|
||||
max_increasing = param.nonlinear.max_inc;
|
||||
max_decreasing = param.nonlinear.max_dec;
|
||||
rate_increasing = param.nonlinear.rate_inc;
|
||||
rate_decreasing = param.nonlinear.rate_dec;
|
||||
min_increasing = param.nonlinear.min_inc;
|
||||
min_decreasing = param.nonlinear.min_dec;
|
||||
} else if (low_noise_render) {
|
||||
max_increasing = param.low_noise.max_inc;
|
||||
max_decreasing = param.low_noise.max_dec;
|
||||
rate_increasing = param.low_noise.rate_inc;
|
||||
@ -168,6 +176,7 @@ void GainToNoAudibleEcho(
|
||||
const AudioProcessing::Config::EchoCanceller3& config,
|
||||
bool low_noise_render,
|
||||
bool saturated_echo,
|
||||
bool linear_echo_estimate,
|
||||
const std::array<float, kFftLengthBy2Plus1>& nearend,
|
||||
const std::array<float, kFftLengthBy2Plus1>& echo,
|
||||
const std::array<float, kFftLengthBy2Plus1>& masker,
|
||||
@ -175,10 +184,15 @@ void GainToNoAudibleEcho(
|
||||
const std::array<float, kFftLengthBy2Plus1>& max_gain,
|
||||
const std::array<float, kFftLengthBy2Plus1>& one_by_echo,
|
||||
std::array<float, kFftLengthBy2Plus1>* gain) {
|
||||
const float nearend_masking_margin =
|
||||
low_noise_render ? 0.3f
|
||||
: (saturated_echo ? config.param.gain_mask.m2
|
||||
: config.param.gain_mask.m3);
|
||||
float nearend_masking_margin = 0.f;
|
||||
if (linear_echo_estimate) {
|
||||
nearend_masking_margin = low_noise_render
|
||||
? 0.3f
|
||||
: (saturated_echo ? config.param.gain_mask.m2
|
||||
: config.param.gain_mask.m3);
|
||||
} else {
|
||||
nearend_masking_margin = config.param.gain_mask.m7;
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < gain->size(); ++k) {
|
||||
const float unity_gain_masker = std::max(nearend[k], masker[k]);
|
||||
@ -252,6 +266,7 @@ void SuppressionGain::LowerBandGain(
|
||||
bool low_noise_render,
|
||||
const rtc::Optional<int>& narrow_peak_band,
|
||||
bool saturated_echo,
|
||||
bool linear_echo_estimate,
|
||||
const std::array<float, kFftLengthBy2Plus1>& nearend,
|
||||
const std::array<float, kFftLengthBy2Plus1>& echo,
|
||||
const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
|
||||
@ -297,8 +312,9 @@ void SuppressionGain::LowerBandGain(
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
std::array<float, kFftLengthBy2Plus1> masker;
|
||||
MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker);
|
||||
GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend,
|
||||
echo, masker, min_gain, max_gain, one_by_echo, gain);
|
||||
GainToNoAudibleEcho(config_, low_noise_render, saturated_echo,
|
||||
linear_echo_estimate, nearend, echo, masker, min_gain,
|
||||
max_gain, one_by_echo, gain);
|
||||
AdjustForExternalFilters(gain);
|
||||
if (narrow_peak_band) {
|
||||
NarrowBandAttenuation(*narrow_peak_band, gain);
|
||||
@ -310,7 +326,8 @@ void SuppressionGain::LowerBandGain(
|
||||
|
||||
// Update the allowed maximum gain increase.
|
||||
UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render,
|
||||
last_echo_, echo, last_gain_, *gain, &gain_increase_);
|
||||
linear_echo_estimate, last_echo_, echo, last_gain_,
|
||||
*gain, &gain_increase_);
|
||||
|
||||
// Store data required for the gain computation of the next block.
|
||||
std::copy(echo.begin(), echo.end(), last_echo_.begin());
|
||||
@ -338,6 +355,7 @@ void SuppressionGain::GetGain(
|
||||
bool saturated_echo,
|
||||
const std::vector<std::vector<float>>& render,
|
||||
bool force_zero_gain,
|
||||
bool linear_echo_estimate,
|
||||
float* high_bands_gain,
|
||||
std::array<float, kFftLengthBy2Plus1>* low_band_gain) {
|
||||
RTC_DCHECK(high_bands_gain);
|
||||
@ -357,8 +375,9 @@ void SuppressionGain::GetGain(
|
||||
// Compute gain for the lower band.
|
||||
const rtc::Optional<int> narrow_peak_band =
|
||||
render_signal_analyzer.NarrowPeakBand();
|
||||
LowerBandGain(low_noise_render, narrow_peak_band, saturated_echo, nearend,
|
||||
echo, comfort_noise, low_band_gain);
|
||||
LowerBandGain(low_noise_render, narrow_peak_band, saturated_echo,
|
||||
linear_echo_estimate, nearend, echo, comfort_noise,
|
||||
low_band_gain);
|
||||
|
||||
// Compute the gain for the upper bands.
|
||||
*high_bands_gain =
|
||||
|
||||
@ -32,6 +32,7 @@ class SuppressionGain {
|
||||
bool saturated_echo,
|
||||
const std::vector<std::vector<float>>& render,
|
||||
bool force_zero_gain,
|
||||
bool linear_echo_estimate,
|
||||
float* high_bands_gain,
|
||||
std::array<float, kFftLengthBy2Plus1>* low_band_gain);
|
||||
|
||||
@ -39,6 +40,7 @@ class SuppressionGain {
|
||||
void LowerBandGain(bool stationary_with_low_power,
|
||||
const rtc::Optional<int>& narrow_peak_band,
|
||||
bool saturated_echo,
|
||||
bool linear_echo_estimate,
|
||||
const std::array<float, kFftLengthBy2Plus1>& nearend,
|
||||
const std::array<float, kFftLengthBy2Plus1>& echo,
|
||||
const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
|
||||
|
||||
@ -34,7 +34,7 @@ TEST(SuppressionGain, NullOutputGains) {
|
||||
.GetGain(E2, R2, N2, RenderSignalAnalyzer(), false,
|
||||
std::vector<std::vector<float>>(
|
||||
3, std::vector<float>(kBlockSize, 0.f)),
|
||||
false, &high_bands_gain, nullptr),
|
||||
false, true, &high_bands_gain, nullptr),
|
||||
"");
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ TEST(SuppressionGain, BasicGainComputation) {
|
||||
R2.fill(0.1f);
|
||||
N2.fill(100.f);
|
||||
for (int k = 0; k < 10; ++k) {
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false,
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false, true,
|
||||
&high_bands_gain, &g);
|
||||
}
|
||||
std::for_each(g.begin(), g.end(),
|
||||
@ -68,7 +68,7 @@ TEST(SuppressionGain, BasicGainComputation) {
|
||||
R2.fill(0.1f);
|
||||
N2.fill(0.f);
|
||||
for (int k = 0; k < 10; ++k) {
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false,
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false, true,
|
||||
&high_bands_gain, &g);
|
||||
}
|
||||
std::for_each(g.begin(), g.end(),
|
||||
@ -79,14 +79,14 @@ TEST(SuppressionGain, BasicGainComputation) {
|
||||
R2.fill(10000000000000.f);
|
||||
N2.fill(0.f);
|
||||
for (int k = 0; k < 10; ++k) {
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false,
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, false, true,
|
||||
&high_bands_gain, &g);
|
||||
}
|
||||
std::for_each(g.begin(), g.end(),
|
||||
[](float a) { EXPECT_NEAR(0.f, a, 0.001); });
|
||||
|
||||
// Verify the functionality for forcing a zero gain.
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, true,
|
||||
suppression_gain.GetGain(E2, R2, N2, analyzer, false, x, true, true,
|
||||
&high_bands_gain, &g);
|
||||
std::for_each(g.begin(), g.end(), [](float a) { EXPECT_FLOAT_EQ(0.f, a); });
|
||||
EXPECT_FLOAT_EQ(0.f, high_bands_gain);
|
||||
|
||||
@ -296,6 +296,7 @@ class AudioProcessing : public rtc::RefCountInterface {
|
||||
float m4 = 0.3f;
|
||||
float m5 = 0.3f;
|
||||
float m6 = 0.0001f;
|
||||
float m7 = 0.01f;
|
||||
} gain_mask;
|
||||
|
||||
struct EchoAudibility {
|
||||
@ -322,6 +323,7 @@ class AudioProcessing : public rtc::RefCountInterface {
|
||||
GainChanges low_noise = {8.f, 10.f, 2.f, 4.f, 4.f, 4.f};
|
||||
GainChanges normal = {4.f, 10.f, 1.5f, 4.f, 2.f, 4.f};
|
||||
GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
|
||||
GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
|
||||
|
||||
float floor_first_increase = 0.001f;
|
||||
} gain_updates;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user