Index: webrtc/modules/audio_processing/aec/aec_core.cc |
diff --git a/webrtc/modules/audio_processing/aec/aec_core.cc b/webrtc/modules/audio_processing/aec/aec_core.cc |
index ca5eae459051b0473be10aa5d7144604c2f33df5..9ddec59c768f2173e43c46af9918835faac6454e 100644 |
--- a/webrtc/modules/audio_processing/aec/aec_core.cc |
+++ b/webrtc/modules/audio_processing/aec/aec_core.cc |
@@ -986,96 +986,30 @@ static void EchoSubtraction(int num_partitions, |
memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); |
} |
-static void EchoSuppression(AecCore* aec, |
- float farend[PART_LEN2], |
- float* echo_subtractor_output, |
- float* output, |
- float* const* outputH) { |
- float efw[2][PART_LEN1]; |
- float xfw[2][PART_LEN1]; |
- float dfw[2][PART_LEN1]; |
- float comfortNoiseHband[2][PART_LEN1]; |
- float fft[PART_LEN2]; |
- float nlpGainHband; |
- int i; |
- size_t j; |
- |
- // Coherence and non-linear filter |
- float cohde[PART_LEN1], cohxd[PART_LEN1]; |
+static void FormSuppressionGain(AecCore* aec, |
+ float cohde[PART_LEN1], |
+ float cohxd[PART_LEN1], |
+ float hNl[PART_LEN1]) { |
float hNlDeAvg, hNlXdAvg; |
- float hNl[PART_LEN1]; |
float hNlPref[kPrefBandSize]; |
float hNlFb = 0, hNlFbLow = 0; |
- const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f; |
const int prefBandSize = kPrefBandSize / aec->mult; |
+ const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f; |
const int minPrefBand = 4 / aec->mult; |
// Power estimate smoothing coefficients. |
const float* min_overdrive = aec->extended_filter_enabled |
? kExtendedMinOverDrive |
: kNormalMinOverDrive; |
- // Filter energy |
- const int delayEstInterval = 10 * aec->mult; |
- |
- float* xfw_ptr = NULL; |
- |
- // Update eBuf with echo subtractor output. |
- memcpy(aec->eBuf + PART_LEN, echo_subtractor_output, |
- sizeof(float) * PART_LEN); |
- |
- // Analysis filter banks for the echo suppressor. |
- // Windowed near-end ffts. |
- WindowData(fft, aec->dBuf); |
- aec_rdft_forward_128(fft); |
- StoreAsComplex(fft, dfw); |
- |
- // Windowed echo suppressor output ffts. |
- WindowData(fft, aec->eBuf); |
- aec_rdft_forward_128(fft); |
- StoreAsComplex(fft, efw); |
- |
- // NLP |
- |
- // Convert far-end partition to the frequency domain with windowing. |
- WindowData(fft, farend); |
- Fft(fft, xfw); |
- xfw_ptr = &xfw[0][0]; |
- |
- // Buffer far. |
- memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); |
- |
- aec->delayEstCtr++; |
- if (aec->delayEstCtr == delayEstInterval) { |
- aec->delayEstCtr = 0; |
- aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf); |
- } |
- |
- // Use delayed far. |
- memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1, |
- sizeof(xfw[0][0]) * 2 * PART_LEN1); |
- |
- WebRtcAec_UpdateCoherenceSpectra(aec->mult, aec->extended_filter_enabled == 1, |
- efw, dfw, xfw, &aec->coherence_state, |
- &aec->divergeState, |
- &aec->extreme_filter_divergence); |
- |
- WebRtcAec_ComputeCoherence(&aec->coherence_state, cohde, cohxd); |
- |
- // 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++) { |
+ for (int i = minPrefBand; i < prefBandSize + minPrefBand; ++i) { |
hNlXdAvg += cohxd[i]; |
} |
hNlXdAvg /= prefBandSize; |
hNlXdAvg = 1 - hNlXdAvg; |
hNlDeAvg = 0; |
- for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { |
+ for (int i = minPrefBand; i < prefBandSize + minPrefBand; ++i) { |
hNlDeAvg += cohde[i]; |
} |
hNlDeAvg /= prefBandSize; |
@@ -1095,11 +1029,11 @@ static void EchoSuppression(AecCore* aec, |
aec->overDrive = min_overdrive[aec->nlp_mode]; |
if (aec->stNearState == 1) { |
- memcpy(hNl, cohde, sizeof(hNl)); |
+ memcpy(hNl, cohde, sizeof(hNl[0]) * PART_LEN1); |
hNlFb = hNlDeAvg; |
hNlFbLow = hNlDeAvg; |
} else { |
- for (i = 0; i < PART_LEN1; i++) { |
+ for (int i = 0; i < PART_LEN1; ++i) { |
hNl[i] = 1 - cohxd[i]; |
} |
hNlFb = hNlXdAvg; |
@@ -1108,12 +1042,12 @@ static void EchoSuppression(AecCore* aec, |
} else { |
if (aec->stNearState == 1) { |
aec->echoState = 0; |
- memcpy(hNl, cohde, sizeof(hNl)); |
+ memcpy(hNl, cohde, sizeof(hNl[0]) * PART_LEN1); |
hNlFb = hNlDeAvg; |
hNlFbLow = hNlDeAvg; |
} else { |
aec->echoState = 1; |
- for (i = 0; i < PART_LEN1; i++) { |
+ for (int i = 0; i < PART_LEN1; ++i) { |
hNl[i] = WEBRTC_SPL_MIN(cohde[i], 1 - cohxd[i]); |
} |
@@ -1161,7 +1095,83 @@ static void EchoSuppression(AecCore* aec, |
0.9f * aec->overdrive_scaling + 0.1f * aec->overDrive; |
} |
+ // Apply the overdrive. |
WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); |
+} |
+ |
+static void EchoSuppression(AecCore* aec, |
+ float farend[PART_LEN2], |
+ float* echo_subtractor_output, |
+ float* output, |
+ float* const* outputH) { |
+ float efw[2][PART_LEN1]; |
+ float xfw[2][PART_LEN1]; |
+ float dfw[2][PART_LEN1]; |
+ float comfortNoiseHband[2][PART_LEN1]; |
+ float fft[PART_LEN2]; |
+ float nlpGainHband; |
+ int i; |
+ size_t j; |
+ |
+ // Coherence and non-linear filter |
+ float cohde[PART_LEN1], cohxd[PART_LEN1]; |
+ float hNl[PART_LEN1]; |
+ |
+ // Filter energy |
+ const int delayEstInterval = 10 * aec->mult; |
+ |
+ float* xfw_ptr = NULL; |
+ |
+ // Update eBuf with echo subtractor output. |
+ memcpy(aec->eBuf + PART_LEN, echo_subtractor_output, |
+ sizeof(float) * PART_LEN); |
+ |
+ // Analysis filter banks for the echo suppressor. |
+ // Windowed near-end ffts. |
+ WindowData(fft, aec->dBuf); |
+ aec_rdft_forward_128(fft); |
+ StoreAsComplex(fft, dfw); |
+ |
+ // Windowed echo suppressor output ffts. |
+ WindowData(fft, aec->eBuf); |
+ aec_rdft_forward_128(fft); |
+ StoreAsComplex(fft, efw); |
+ |
+ // NLP |
+ |
+ // Convert far-end partition to the frequency domain with windowing. |
+ WindowData(fft, farend); |
+ Fft(fft, xfw); |
+ xfw_ptr = &xfw[0][0]; |
+ |
+ // Buffer far. |
+ memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); |
+ |
+ aec->delayEstCtr++; |
+ if (aec->delayEstCtr == delayEstInterval) { |
+ aec->delayEstCtr = 0; |
+ aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf); |
+ } |
+ |
+ // Use delayed far. |
+ memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1, |
+ sizeof(xfw[0][0]) * 2 * PART_LEN1); |
+ |
+ WebRtcAec_UpdateCoherenceSpectra(aec->mult, aec->extended_filter_enabled == 1, |
+ efw, dfw, xfw, &aec->coherence_state, |
+ &aec->divergeState, |
+ &aec->extreme_filter_divergence); |
+ |
+ WebRtcAec_ComputeCoherence(&aec->coherence_state, cohde, cohxd); |
+ |
+ // 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); |
+ } |
+ |
+ FormSuppressionGain(aec, cohde, cohxd, hNl); |
+ |
WebRtcAec_Suppress(hNl, efw); |
// Add comfort noise. |