AEC3: Corrected the filter adjustment during analog gain changes

This CL corrects the way that the echo subtractor output is
adjusted during the adjustment of the adaptive filter when the
analog AGC gain changes.

The CL also ensures that the main adaptive filter is not updated
when this occurs.

Bug: webrtc:9561,chromium:867373
Change-Id: I636f936128f7d9f0d82ca4140b59f148eb35d6a4
Reviewed-on: https://webrtc-review.googlesource.com/90401
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24101}
This commit is contained in:
Per Åhgren
2018-07-25 16:30:54 +02:00
committed by Commit Bot
parent a12c42a6b2
commit 7f5175a455
2 changed files with 29 additions and 25 deletions

View File

@ -71,6 +71,18 @@ void PredictionError(const Aec3Fft& fft,
}
}
void ScaleFilterOutput(rtc::ArrayView<const float> y,
float factor,
rtc::ArrayView<float> e,
rtc::ArrayView<float> s) {
RTC_DCHECK_EQ(y.size(), e.size());
RTC_DCHECK_EQ(y.size(), s.size());
for (size_t k = 0; k < y.size(); ++k) {
s[k] *= factor;
e[k] = y[k] - s[k];
}
}
} // namespace
Subtractor::Subtractor(const EchoCanceller3Config& config,
@ -157,29 +169,34 @@ void Subtractor::Process(const RenderBuffer& render_buffer,
FftData S;
FftData& G = S;
// Form the output of the main filter.
// Form the outputs of the main and shadow filters.
main_filter_.Filter(render_buffer, &S);
bool main_saturation = false;
PredictionError(fft_, S, y, &e_main, &output->s_main,
adaptation_during_saturation_, &main_saturation);
fft_.ZeroPaddedFft(e_main, Aec3Fft::Window::kHanning, &E_main);
// Form the output of the shadow filter.
shadow_filter_.Filter(render_buffer, &S);
bool shadow_saturation = false;
PredictionError(fft_, S, y, &e_shadow, nullptr, adaptation_during_saturation_,
&shadow_saturation);
fft_.ZeroPaddedFft(e_shadow, Aec3Fft::Window::kHanning, &E_shadow);
// Adjust the filter if needed.
bool main_filter_adjusted = false;
if (enable_misadjustment_estimator_) {
filter_misadjustment_estimator_.Update(e_main, y);
if (filter_misadjustment_estimator_.IsAdjustmentNeeded()) {
float scale = filter_misadjustment_estimator_.GetMisadjustment();
main_filter_.ScaleFilter(scale);
output->ScaleOutputMainFilter(scale);
ScaleFilterOutput(y, scale, e_main, output->s_main);
filter_misadjustment_estimator_.Reset();
main_filter_adjusted = true;
}
}
// Compute the FFts of the main and shadow filter outputs.
fft_.ZeroPaddedFft(e_main, Aec3Fft::Window::kHanning, &E_main);
fft_.ZeroPaddedFft(e_shadow, Aec3Fft::Window::kHanning, &E_shadow);
// Compute spectra for future use.
E_shadow.Spectrum(optimization_, output->E2_shadow);
E_main.Spectrum(optimization_, output->E2_main);
@ -187,8 +204,13 @@ void Subtractor::Process(const RenderBuffer& render_buffer,
// Update the main filter.
std::array<float, kFftLengthBy2Plus1> X2;
render_buffer.SpectralSum(main_filter_.SizePartitions(), &X2);
G_main_.Compute(X2, render_signal_analyzer, *output, main_filter_,
aec_state.SaturatedCapture() || main_saturation, &G);
if (!main_filter_adjusted) {
G_main_.Compute(X2, render_signal_analyzer, *output, main_filter_,
aec_state.SaturatedCapture() || main_saturation, &G);
} else {
G.re.fill(0.f);
G.im.fill(0.f);
}
main_filter_.Adapt(render_buffer, G);
data_dumper_->DumpRaw("aec3_subtractor_G_main", G.re);
data_dumper_->DumpRaw("aec3_subtractor_G_main", G.im);

View File

@ -36,24 +36,6 @@ struct SubtractorOutput {
E2_main.fill(0.f);
E2_shadow.fill(0.f);
}
void ScaleOutputMainFilter(float factor) {
for (auto& s : s_main) {
s *= factor;
}
for (auto& e : e_main) {
e *= factor;
}
for (auto& E2 : E2_main) {
E2 *= factor * factor;
}
for (auto& re : E_main.re) {
re *= factor;
}
for (auto& im : E_main.im) {
im *= factor;
}
}
};
} // namespace webrtc