Some minor (bitexact) AEC echo suppressor refactoring
-Moved filter reset from the echo suppression
into the echo subtraction code where it belongs
(the echo subtractor should own its filter reset).
-Moved the selection between using the microphone sinal and
the echo subtractor output down to the lowest level in the
EchoSuppression function. This makes sense as that selection
was very hidden in an unrelated sub-sub-function call and
as the selection is critical for what the AEC outputs.
The changes have been tested for bitexactness.
BUG=webrtc:5201
Review URL: https://codereview.webrtc.org/1499573003
Cr-Commit-Position: refs/heads/master@{#10956}
diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c
index cc8905f..41e9ba1 100644
--- a/webrtc/modules/audio_processing/aec/aec_core.c
+++ b/webrtc/modules/audio_processing/aec/aec_core.c
@@ -327,12 +327,13 @@
// - sde : cross-PSD of near-end and residual echo
// - sxd : cross-PSD of near-end and far-end
//
-// In addition to updating the PSDs, also the filter diverge state is determined
-// upon actions are taken.
+// In addition to updating the PSDs, also the filter diverge state is
+// determined.
static void SmoothedPSD(AecCore* aec,
float efw[2][PART_LEN1],
float dfw[2][PART_LEN1],
- float xfw[2][PART_LEN1]) {
+ float xfw[2][PART_LEN1],
+ int* extreme_filter_divergence) {
// Power estimate smoothing coefficients.
const float* ptrGCoh = aec->extended_filter_enabled
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
@@ -373,15 +374,12 @@
seSum += aec->se[i];
}
- // Divergent filter safeguard.
+ // Divergent filter safeguard update.
aec->divergeState = (aec->divergeState ? 1.05f : 1.0f) * seSum > sdSum;
- if (aec->divergeState)
- memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
-
- // Reset if error is significantly larger than nearend (13 dB).
- if (!aec->extended_filter_enabled && seSum > (19.95f * sdSum))
- memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
+ // Signal extreme filter divergence if the error is significantly larger
+ // than the nearend (13 dB).
+ *extreme_filter_divergence = (seSum > (19.95f * sdSum));
}
// Window time domain data to be used by the fft.
@@ -414,10 +412,11 @@
float xfw[2][PART_LEN1],
float* fft,
float* cohde,
- float* cohxd) {
+ float* cohxd,
+ int* extreme_filter_divergence) {
int i;
- SmoothedPSD(aec, efw, dfw, xfw);
+ SmoothedPSD(aec, efw, dfw, xfw, extreme_filter_divergence);
// Subband coherence
for (i = 0; i < PART_LEN1; i++) {
@@ -945,6 +944,14 @@
int i;
memset(s_fft, 0, sizeof(s_fft));
+ // Conditionally reset the echo subtraction filter if the filter has diverged
+ // significantly.
+ if (!aec->extended_filter_enabled &&
+ aec->extreme_filter_divergence) {
+ memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
+ aec->extreme_filter_divergence = 0;
+ }
+
// Produce echo estimate s_fft.
WebRtcAec_FilterFar(num_partitions,
x_fft_buf_block_pos,
@@ -1072,7 +1079,14 @@
aec->xfwBuf + aec->delayIdx * PART_LEN1,
sizeof(xfw[0][0]) * 2 * PART_LEN1);
- WebRtcAec_SubbandCoherence(aec, efw, dfw, xfw, fft, cohde, cohxd);
+ WebRtcAec_SubbandCoherence(aec, efw, dfw, xfw, fft, cohde, cohxd,
+ &aec->extreme_filter_divergence);
+
+ // Select the microphone signal as output if the filter is deemed to have
+ // diverged.
+ if (aec->divergeState) {
+ memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
+ }
hNlXdAvg = 0;
for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) {
@@ -1740,6 +1754,8 @@
aec->seed = 777;
aec->delayEstCtr = 0;
+ aec->extreme_filter_divergence = 0;
+
// Metrics disabled by default
aec->metricsMode = 0;
InitMetrics(aec);
diff --git a/webrtc/modules/audio_processing/aec/aec_core_internal.h b/webrtc/modules/audio_processing/aec/aec_core_internal.h
index 9ec6599..f8cb799 100644
--- a/webrtc/modules/audio_processing/aec/aec_core_internal.h
+++ b/webrtc/modules/audio_processing/aec/aec_core_internal.h
@@ -152,6 +152,10 @@
// Runtime selection of number of filter partitions.
int num_partitions;
+ // Flag that extreme filter divergence has been detected by the Echo
+ // Suppressor.
+ int extreme_filter_divergence;
+
#ifdef WEBRTC_AEC_DEBUG_DUMP
// Sequence number of this AEC instance, so that different instances can
// choose different dump file names.
@@ -209,7 +213,8 @@
float xfw[2][PART_LEN1],
float* fft,
float* cohde,
- float* cohxd);
+ float* cohxd,
+ int* extreme_filter_divergence);
extern WebRtcAecSubBandCoherence WebRtcAec_SubbandCoherence;
typedef int (*WebRtcAecPartitionDelay)(const AecCore* aec);
diff --git a/webrtc/modules/audio_processing/aec/aec_core_neon.c b/webrtc/modules/audio_processing/aec/aec_core_neon.c
index 84f2d29..7898ab2 100644
--- a/webrtc/modules/audio_processing/aec/aec_core_neon.c
+++ b/webrtc/modules/audio_processing/aec/aec_core_neon.c
@@ -510,7 +510,8 @@
static void SmoothedPSD(AecCore* aec,
float efw[2][PART_LEN1],
float dfw[2][PART_LEN1],
- float xfw[2][PART_LEN1]) {
+ float xfw[2][PART_LEN1],
+ int* extreme_filter_divergence) {
// Power estimate smoothing coefficients.
const float* ptrGCoh = aec->extended_filter_enabled
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
@@ -626,15 +627,12 @@
seSum += aec->se[i];
}
- // Divergent filter safeguard.
+ // Divergent filter safeguard update.
aec->divergeState = (aec->divergeState ? 1.05f : 1.0f) * seSum > sdSum;
- if (aec->divergeState)
- memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
-
- // Reset if error is significantly larger than nearend (13 dB).
- if (!aec->extended_filter_enabled && seSum > (19.95f * sdSum))
- memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
+ // Signal extreme filter divergence if the error is significantly larger
+ // than the nearend (13 dB).
+ *extreme_filter_divergence = (seSum > (19.95f * sdSum));
}
// Window time domain data to be used by the fft.
@@ -680,10 +678,11 @@
float xfw[2][PART_LEN1],
float* fft,
float* cohde,
- float* cohxd) {
+ float* cohxd,
+ int* extreme_filter_divergence) {
int i;
- SmoothedPSD(aec, efw, dfw, xfw);
+ SmoothedPSD(aec, efw, dfw, xfw, extreme_filter_divergence);
{
const float32x4_t vec_1eminus10 = vdupq_n_f32(1e-10f);
diff --git a/webrtc/modules/audio_processing/aec/aec_core_sse2.c b/webrtc/modules/audio_processing/aec/aec_core_sse2.c
index 8134917..f897a4c 100644
--- a/webrtc/modules/audio_processing/aec/aec_core_sse2.c
+++ b/webrtc/modules/audio_processing/aec/aec_core_sse2.c
@@ -489,7 +489,8 @@
static void SmoothedPSD(AecCore* aec,
float efw[2][PART_LEN1],
float dfw[2][PART_LEN1],
- float xfw[2][PART_LEN1]) {
+ float xfw[2][PART_LEN1],
+ int* extreme_filter_divergence) {
// Power estimate smoothing coefficients.
const float* ptrGCoh = aec->extended_filter_enabled
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
@@ -608,15 +609,12 @@
seSum += aec->se[i];
}
- // Divergent filter safeguard.
+ // Divergent filter safeguard update.
aec->divergeState = (aec->divergeState ? 1.05f : 1.0f) * seSum > sdSum;
- if (aec->divergeState)
- memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
-
- // Reset if error is significantly larger than nearend (13 dB).
- if (!aec->extended_filter_enabled && seSum > (19.95f * sdSum))
- memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
+ // Signal extreme filter divergence if the error is significantly larger
+ // than the nearend (13 dB).
+ *extreme_filter_divergence = (seSum > (19.95f * sdSum));
}
// Window time domain data to be used by the fft.
@@ -666,10 +664,11 @@
float xfw[2][PART_LEN1],
float* fft,
float* cohde,
- float* cohxd) {
+ float* cohxd,
+ int* extreme_filter_divergence) {
int i;
- SmoothedPSD(aec, efw, dfw, xfw);
+ SmoothedPSD(aec, efw, dfw, xfw, extreme_filter_divergence);
{
const __m128 vec_1eminus10 = _mm_set1_ps(1e-10f);