| 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.
|
|
|