Added the ability to adjust the filter adaptation speed in AEC3

Bug: webrtc:8609
Change-Id: I90eac3948ad0b7b1b5df2585ace3783e950c05d5
Reviewed-on: https://webrtc-review.googlesource.com/31485
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21217}
This commit is contained in:
Per Åhgren 2017-12-11 23:29:44 +01:00 committed by Commit Bot
parent 09a718accd
commit 477f289779
9 changed files with 46 additions and 18 deletions

View File

@ -316,7 +316,8 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) {
config.delay.default_delay = 1;
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, 3));
ShadowFilterUpdateGain gain;
ShadowFilterUpdateGain gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> n(kBlockSize, 0.f);

View File

@ -28,9 +28,14 @@ constexpr int kPoorExcitationCounterInitial = 1000;
int MainFilterUpdateGain::instance_count_ = 0;
MainFilterUpdateGain::MainFilterUpdateGain()
MainFilterUpdateGain::MainFilterUpdateGain(float leakage_converged,
float leakage_diverged,
float noise_gate_power)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
leakage_converged_(leakage_converged),
leakage_diverged_(leakage_diverged),
noise_gate_power_(noise_gate_power),
poor_excitation_counter_(kPoorExcitationCounterInitial) {
H_error_.fill(kHErrorInitial);
}
@ -75,11 +80,10 @@ void MainFilterUpdateGain::Compute(
G->im.fill(0.f);
} else {
// Corresponds to WGN of power -39 dBFS.
constexpr float kNoiseGatePower = 220075344.f;
std::array<float, kFftLengthBy2Plus1> mu;
// mu = H_error / (0.5* H_error* X2 + n * E2).
for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
mu[k] = X2[k] > kNoiseGatePower
mu[k] = X2[k] > noise_gate_power_
? H_error_[k] / (0.5f * H_error_[k] * X2[k] +
size_partitions * E2_main[k])
: 0.f;
@ -102,11 +106,9 @@ void MainFilterUpdateGain::Compute(
// H_error = H_error + factor * erl.
std::array<float, kFftLengthBy2Plus1> H_error_increase;
constexpr float kErlScaleAccurate = 1.f / 100.0f;
constexpr float kErlScaleInaccurate = 1.f / 60.0f;
std::transform(E2_shadow.begin(), E2_shadow.end(), E2_main.begin(),
H_error_increase.begin(), [&](float a, float b) {
return a >= b ? kErlScaleAccurate : kErlScaleInaccurate;
return a >= b ? leakage_converged_ : leakage_diverged_;
});
std::transform(erl.begin(), erl.end(), H_error_increase.begin(),
H_error_increase.begin(), std::multiplies<float>());

View File

@ -28,7 +28,9 @@ class ApmDataDumper;
// Provides functionality for computing the adaptive gain for the main filter.
class MainFilterUpdateGain {
public:
MainFilterUpdateGain();
MainFilterUpdateGain(float leakage_converged,
float leakage_diverged,
float noise_gate_power);
~MainFilterUpdateGain();
// Takes action in the case of a known echo path change.
@ -45,6 +47,9 @@ class MainFilterUpdateGain {
private:
static int instance_count_;
std::unique_ptr<ApmDataDumper> data_dumper_;
const float leakage_converged_;
const float leakage_diverged_;
const float noise_gate_power_;
std::array<float, kFftLengthBy2Plus1> H_error_;
size_t poor_excitation_counter_;
size_t call_counter_ = 0;

View File

@ -50,8 +50,11 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Aec3Fft fft;
std::array<float, kBlockSize> x_old;
x_old.fill(0.f);
ShadowFilterUpdateGain shadow_gain;
MainFilterUpdateGain main_gain;
ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
MainFilterUpdateGain main_gain(config.filter.leakage_converged,
config.filter.leakage_diverged,
config.filter.main_noise_gate);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
@ -190,7 +193,9 @@ TEST(MainFilterUpdateGain, NullDataOutputGain) {
RenderDelayBuffer::Create(config, 3));
RenderSignalAnalyzer analyzer;
SubtractorOutput output;
MainFilterUpdateGain gain;
MainFilterUpdateGain gain(config.filter.leakage_converged,
config.filter.leakage_diverged,
config.filter.main_noise_gate);
EXPECT_DEATH(gain.Compute(*render_delay_buffer->GetRenderBuffer(), analyzer,
output, filter, false, nullptr),
"");

View File

@ -17,6 +17,10 @@
namespace webrtc {
ShadowFilterUpdateGain::ShadowFilterUpdateGain(float rate,
float noise_gate_power)
: rate_(rate), noise_gate_power_(noise_gate_power) {}
void ShadowFilterUpdateGain::HandleEchoPathChange() {
// TODO(peah): Check whether this counter should instead be initialized to a
// large value.
@ -47,13 +51,10 @@ void ShadowFilterUpdateGain::Compute(
}
// Compute mu.
// Corresponds to WGN of power -39 dBFS.
constexpr float kNoiseGatePower = 220075344.f;
constexpr float kMuFixed = .5f;
std::array<float, kFftLengthBy2Plus1> mu;
auto X2 = render_buffer.SpectralSum(size_partitions);
std::transform(X2.begin(), X2.end(), mu.begin(), [&](float a) {
return a > kNoiseGatePower ? kMuFixed / a : 0.f;
return a > noise_gate_power_ ? rate_ / a : 0.f;
});
// Avoid updating the filter close to narrow bands in the render signals.

View File

@ -21,6 +21,8 @@ namespace webrtc {
// Provides functionality for computing the fixed gain for the shadow filter.
class ShadowFilterUpdateGain {
public:
ShadowFilterUpdateGain(float rate, float noise_gate_power);
// Takes action in the case of a known echo path change.
void HandleEchoPathChange();
@ -33,6 +35,8 @@ class ShadowFilterUpdateGain {
FftData* G);
private:
const float rate_;
const float noise_gate_power_;
// TODO(peah): Check whether this counter should instead be initialized to a
// large value.
size_t poor_signal_excitation_counter_ = 0;

View File

@ -52,7 +52,8 @@ void RunFilterUpdateTest(int num_blocks_to_process,
std::array<float, kBlockSize> x_old;
x_old.fill(0.f);
ShadowFilterUpdateGain shadow_gain;
ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
@ -134,7 +135,7 @@ TEST(ShadowFilterUpdateGain, NullDataOutputGain) {
RenderBuffer render_buffer(1, &block_buffer, &spectrum_buffer, &fft_buffer);
RenderSignalAnalyzer analyzer;
FftData E;
ShadowFilterUpdateGain gain;
ShadowFilterUpdateGain gain(0.5f, 220075344.f);
EXPECT_DEATH(gain.Compute(render_buffer, analyzer, E, 1, false, nullptr), "");
}

View File

@ -52,7 +52,11 @@ Subtractor::Subtractor(const EchoCanceller3Config& config,
data_dumper_(data_dumper),
optimization_(optimization),
main_filter_(config.filter.length_blocks, optimization, data_dumper_),
shadow_filter_(config.filter.length_blocks, optimization, data_dumper_) {
shadow_filter_(config.filter.length_blocks, optimization, data_dumper_),
G_main_(config.filter.leakage_converged,
config.filter.leakage_diverged,
config.filter.main_noise_gate),
G_shadow_(config.filter.shadow_rate, config.filter.shadow_noise_gate) {
RTC_DCHECK(data_dumper_);
}

View File

@ -1160,6 +1160,11 @@ struct EchoCanceller3Config {
struct Filter {
size_t length_blocks = 12;
float shadow_rate = 0.5f;
float leakage_converged = 0.01f;
float leakage_diverged = 1.f / 60.f;
float main_noise_gate = 220075344.f;
float shadow_noise_gate = 220075344.f;
} filter;
struct Erle {