Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1190)

Unified Diff: webrtc/modules/audio_processing/aec/aec_core.c

Issue 1456123003: Ducking fix #3: Removed the state as an input to the FilterAdaptation function (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@Aec_Code_Cleanup2_CL
Patch Set: Removed gcc build-breaking method argument specifiers Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/modules/audio_processing/aec/aec_core_internal.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/modules/audio_processing/aec/aec_core.c
diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c
index 91b55b6acd3159ee64cf3b79036d09c43aea8787..da5c26b68395eab344f7f5de650e3a394d478347 100644
--- a/webrtc/modules/audio_processing/aec/aec_core.c
+++ b/webrtc/modules/audio_processing/aec/aec_core.c
@@ -151,30 +151,31 @@ static int CmpFloat(const void* a, const void* b) {
return (*da > *db) - (*da < *db);
}
-static void FilterFar(int num_partitions,
- int x_fft_buffer_block_pos,
- float x_fft_buffer[2][kExtendedNumPartitions * PART_LEN1],
- float h_fft_buffer[2][kExtendedNumPartitions * PART_LEN1],
- float y_fft[2][PART_LEN1]) {
+static void FilterFar(
+ int num_partitions,
+ int x_fft_buf_block_pos,
+ float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1],
+ float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1],
+ float y_fft[2][PART_LEN1]) {
int i;
for (i = 0; i < num_partitions; i++) {
int j;
- int x_pos = (i + x_fft_buffer_block_pos) * PART_LEN1;
+ int xPos = (i + x_fft_buf_block_pos) * PART_LEN1;
int pos = i * PART_LEN1;
- // Check for wrapped buffer.
- if (i + x_fft_buffer_block_pos >= num_partitions) {
- x_pos -= num_partitions * (PART_LEN1);
+ // Check for wrap
+ if (i + x_fft_buf_block_pos >= num_partitions) {
+ xPos -= num_partitions * (PART_LEN1);
}
for (j = 0; j < PART_LEN1; j++) {
- y_fft[0][j] += MulRe(x_fft_buffer[0][x_pos + j],
- x_fft_buffer[1][x_pos + j],
- h_fft_buffer[0][pos + j],
- h_fft_buffer[1][pos + j]);
- y_fft[1][j] += MulIm(x_fft_buffer[0][x_pos + j],
- x_fft_buffer[1][x_pos + j],
- h_fft_buffer[0][pos + j],
- h_fft_buffer[1][pos + j]);
+ y_fft[0][j] += MulRe(x_fft_buf[0][xPos + j],
+ x_fft_buf[1][xPos + j],
+ h_fft_buf[0][pos + j],
+ h_fft_buf[1][pos + j]);
+ y_fft[1][j] += MulIm(x_fft_buf[0][xPos + j],
+ x_fft_buf[1][xPos + j],
+ h_fft_buf[0][pos + j],
+ h_fft_buf[1][pos + j]);
}
}
}
@@ -182,7 +183,7 @@ static void FilterFar(int num_partitions,
static void ScaleErrorSignal(int extended_filter_enabled,
float normal_mu,
float normal_error_threshold,
- float *x_pow,
+ float x_pow[PART_LEN1],
float ef[2][PART_LEN1]) {
const float mu = extended_filter_enabled ? kExtendedMu : normal_mu;
const float error_threshold = extended_filter_enabled
@@ -207,59 +208,40 @@ static void ScaleErrorSignal(int extended_filter_enabled,
}
}
-// Time-unconstrined filter adaptation.
-// TODO(andrew): consider for a low-complexity mode.
-// static void FilterAdaptationUnconstrained(AecCore* aec, float *fft,
-// float ef[2][PART_LEN1]) {
-// int i, j;
-// for (i = 0; i < aec->num_partitions; i++) {
-// int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
-// int pos;
-// // Check for wrap
-// if (i + aec->xfBufBlockPos >= aec->num_partitions) {
-// xPos -= aec->num_partitions * PART_LEN1;
-// }
-//
-// pos = i * PART_LEN1;
-//
-// for (j = 0; j < PART_LEN1; j++) {
-// aec->wfBuf[0][pos + j] += MulRe(aec->xfBuf[0][xPos + j],
-// -aec->xfBuf[1][xPos + j],
-// ef[0][j], ef[1][j]);
-// aec->wfBuf[1][pos + j] += MulIm(aec->xfBuf[0][xPos + j],
-// -aec->xfBuf[1][xPos + j],
-// ef[0][j], ef[1][j]);
-// }
-// }
-//}
-
-static void FilterAdaptation(AecCore* aec, float* fft, float ef[2][PART_LEN1]) {
+
+static void FilterAdaptation(
+ int num_partitions,
+ int x_fft_buf_block_pos,
+ float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1],
+ float e_fft[2][PART_LEN1],
+ float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]) {
int i, j;
- for (i = 0; i < aec->num_partitions; i++) {
- int xPos = (i + aec->xfBufBlockPos) * (PART_LEN1);
+ float fft[PART_LEN2];
+ for (i = 0; i < num_partitions; i++) {
+ int xPos = (i + x_fft_buf_block_pos) * (PART_LEN1);
int pos;
// Check for wrap
- if (i + aec->xfBufBlockPos >= aec->num_partitions) {
- xPos -= aec->num_partitions * PART_LEN1;
+ if (i + x_fft_buf_block_pos >= num_partitions) {
+ xPos -= num_partitions * PART_LEN1;
}
pos = i * PART_LEN1;
for (j = 0; j < PART_LEN; j++) {
- fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j],
- -aec->xfBuf[1][xPos + j],
- ef[0][j],
- ef[1][j]);
- fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j],
- -aec->xfBuf[1][xPos + j],
- ef[0][j],
- ef[1][j]);
+ fft[2 * j] = MulRe(x_fft_buf[0][xPos + j],
+ -x_fft_buf[1][xPos + j],
+ e_fft[0][j],
+ e_fft[1][j]);
+ fft[2 * j + 1] = MulIm(x_fft_buf[0][xPos + j],
+ -x_fft_buf[1][xPos + j],
+ e_fft[0][j],
+ e_fft[1][j]);
}
- fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
- -aec->xfBuf[1][xPos + PART_LEN],
- ef[0][PART_LEN],
- ef[1][PART_LEN]);
+ fft[1] = MulRe(x_fft_buf[0][xPos + PART_LEN],
+ -x_fft_buf[1][xPos + PART_LEN],
+ e_fft[0][PART_LEN],
+ e_fft[1][PART_LEN]);
aec_rdft_inverse_128(fft);
memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN);
@@ -273,12 +255,12 @@ static void FilterAdaptation(AecCore* aec, float* fft, float ef[2][PART_LEN1]) {
}
aec_rdft_forward_128(fft);
- aec->wfBuf[0][pos] += fft[0];
- aec->wfBuf[0][pos + PART_LEN] += fft[1];
+ h_fft_buf[0][pos] += fft[0];
+ h_fft_buf[0][pos + PART_LEN] += fft[1];
for (j = 1; j < PART_LEN; j++) {
- aec->wfBuf[0][pos + j] += fft[2 * j];
- aec->wfBuf[1][pos + j] += fft[2 * j + 1];
+ h_fft_buf[0][pos + j] += fft[2 * j];
+ h_fft_buf[1][pos + j] += fft[2 * j + 1];
}
}
}
@@ -845,34 +827,26 @@ static void UpdateDelayMetrics(AecCore* self) {
return;
}
-static void FrequencyToTime(float freq_data[2][PART_LEN1],
- float time_data[PART_LEN2]) {
+static void InverseFft(float freq_data[2][PART_LEN1],
+ float time_data[PART_LEN2]) {
int i;
- time_data[0] = freq_data[0][0];
- time_data[1] = freq_data[0][PART_LEN];
+ const float scale = 1.0f / PART_LEN2;
+ time_data[0] = freq_data[0][0] * scale;
+ time_data[1] = freq_data[0][PART_LEN] * scale;
for (i = 1; i < PART_LEN; i++) {
- time_data[2 * i] = freq_data[0][i];
- time_data[2 * i + 1] = freq_data[1][i];
+ time_data[2 * i] = freq_data[0][i] * scale;
+ time_data[2 * i + 1] = freq_data[1][i] * scale;
}
aec_rdft_inverse_128(time_data);
}
-static void TimeToFrequency(float time_data[PART_LEN2],
- float freq_data[2][PART_LEN1],
- int window) {
- int i = 0;
-
- // TODO(bjornv): Should we have a different function/wrapper for windowed FFT?
- if (window) {
- for (i = 0; i < PART_LEN; i++) {
- time_data[i] *= WebRtcAec_sqrtHanning[i];
- time_data[PART_LEN + i] *= WebRtcAec_sqrtHanning[PART_LEN - i];
- }
- }
-
+static void Fft(float time_data[PART_LEN2],
+ float freq_data[2][PART_LEN1]) {
+ int i;
aec_rdft_forward_128(time_data);
- // Reorder.
+
+ // Reorder fft output data.
freq_data[1][0] = 0;
freq_data[1][PART_LEN] = 0;
freq_data[0][0] = time_data[0];
@@ -963,61 +937,76 @@ static int SignalBasedDelayCorrection(AecCore* self) {
return delay_correction;
}
-static void EchoSubtraction(AecCore* aec,
- float* nearend_ptr) {
- float yf[2][PART_LEN1];
- float fft[PART_LEN2];
- float y[PART_LEN];
+static void EchoSubtraction(
+ AecCore* aec,
+ int num_partitions,
+ int x_fft_buf_block_pos,
+ int metrics_mode,
+ int extended_filter_enabled,
+ float normal_mu,
+ float normal_error_threshold,
+ float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1],
+ float* const y,
+ float x_pow[PART_LEN1],
+ float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1],
+ PowerLevel* linout_level,
+ float echo_subtractor_output[PART_LEN]) {
+ float s_fft[2][PART_LEN1];
+ float e_extended[PART_LEN2];
+ float s_extended[PART_LEN2];
+ float *s;
float e[PART_LEN];
- float ef[2][PART_LEN1];
- float scale;
+ float e_fft[2][PART_LEN1];
int i;
- memset(yf, 0, sizeof(yf));
-
- // Produce frequency domain echo estimate.
- WebRtcAec_FilterFar(aec->num_partitions,
- aec->xfBufBlockPos,
- aec->xfBuf,
- aec->wfBuf,
- yf);
-
- // Inverse fft to obtain echo estimate and error.
- FrequencyToTime(yf, fft);
+ memset(s_fft, 0, sizeof(s_fft));
+
+ // Produce echo estimate s_fft.
+ WebRtcAec_FilterFar(num_partitions,
+ x_fft_buf_block_pos,
+ x_fft_buf,
+ h_fft_buf,
+ s_fft);
+
+ // Compute the time-domain echo estimate s.
+ InverseFft(s_fft, s_extended);
+ s = &s_extended[PART_LEN];
+ for (i = 0; i < PART_LEN; ++i) {
+ s[i] *= 2.0f;
+ }
- // Extract the output signal and compute the time-domain error.
- scale = 2.0f / PART_LEN2;
+ // Compute the time-domain echo prediction error.
for (i = 0; i < PART_LEN; ++i) {
- y[i] = fft[PART_LEN + i] * scale; // fft scaling.
- e[i] = nearend_ptr[i] - y[i];
+ e[i] = y[i] - s[i];
}
- // Error fft
- memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
- memset(fft, 0, sizeof(float) * PART_LEN);
- memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN);
- TimeToFrequency(fft, ef, 0);
+ // Compute the frequency domain echo prediction error.
+ memset(e_extended, 0, sizeof(float) * PART_LEN);
+ memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN);
+ Fft(e_extended, e_fft);
RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file,
- &ef[0][0],
- sizeof(ef[0][0]) * PART_LEN1 * 2);
+ &e_fft[0][0],
+ sizeof(e_fft[0][0]) * PART_LEN1 * 2);
- if (aec->metricsMode == 1) {
+ if (metrics_mode == 1) {
// Note that the first PART_LEN samples in fft (before transformation) are
// zero. Hence, the scaling by two in UpdateLevel() should not be
// performed. That scaling is taken care of in UpdateMetrics() instead.
- UpdateLevel(&aec->linoutlevel, ef);
+ UpdateLevel(linout_level, e_fft);
}
// Scale error signal inversely with far power.
- WebRtcAec_ScaleErrorSignal(aec->extended_filter_enabled,
- aec->normal_mu,
- aec->normal_error_threshold,
- aec->xPow,
- ef);
- WebRtcAec_FilterAdaptation(aec, fft, ef);
-
-
- RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN);
+ WebRtcAec_ScaleErrorSignal(extended_filter_enabled,
+ normal_mu,
+ normal_error_threshold,
+ x_pow,
+ e_fft);
+ WebRtcAec_FilterAdaptation(num_partitions,
+ x_fft_buf_block_pos,
+ x_fft_buf,
+ e_fft,
+ h_fft_buf);
+ memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN);
}
@@ -1274,6 +1263,7 @@ static void ProcessBlock(AecCore* aec) {
const float gInitNoise[2] = {0.999f, 0.001f};
float nearend[PART_LEN];
+ float echo_subtractor_output[PART_LEN];
float* nearend_ptr = NULL;
float output[PART_LEN];
float outputH[NUM_HIGH_BANDS_MAX][PART_LEN];
@@ -1313,7 +1303,7 @@ static void ProcessBlock(AecCore* aec) {
// Near fft
memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2);
- TimeToFrequency(fft, df, 0);
+ Fft(fft, df);
// Power smoothing
for (i = 0; i < PART_LEN1; i++) {
@@ -1392,9 +1382,26 @@ static void ProcessBlock(AecCore* aec) {
sizeof(float) * PART_LEN1);
// Perform echo subtraction.
- EchoSubtraction(aec, nearend_ptr);
+ EchoSubtraction(aec,
+ aec->num_partitions,
+ aec->xfBufBlockPos,
+ aec->metricsMode,
+ aec->extended_filter_enabled,
+ aec->normal_mu,
+ aec->normal_error_threshold,
+ aec->xfBuf,
+ nearend_ptr,
+ aec->xPow,
+ aec->wfBuf,
+ &aec->linoutlevel,
+ echo_subtractor_output);
+
+ RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN);
// Perform echo suppression.
+ memcpy(aec->eBuf + PART_LEN,
+ echo_subtractor_output,
+ sizeof(float) * PART_LEN);
EchoSuppression(aec, output, outputH_ptr);
if (aec->metricsMode == 1) {
@@ -1737,12 +1744,12 @@ void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) {
}
// Convert far-end partition to the frequency domain without windowing.
memcpy(fft, farend, sizeof(float) * PART_LEN2);
- TimeToFrequency(fft, xf, 0);
+ Fft(fft, xf);
WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1);
// Convert far-end partition to the frequency domain with windowing.
- memcpy(fft, farend, sizeof(float) * PART_LEN2);
- TimeToFrequency(fft, xf, 1);
+ WindowData(fft, farend);
+ Fft(fft, xf);
WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1);
}
« no previous file with comments | « no previous file | webrtc/modules/audio_processing/aec/aec_core_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698