From 944744b25c76810e576516d2f676b1d9105e302f Mon Sep 17 00:00:00 2001 From: minyuel Date: Mon, 29 Feb 2016 13:09:01 +0100 Subject: [PATCH] Calculating ERLE in AEC more properly. The audio level of the AEC's output level was calculated before overlapping add, and therefore, a compensation was needed. The compensation is multiplying the level by 2 since, before overlapping add, the level is roughly halved due to windowing. This had to be that way because the level was calculated in frequency domain and the signal after overlapping add has only its time domain representation. The level calculation has been updated to work on time domain signal and therefore the problem is not there any longer. This CL is to put the calculation of the AEC output level after overlapping add and remove the compensation. BUG= R=peah@webrtc.org Review URL: https://codereview.webrtc.org/1644133002 . Cr-Commit-Position: refs/heads/master@{#11810} --- .../modules/audio_processing/aec/aec_core.cc | 18 ++++-------------- .../test/audio_processing_unittest.cc | 8 ++++---- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/webrtc/modules/audio_processing/aec/aec_core.cc b/webrtc/modules/audio_processing/aec/aec_core.cc index 2cc2968f81..1a45a0c8c0 100644 --- a/webrtc/modules/audio_processing/aec/aec_core.cc +++ b/webrtc/modules/audio_processing/aec/aec_core.cc @@ -689,12 +689,11 @@ static void UpdateMetrics(AecCore* aec) { // ERLE // subtract noise power - suppressedEcho = 2 * (aec->nlpoutlevel.averagelevel - - safety * aec->nlpoutlevel.minlevel); + suppressedEcho = aec->nlpoutlevel.averagelevel - + safety * aec->nlpoutlevel.minlevel; dtmp = 10 * static_cast(log10(aec->nearlevel.averagelevel / - (2 * aec->nlpoutlevel.averagelevel) + - 1e-10f)); + aec->nlpoutlevel.averagelevel + 1e-10f)); dtmp2 = 10 * static_cast(log10(echo / suppressedEcho + 1e-10f)); dtmp = dtmp2; @@ -1139,16 +1138,6 @@ static void EchoSuppression(AecCore* aec, // Inverse error fft. ScaledInverseFft(efw, fft, 2.0f, 1); - // TODO(bjornv): Investigate how to take the windowing below into account if - // needed. - if (aec->metricsMode == 1) { - // Note that we have a scaling by two in the time domain |eBuf|. - // In addition the time domain signal is windowed before transformation, - // losing half the energy on the average. We take care of the first - // scaling only in UpdateMetrics(). - UpdateLevel(&aec->nlpoutlevel, CalculatePower(fft, PART_LEN2)); - } - // Overlap and add to obtain output. for (i = 0; i < PART_LEN; i++) { output[i] = (fft[i] * WebRtcAec_sqrtHanning[i] + @@ -1358,6 +1347,7 @@ static void ProcessBlock(AecCore* aec) { EchoSuppression(aec, farend_ptr, echo_subtractor_output, output, outputH_ptr); if (aec->metricsMode == 1) { + UpdateLevel(&aec->nlpoutlevel, CalculatePower(output, PART_LEN)); UpdateMetrics(aec); } diff --git a/webrtc/modules/audio_processing/test/audio_processing_unittest.cc b/webrtc/modules/audio_processing/test/audio_processing_unittest.cc index 3ffed87444..40e235be1d 100644 --- a/webrtc/modules/audio_processing/test/audio_processing_unittest.cc +++ b/webrtc/modules/audio_processing/test/audio_processing_unittest.cc @@ -204,10 +204,10 @@ int16_t MaxAudioFrame(const AudioFrame& frame) { #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) void TestStats(const AudioProcessing::Statistic& test, const audioproc::Test::Statistic& reference) { - EXPECT_NEAR(reference.instant(), test.instant, 1); - EXPECT_EQ(reference.average(), test.average); - EXPECT_EQ(reference.maximum(), test.maximum); - EXPECT_NEAR(reference.minimum(), test.minimum, 1); + EXPECT_NEAR(reference.instant(), test.instant, 2); + EXPECT_NEAR(reference.average(), test.average, 2); + EXPECT_NEAR(reference.maximum(), test.maximum, 2); + EXPECT_NEAR(reference.minimum(), test.minimum, 2); } void WriteStatsMessage(const AudioProcessing::Statistic& output,