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 4b5abedd5aa7694172fe773438fcc0822dc08ee9..5fbe05cdf0485e7c21ade7dee83de12856a8f108 100644 |
--- a/webrtc/modules/audio_processing/aec/aec_core.cc |
+++ b/webrtc/modules/audio_processing/aec/aec_core.cc |
@@ -25,6 +25,7 @@ |
#include <stdlib.h> |
#include <string.h> |
+#include "webrtc/base/checks.h" |
extern "C" { |
#include "webrtc/common_audio/ring_buffer.h" |
} |
@@ -239,11 +240,10 @@ static void FilterFar(int num_partitions, |
} |
static void ScaleErrorSignal(int extended_filter_enabled, |
tlegrand-webrtc
2016/04/14 14:32:42
This function don't really need the first paramete
peah-webrtc
2016/04/14 22:12:41
That is definitely a good change. I did not want t
tlegrand-webrtc
2016/04/15 09:07:04
Great! I think it's fine, since the CL isn't that
|
- float normal_mu, |
+ float mu, |
tlegrand-webrtc
2016/04/14 14:32:42
With removal of mu = kExtendedMu if extended filte
hlundin-webrtc
2016/04/14 14:47:46
It is now called (through EchoSubtraction) with ae
peah-webrtc
2016/04/14 22:12:41
Fully true.
peah-webrtc
2016/04/14 22:12:41
It is now called in a different way but with a mu
tlegrand-webrtc
2016/04/15 09:07:04
Acknowledged.
|
float normal_error_threshold, |
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 |
? kExtendedErrorThreshold |
: normal_error_threshold; |
@@ -936,10 +936,36 @@ static int SignalBasedDelayCorrection(AecCore* self) { |
return delay_correction; |
} |
+static void RegressorPower(int num_partitions, |
+ int latest_added_partition, |
+ float x_fft_buf[2] |
+ [kExtendedNumPartitions * PART_LEN1], |
+ float x_pow[PART_LEN1]) { |
+ RTC_DCHECK_LT(latest_added_partition, num_partitions); |
+ memset(x_pow, 0, PART_LEN1 * sizeof(x_pow[0])); |
+ |
+ int partition = latest_added_partition; |
+ int x_fft_buf_position = partition * PART_LEN1; |
+ for (int i = 0; i < num_partitions; ++i) { |
+ for (int bin = 0; bin < PART_LEN1; ++bin) { |
+ float re = x_fft_buf[0][x_fft_buf_position]; |
+ float im = x_fft_buf[1][x_fft_buf_position]; |
+ x_pow[bin] += re * re + im * im; |
+ ++x_fft_buf_position; |
+ } |
+ |
+ ++partition; |
+ if (partition == num_partitions) { |
+ partition = 0; |
+ x_fft_buf_position = 0; |
hlundin-webrtc
2016/04/14 14:02:26
Can you DCHECK what you expect x_fft_buf_position
peah-webrtc
2016/04/14 22:12:41
Good point!
Done.
|
+ } |
+ } |
+} |
+ |
static void EchoSubtraction(AecCore* aec, |
int num_partitions, |
int extended_filter_enabled, |
- float normal_mu, |
+ float filter_step_size, |
float normal_error_threshold, |
float* x_fft, |
int* x_fft_buf_block_pos, |
@@ -1001,7 +1027,7 @@ static void EchoSubtraction(AecCore* aec, |
sizeof(e_fft[0][0]) * PART_LEN1 * 2); |
// Scale error signal inversely with far power. |
- WebRtcAec_ScaleErrorSignal(extended_filter_enabled, normal_mu, |
+ WebRtcAec_ScaleErrorSignal(extended_filter_enabled, filter_step_size, |
normal_error_threshold, x_pow, e_fft); |
WebRtcAec_FilterAdaptation(num_partitions, *x_fft_buf_block_pos, x_fft_buf, |
e_fft, h_fft_buf); |
@@ -1316,14 +1342,27 @@ static void ProcessBlock(AecCore* aec) { |
Fft(fft, df); |
// Power smoothing |
- for (i = 0; i < PART_LEN1; i++) { |
- far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + |
- (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); |
- aec->xPow[i] = |
- gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; |
- // Calculate absolute spectra |
- abs_far_spectrum[i] = sqrtf(far_spectrum); |
+ if (aec->refined_adaptive_filter_enabled) { |
+ for (i = 0; i < PART_LEN1; ++i) { |
+ far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + |
+ (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); |
+ // Calculate absolute spectra |
+ abs_far_spectrum[i] = sqrtf(far_spectrum); |
+ } |
+ RegressorPower(aec->num_partitions, aec->xfBufBlockPos, aec->xfBuf, |
+ aec->xPow); |
+ } else { |
+ for (i = 0; i < PART_LEN1; ++i) { |
+ far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + |
+ (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); |
+ aec->xPow[i] = |
+ gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; |
+ // Calculate absolute spectra |
+ abs_far_spectrum[i] = sqrtf(far_spectrum); |
+ } |
+ } |
+ for (i = 0; i < PART_LEN1; ++i) { |
near_spectrum = df[0][i] * df[0][i] + df[1][i] * df[1][i]; |
aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] * near_spectrum; |
// Calculate absolute spectra |
@@ -1379,9 +1418,9 @@ static void ProcessBlock(AecCore* aec) { |
// Perform echo subtraction. |
EchoSubtraction(aec, aec->num_partitions, aec->extended_filter_enabled, |
- aec->normal_mu, aec->normal_error_threshold, &x_fft[0][0], |
- &aec->xfBufBlockPos, aec->xfBuf, nearend_ptr, aec->xPow, |
- aec->wfBuf, echo_subtractor_output); |
+ aec->filter_step_size, aec->normal_error_threshold, |
+ &x_fft[0][0], &aec->xfBufBlockPos, aec->xfBuf, nearend_ptr, |
+ aec->xPow, aec->wfBuf, echo_subtractor_output); |
RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN); |
@@ -1485,6 +1524,7 @@ AecCore* WebRtcAec_CreateAec() { |
#endif |
aec->extended_filter_enabled = 0; |
aec->aec3_enabled = 0; |
+ aec->refined_adaptive_filter_enabled = false; |
// Assembly optimization |
WebRtcAec_FilterFar = FilterFar; |
@@ -1548,17 +1588,37 @@ void WebRtcAec_FreeAec(AecCore* aec) { |
delete aec; |
} |
+static void SetAdaptiveFilterStepSize(AecCore* aec) { |
+ // Extended filter adaptation parameter. |
+ // TODO(ajm): No narrowband tuning yet. |
+ const float kExtendedMu = 0.4f; |
+ |
+ if (aec->refined_adaptive_filter_enabled) { |
+ aec->filter_step_size = 0.05f; |
hlundin-webrtc
2016/04/14 14:02:26
The old code seems to vary the step size depending
peah-webrtc
2016/04/14 22:12:41
Maybe,
The only way the sample rate affects the a
|
+ } else { |
+ if (aec->extended_filter_enabled) { |
+ aec->filter_step_size = kExtendedMu; |
+ } else { |
+ if (aec->sampFreq == 8000) { |
+ aec->filter_step_size = 0.6f; |
+ } else { |
+ aec->filter_step_size = 0.5f; |
+ } |
+ } |
+ } |
+} |
+ |
int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { |
int i; |
aec->sampFreq = sampFreq; |
+ SetAdaptiveFilterStepSize(aec); |
+ |
if (sampFreq == 8000) { |
- aec->normal_mu = 0.6f; |
aec->normal_error_threshold = 2e-6f; |
aec->num_bands = 1; |
} else { |
- aec->normal_mu = 0.5f; |
aec->normal_error_threshold = 1.5e-6f; |
aec->num_bands = (size_t)(sampFreq / 16000); |
} |
@@ -1930,6 +1990,14 @@ int WebRtcAec_aec3_enabled(AecCore* self) { |
return self->aec3_enabled; |
} |
+void WebRtcAec_enable_refined_adaptive_filter(AecCore* self, bool enable) { |
+ self->refined_adaptive_filter_enabled = enable; |
+ SetAdaptiveFilterStepSize(self); |
+} |
+ |
+bool WebRtcAec_refined_adaptive_filter_enabled(AecCore* self) { |
hlundin-webrtc
2016/04/14 14:02:27
const AecCore*
peah-webrtc
2016/04/14 22:12:41
Done.
|
+ return self->refined_adaptive_filter_enabled; |
+} |
void WebRtcAec_enable_extended_filter(AecCore* self, int enable) { |
self->extended_filter_enabled = enable; |