Added windowing of the error signal in echo canceller 3

This CL adds windowing of the error signal in echo canceller 3 to
avoid issues with spectral leakage affecting the quality of
the filter estimate.

Bug: webrtc:8661
Change-Id: I3e583f80fe02d7bba387a906bf44fbe7b89a2a6f
Reviewed-on: https://webrtc-review.googlesource.com/34188
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21328}
This commit is contained in:
Per Åhgren 2017-12-18 15:45:49 +01:00 committed by Commit Bot
parent 5825aa673c
commit 7634c16a02
2 changed files with 31 additions and 10 deletions

View File

@ -22,26 +22,48 @@ namespace webrtc {
namespace { namespace {
const float kHamming64[64] = {
0.08f, 0.08228584f, 0.08912066f, 0.10043651f, 0.11612094f,
0.13601808f, 0.15993016f, 0.18761956f, 0.21881106f, 0.25319469f,
0.29042872f, 0.3301431f, 0.37194313f, 0.41541338f, 0.46012184f,
0.50562416f, 0.55146812f, 0.5971981f, 0.64235963f, 0.68650386f,
0.72919207f, 0.77f, 0.80852209f, 0.84437549f, 0.87720386f,
0.90668095f, 0.93251381f, 0.95444568f, 0.97225861f, 0.98577555f,
0.99486218f, 0.99942818f, 0.99942818f, 0.99486218f, 0.98577555f,
0.97225861f, 0.95444568f, 0.93251381f, 0.90668095f, 0.87720386f,
0.84437549f, 0.80852209f, 0.77f, 0.72919207f, 0.68650386f,
0.64235963f, 0.5971981f, 0.55146812f, 0.50562416f, 0.46012184f,
0.41541338f, 0.37194313f, 0.3301431f, 0.29042872f, 0.25319469f,
0.21881106f, 0.18761956f, 0.15993016f, 0.13601808f, 0.11612094f,
0.10043651f, 0.08912066f, 0.08228584f, 0.08f};
void PredictionError(const Aec3Fft& fft, void PredictionError(const Aec3Fft& fft,
const FftData& S, const FftData& S,
rtc::ArrayView<const float> y, rtc::ArrayView<const float> y,
std::array<float, kBlockSize>* e, std::array<float, kBlockSize>* e,
FftData* E, FftData* E,
std::array<float, kBlockSize>* s) { std::array<float, kBlockSize>* s) {
std::array<float, kFftLength> s_scratch; std::array<float, kFftLength> tmp;
fft.Ifft(S, &s_scratch); fft.Ifft(S, &tmp);
constexpr float kScale = 1.0f / kFftLengthBy2; constexpr float kScale = 1.0f / kFftLengthBy2;
std::transform(y.begin(), y.end(), s_scratch.begin() + kFftLengthBy2, std::transform(y.begin(), y.end(), tmp.begin() + kFftLengthBy2, e->begin(),
e->begin(), [&](float a, float b) { return a - b * kScale; }); [&](float a, float b) { return a - b * kScale; });
std::for_each(e->begin(), e->end(),
[](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(*e, E);
if (s) { if (s) {
for (size_t k = 0; k < s->size(); ++k) { for (size_t k = 0; k < s->size(); ++k) {
(*s)[k] = kScale * s_scratch[k + kFftLengthBy2]; (*s)[k] = kScale * tmp[k + kFftLengthBy2];
} }
} }
std::for_each(e->begin(), e->end(),
[](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
RTC_DCHECK_EQ(64, e->size());
RTC_DCHECK_LE(64, tmp.size());
std::transform(e->begin(), e->end(), std::begin(kHamming64), tmp.begin(),
[](float a, float b) { return a * b; });
fft.ZeroPaddedFft(rtc::ArrayView<const float>(tmp.data(), 64), E);
} }
} // namespace } // namespace
@ -111,7 +133,6 @@ void Subtractor::Process(const RenderBuffer& render_buffer,
shadow_filter_.Filter(render_buffer, &S); shadow_filter_.Filter(render_buffer, &S);
PredictionError(fft_, S, y, &e_shadow, &E_shadow, nullptr); PredictionError(fft_, S, y, &e_shadow, &E_shadow, nullptr);
if (!converged_filter_) { if (!converged_filter_) {
const auto sum_of_squares = [](float a, float b) { return a + b * b; }; const auto sum_of_squares = [](float a, float b) { return a + b * b; };
const float e2_main = const float e2_main =

View File

@ -162,7 +162,7 @@ TEST(Subtractor, Convergence) {
SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks)); SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
float echo_to_nearend_power = float echo_to_nearend_power =
RunSubtractorTest(300, delay_samples, filter_length_blocks, false, RunSubtractorTest(400, delay_samples, filter_length_blocks, false,
blocks_with_echo_path_changes); blocks_with_echo_path_changes);
// Use different criteria to take overmodelling into account. // Use different criteria to take overmodelling into account.