Format changes achieved by running
clang-format -i -style=Chromium BUG= Review URL: https://codereview.webrtc.org/1639283002 Cr-Commit-Position: refs/heads/master@{#11427}
This commit is contained in:
parent
f5b804bb9c
commit
ff63ed2888
@ -29,4 +29,3 @@ extern const float WebRtcAec_kNormalSmoothingCoefficients[2][2];
|
||||
extern const float WebRtcAec_kMinFarendPSD;
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_COMMON_H_
|
||||
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
|
||||
// Buffer size (samples)
|
||||
static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz.
|
||||
|
||||
@ -120,9 +119,7 @@ const float WebRtcAec_kNormalSmoothingCoefficients[2][2] = {{0.9f, 0.1f},
|
||||
{0.93f, 0.07f}};
|
||||
|
||||
// Number of partitions forming the NLP's "preferred" bands.
|
||||
enum {
|
||||
kPrefBandSize = 24
|
||||
};
|
||||
enum { kPrefBandSize = 24 };
|
||||
|
||||
#ifdef WEBRTC_AEC_DEBUG_DUMP
|
||||
extern int webrtc_aec_instance_count;
|
||||
@ -153,12 +150,11 @@ static int CmpFloat(const void* a, const void* b) {
|
||||
return (*da > *db) - (*da < *db);
|
||||
}
|
||||
|
||||
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]) {
|
||||
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;
|
||||
@ -170,14 +166,10 @@ static void FilterFar(
|
||||
}
|
||||
|
||||
for (j = 0; j < PART_LEN1; 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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -210,7 +202,6 @@ static void ScaleErrorSignal(int extended_filter_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void FilterAdaptation(
|
||||
int num_partitions,
|
||||
int x_fft_buf_block_pos,
|
||||
@ -230,20 +221,14 @@ static void FilterAdaptation(
|
||||
pos = i * PART_LEN1;
|
||||
|
||||
for (j = 0; j < PART_LEN; 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[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(x_fft_buf[0][xPos + PART_LEN],
|
||||
-x_fft_buf[1][xPos + PART_LEN],
|
||||
e_fft[0][PART_LEN],
|
||||
e_fft[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);
|
||||
@ -305,7 +290,7 @@ static int PartitionDelay(const AecCore* aec) {
|
||||
float wfEn = 0;
|
||||
for (j = 0; j < PART_LEN1; j++) {
|
||||
wfEn += aec->wfBuf[0][pos + j] * aec->wfBuf[0][pos + j] +
|
||||
aec->wfBuf[1][pos + j] * aec->wfBuf[1][pos + j];
|
||||
aec->wfBuf[1][pos + j] * aec->wfBuf[1][pos + j];
|
||||
}
|
||||
|
||||
if (wfEn > wfEnMax) {
|
||||
@ -334,9 +319,10 @@ static void SmoothedPSD(AecCore* aec,
|
||||
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]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
const float* ptrGCoh =
|
||||
aec->extended_filter_enabled
|
||||
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
int i;
|
||||
float sdSum = 0, seSum = 0;
|
||||
|
||||
@ -349,11 +335,10 @@ static void SmoothedPSD(AecCore* aec,
|
||||
// The threshold is not arbitrarily chosen, but balances protection and
|
||||
// adverse interaction with the algorithm's tuning.
|
||||
// TODO(bjornv): investigate further why this is so sensitive.
|
||||
aec->sx[i] =
|
||||
ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
aec->sx[i] = ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
|
||||
aec->sde[i][0] =
|
||||
ptrGCoh[0] * aec->sde[i][0] +
|
||||
@ -483,7 +468,6 @@ static void ComfortNoise(AecCore* aec,
|
||||
tmpAvg = 0.0;
|
||||
num = 0;
|
||||
if (aec->num_bands > 1) {
|
||||
|
||||
// average noise scale
|
||||
// average over second half of freq spectrum (i.e., 4->8khz)
|
||||
// TODO: we shouldn't need num. We know how many elements we're summing.
|
||||
@ -621,7 +605,6 @@ static void UpdateMetrics(AecCore* aec) {
|
||||
}
|
||||
|
||||
if (aec->farlevel.frcounter == 0) {
|
||||
|
||||
if (aec->farlevel.minlevel < noisyPower) {
|
||||
actThreshold = actThresholdClean;
|
||||
} else {
|
||||
@ -632,10 +615,8 @@ static void UpdateMetrics(AecCore* aec) {
|
||||
(aec->farlevel.sfrcounter == 0)
|
||||
|
||||
// Estimate in active far-end segments only
|
||||
&&
|
||||
(aec->farlevel.averagelevel >
|
||||
(actThreshold * aec->farlevel.minlevel))) {
|
||||
|
||||
&& (aec->farlevel.averagelevel >
|
||||
(actThreshold * aec->farlevel.minlevel))) {
|
||||
// Subtract noise power
|
||||
echo = aec->nearlevel.averagelevel - safety * aec->nearlevel.minlevel;
|
||||
|
||||
@ -769,21 +750,22 @@ static void UpdateDelayMetrics(AecCore* self) {
|
||||
for (i = 0; i < kHistorySizeBlocks; i++) {
|
||||
l1_norm += abs(i - median) * self->delay_histogram[i];
|
||||
}
|
||||
self->delay_std = (int)((l1_norm + self->num_delay_values / 2) /
|
||||
self->num_delay_values) * kMsPerBlock;
|
||||
self->delay_std =
|
||||
(int)((l1_norm + self->num_delay_values / 2) / self->num_delay_values) *
|
||||
kMsPerBlock;
|
||||
|
||||
// Determine fraction of delays that are out of bounds, that is, either
|
||||
// negative (anti-causal system) or larger than the AEC filter length.
|
||||
{
|
||||
int num_delays_out_of_bounds = self->num_delay_values;
|
||||
const int histogram_length = sizeof(self->delay_histogram) /
|
||||
sizeof(self->delay_histogram[0]);
|
||||
const int histogram_length =
|
||||
sizeof(self->delay_histogram) / sizeof(self->delay_histogram[0]);
|
||||
for (i = lookahead; i < lookahead + self->num_partitions; ++i) {
|
||||
if (i < histogram_length)
|
||||
num_delays_out_of_bounds -= self->delay_histogram[i];
|
||||
}
|
||||
self->fraction_poor_delays = (float)num_delays_out_of_bounds /
|
||||
self->num_delay_values;
|
||||
self->fraction_poor_delays =
|
||||
(float)num_delays_out_of_bounds / self->num_delay_values;
|
||||
}
|
||||
|
||||
// Reset histogram.
|
||||
@ -809,9 +791,7 @@ static void ScaledInverseFft(float freq_data[2][PART_LEN1],
|
||||
aec_rdft_inverse_128(time_data);
|
||||
}
|
||||
|
||||
|
||||
static void Fft(float time_data[PART_LEN2],
|
||||
float freq_data[2][PART_LEN1]) {
|
||||
static void Fft(float time_data[PART_LEN2], float freq_data[2][PART_LEN1]) {
|
||||
int i;
|
||||
aec_rdft_forward_128(time_data);
|
||||
|
||||
@ -852,10 +832,9 @@ static int SignalBasedDelayCorrection(AecCore* self) {
|
||||
// 4. Finally, verify that the proposed |delay_correction| is feasible by
|
||||
// comparing with the size of the far-end buffer.
|
||||
last_delay = WebRtc_last_delay(self->delay_estimator);
|
||||
if ((last_delay >= 0) &&
|
||||
(last_delay != self->previous_delay) &&
|
||||
if ((last_delay >= 0) && (last_delay != self->previous_delay) &&
|
||||
(WebRtc_last_delay_quality(self->delay_estimator) >
|
||||
self->delay_quality_threshold)) {
|
||||
self->delay_quality_threshold)) {
|
||||
int delay = last_delay - WebRtc_lookahead(self->delay_estimator);
|
||||
// Allow for a slack in the actual delay, defined by a |lower_bound| and an
|
||||
// |upper_bound|. The adaptive echo cancellation filter is currently
|
||||
@ -889,31 +868,34 @@ static int SignalBasedDelayCorrection(AecCore* self) {
|
||||
// correction.
|
||||
if (self->delay_correction_count > 0) {
|
||||
float delay_quality = WebRtc_last_delay_quality(self->delay_estimator);
|
||||
delay_quality = (delay_quality > kDelayQualityThresholdMax ?
|
||||
kDelayQualityThresholdMax : delay_quality);
|
||||
delay_quality =
|
||||
(delay_quality > kDelayQualityThresholdMax ? kDelayQualityThresholdMax
|
||||
: delay_quality);
|
||||
self->delay_quality_threshold =
|
||||
(delay_quality > self->delay_quality_threshold ? delay_quality :
|
||||
self->delay_quality_threshold);
|
||||
(delay_quality > self->delay_quality_threshold
|
||||
? delay_quality
|
||||
: self->delay_quality_threshold);
|
||||
}
|
||||
return delay_correction;
|
||||
}
|
||||
|
||||
static void EchoSubtraction(
|
||||
AecCore* aec,
|
||||
int num_partitions,
|
||||
int x_fft_buf_block_pos,
|
||||
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],
|
||||
float echo_subtractor_output[PART_LEN]) {
|
||||
static void EchoSubtraction(AecCore* aec,
|
||||
int num_partitions,
|
||||
int x_fft_buf_block_pos,
|
||||
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],
|
||||
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* s;
|
||||
float e[PART_LEN];
|
||||
float e_fft[2][PART_LEN1];
|
||||
int i;
|
||||
@ -921,17 +903,13 @@ static void EchoSubtraction(
|
||||
|
||||
// Conditionally reset the echo subtraction filter if the filter has diverged
|
||||
// significantly.
|
||||
if (!aec->extended_filter_enabled &&
|
||||
aec->extreme_filter_divergence) {
|
||||
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,
|
||||
x_fft_buf,
|
||||
h_fft_buf,
|
||||
WebRtcAec_FilterFar(num_partitions, x_fft_buf_block_pos, x_fft_buf, h_fft_buf,
|
||||
s_fft);
|
||||
|
||||
// Compute the time-domain echo estimate s.
|
||||
@ -948,21 +926,14 @@ static void EchoSubtraction(
|
||||
memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN);
|
||||
Fft(e_extended, e_fft);
|
||||
|
||||
RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file,
|
||||
&e_fft[0][0],
|
||||
RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, &e_fft[0][0],
|
||||
sizeof(e_fft[0][0]) * PART_LEN1 * 2);
|
||||
|
||||
// Scale error signal inversely with far power.
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1000,8 +971,7 @@ static void EchoSuppression(AecCore* aec,
|
||||
float* xfw_ptr = NULL;
|
||||
|
||||
// Update eBuf with echo subtractor output.
|
||||
memcpy(aec->eBuf + PART_LEN,
|
||||
echo_subtractor_output,
|
||||
memcpy(aec->eBuf + PART_LEN, echo_subtractor_output,
|
||||
sizeof(float) * PART_LEN);
|
||||
|
||||
// Analysis filter banks for the echo suppressor.
|
||||
@ -1032,8 +1002,7 @@ static void EchoSuppression(AecCore* aec,
|
||||
}
|
||||
|
||||
// Use delayed far.
|
||||
memcpy(xfw,
|
||||
aec->xfwBuf + aec->delayIdx * PART_LEN1,
|
||||
memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1,
|
||||
sizeof(xfw[0][0]) * 2 * PART_LEN1);
|
||||
|
||||
WebRtcAec_SubbandCoherence(aec, efw, dfw, xfw, fft, cohde, cohxd,
|
||||
@ -1084,7 +1053,6 @@ static void EchoSuppression(AecCore* aec,
|
||||
hNlFbLow = hNlXdAvg;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (aec->stNearState == 1) {
|
||||
aec->echoState = 0;
|
||||
memcpy(hNl, cohde, sizeof(hNl));
|
||||
@ -1159,8 +1127,8 @@ static void EchoSuppression(AecCore* aec,
|
||||
aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]);
|
||||
|
||||
// Saturate output to keep it in the allowed range.
|
||||
output[i] = WEBRTC_SPL_SAT(
|
||||
WEBRTC_SPL_WORD16_MAX, output[i], WEBRTC_SPL_WORD16_MIN);
|
||||
output[i] =
|
||||
WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[i], WEBRTC_SPL_WORD16_MIN);
|
||||
}
|
||||
memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0]));
|
||||
|
||||
@ -1189,11 +1157,10 @@ static void EchoSuppression(AecCore* aec,
|
||||
// Saturate output to keep it in the allowed range.
|
||||
for (j = 0; j < aec->num_bands - 1; ++j) {
|
||||
for (i = 0; i < PART_LEN; i++) {
|
||||
outputH[j][i] = WEBRTC_SPL_SAT(
|
||||
WEBRTC_SPL_WORD16_MAX, outputH[j][i], WEBRTC_SPL_WORD16_MIN);
|
||||
outputH[j][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, outputH[j][i],
|
||||
WEBRTC_SPL_WORD16_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Copy the current block to the old position.
|
||||
@ -1205,8 +1172,7 @@ static void EchoSuppression(AecCore* aec,
|
||||
memcpy(aec->dBufH[j], aec->dBufH[j] + PART_LEN, sizeof(float) * PART_LEN);
|
||||
}
|
||||
|
||||
memmove(aec->xfwBuf + PART_LEN1,
|
||||
aec->xfwBuf,
|
||||
memmove(aec->xfwBuf + PART_LEN1, aec->xfwBuf,
|
||||
sizeof(aec->xfwBuf) - sizeof(complex_t) * PART_LEN1);
|
||||
}
|
||||
|
||||
@ -1245,9 +1211,7 @@ static void ProcessBlock(AecCore* aec) {
|
||||
|
||||
// Concatenate old and new nearend blocks.
|
||||
for (i = 0; i < aec->num_bands - 1; ++i) {
|
||||
WebRtc_ReadBuffer(aec->nearFrBufH[i],
|
||||
(void**)&nearend_ptr,
|
||||
nearend,
|
||||
WebRtc_ReadBuffer(aec->nearFrBufH[i], (void**)&nearend_ptr, nearend,
|
||||
PART_LEN);
|
||||
memcpy(aec->dBufH[i] + PART_LEN, nearend_ptr, sizeof(nearend));
|
||||
}
|
||||
@ -1330,8 +1294,8 @@ static void ProcessBlock(AecCore* aec) {
|
||||
|
||||
// Block wise delay estimation used for logging
|
||||
if (aec->delay_logging_enabled) {
|
||||
if (WebRtc_AddFarSpectrumFloat(
|
||||
aec->delay_estimator_farend, abs_far_spectrum, PART_LEN1) == 0) {
|
||||
if (WebRtc_AddFarSpectrumFloat(aec->delay_estimator_farend,
|
||||
abs_far_spectrum, PART_LEN1) == 0) {
|
||||
int delay_estimate = WebRtc_DelayEstimatorProcessFloat(
|
||||
aec->delay_estimator, abs_near_spectrum, PART_LEN1);
|
||||
if (delay_estimate >= 0) {
|
||||
@ -1353,24 +1317,16 @@ static void ProcessBlock(AecCore* aec) {
|
||||
}
|
||||
|
||||
// Buffer xf
|
||||
memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1,
|
||||
xf_ptr,
|
||||
memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, xf_ptr,
|
||||
sizeof(float) * PART_LEN1);
|
||||
memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1,
|
||||
&xf_ptr[PART_LEN1],
|
||||
memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, &xf_ptr[PART_LEN1],
|
||||
sizeof(float) * PART_LEN1);
|
||||
|
||||
// Perform echo subtraction.
|
||||
EchoSubtraction(aec,
|
||||
aec->num_partitions,
|
||||
aec->xfBufBlockPos,
|
||||
EchoSubtraction(aec, aec->num_partitions, aec->xfBufBlockPos,
|
||||
aec->extended_filter_enabled,
|
||||
aec->normal_mu,
|
||||
aec->normal_error_threshold,
|
||||
aec->xfBuf,
|
||||
nearend_ptr,
|
||||
aec->xPow,
|
||||
aec->wfBuf,
|
||||
aec->normal_mu, aec->normal_error_threshold, aec->xfBuf,
|
||||
nearend_ptr, aec->xPow, aec->wfBuf,
|
||||
echo_subtractor_output);
|
||||
|
||||
RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN);
|
||||
@ -1417,14 +1373,14 @@ AecCore* WebRtcAec_CreateAec() {
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) {
|
||||
aec->nearFrBufH[i] = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
|
||||
sizeof(float));
|
||||
aec->nearFrBufH[i] =
|
||||
WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float));
|
||||
if (!aec->nearFrBufH[i]) {
|
||||
WebRtcAec_FreeAec(aec);
|
||||
return NULL;
|
||||
}
|
||||
aec->outFrBufH[i] = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
|
||||
sizeof(float));
|
||||
aec->outFrBufH[i] =
|
||||
WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float));
|
||||
if (!aec->outFrBufH[i]) {
|
||||
WebRtcAec_FreeAec(aec);
|
||||
return NULL;
|
||||
@ -1485,7 +1441,6 @@ AecCore* WebRtcAec_CreateAec() {
|
||||
WebRtcAec_PartitionDelay = PartitionDelay;
|
||||
WebRtcAec_WindowData = WindowData;
|
||||
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
if (WebRtc_GetCPUInfo(kSSE2)) {
|
||||
WebRtcAec_InitAec_SSE2();
|
||||
@ -1567,21 +1522,19 @@ int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
|
||||
int process_rate = sampFreq > 16000 ? 16000 : sampFreq;
|
||||
RTC_AEC_DEBUG_WAV_REOPEN("aec_far", aec->instance_index,
|
||||
aec->debug_dump_count, process_rate,
|
||||
&aec->farFile );
|
||||
&aec->farFile);
|
||||
RTC_AEC_DEBUG_WAV_REOPEN("aec_near", aec->instance_index,
|
||||
aec->debug_dump_count, process_rate,
|
||||
&aec->nearFile);
|
||||
RTC_AEC_DEBUG_WAV_REOPEN("aec_out", aec->instance_index,
|
||||
aec->debug_dump_count, process_rate,
|
||||
&aec->outFile );
|
||||
&aec->outFile);
|
||||
RTC_AEC_DEBUG_WAV_REOPEN("aec_out_linear", aec->instance_index,
|
||||
aec->debug_dump_count, process_rate,
|
||||
&aec->outLinearFile);
|
||||
}
|
||||
|
||||
RTC_AEC_DEBUG_RAW_OPEN("aec_e_fft",
|
||||
aec->debug_dump_count,
|
||||
&aec->e_fft_file);
|
||||
RTC_AEC_DEBUG_RAW_OPEN("aec_e_fft", aec->debug_dump_count, &aec->e_fft_file);
|
||||
|
||||
++aec->debug_dump_count;
|
||||
#endif
|
||||
@ -1667,8 +1620,8 @@ int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
|
||||
memset(aec->wfBuf, 0, sizeof(complex_t) * kExtendedNumPartitions * PART_LEN1);
|
||||
memset(aec->sde, 0, sizeof(complex_t) * PART_LEN1);
|
||||
memset(aec->sxd, 0, sizeof(complex_t) * PART_LEN1);
|
||||
memset(
|
||||
aec->xfwBuf, 0, sizeof(complex_t) * kExtendedNumPartitions * PART_LEN1);
|
||||
memset(aec->xfwBuf, 0,
|
||||
sizeof(complex_t) * kExtendedNumPartitions * PART_LEN1);
|
||||
memset(aec->se, 0, sizeof(float) * PART_LEN1);
|
||||
|
||||
// To prevent numerical instability in the first block.
|
||||
@ -1764,7 +1717,7 @@ void WebRtcAec_ProcessFrames(AecCore* aec,
|
||||
|
||||
assert(aec->num_bands == num_bands);
|
||||
|
||||
for (j = 0; j < num_samples; j+= FRAME_LEN) {
|
||||
for (j = 0; j < num_samples; j += FRAME_LEN) {
|
||||
// TODO(bjornv): Change the near-end buffer handling to be the same as for
|
||||
// far-end, that is, with a near_pre_buf.
|
||||
// Buffer the near-end frame.
|
||||
@ -1793,15 +1746,14 @@ void WebRtcAec_ProcessFrames(AecCore* aec,
|
||||
// which should be investigated. Maybe, allow for a non-symmetric
|
||||
// rounding, like -16.
|
||||
int move_elements = (aec->knownDelay - knownDelay - 32) / PART_LEN;
|
||||
int moved_elements =
|
||||
WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
|
||||
int moved_elements = WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
|
||||
aec->knownDelay -= moved_elements * PART_LEN;
|
||||
} else {
|
||||
// 2 b) Apply signal based delay correction.
|
||||
int move_elements = SignalBasedDelayCorrection(aec);
|
||||
int moved_elements =
|
||||
WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
|
||||
int far_near_buffer_diff = WebRtc_available_read(aec->far_time_buf) -
|
||||
int moved_elements = WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
|
||||
int far_near_buffer_diff =
|
||||
WebRtc_available_read(aec->far_time_buf) -
|
||||
WebRtc_available_read(aec->nearFrBuf) / PART_LEN;
|
||||
WebRtc_SoftResetDelayEstimator(aec->delay_estimator, moved_elements);
|
||||
WebRtc_SoftResetDelayEstimatorFarend(aec->delay_estimator_farend,
|
||||
@ -1844,7 +1796,9 @@ void WebRtcAec_ProcessFrames(AecCore* aec,
|
||||
}
|
||||
}
|
||||
|
||||
int WebRtcAec_GetDelayMetricsCore(AecCore* self, int* median, int* std,
|
||||
int WebRtcAec_GetDelayMetricsCore(AecCore* self,
|
||||
int* median,
|
||||
int* std,
|
||||
float* fraction_poor_delays) {
|
||||
assert(self != NULL);
|
||||
assert(median != NULL);
|
||||
@ -1866,7 +1820,9 @@ int WebRtcAec_GetDelayMetricsCore(AecCore* self, int* median, int* std,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtcAec_echo_state(AecCore* self) { return self->echoState; }
|
||||
int WebRtcAec_echo_state(AecCore* self) {
|
||||
return self->echoState;
|
||||
}
|
||||
|
||||
void WebRtcAec_GetEchoStats(AecCore* self,
|
||||
Stats* erl,
|
||||
@ -1917,7 +1873,9 @@ int WebRtcAec_extended_filter_enabled(AecCore* self) {
|
||||
return self->extended_filter_enabled;
|
||||
}
|
||||
|
||||
int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; }
|
||||
int WebRtcAec_system_delay(AecCore* self) {
|
||||
return self->system_delay;
|
||||
}
|
||||
|
||||
void WebRtcAec_SetSystemDelay(AecCore* self, int delay) {
|
||||
assert(delay >= 0);
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
#define PART_LEN 64 // Length of partition
|
||||
#define PART_LEN1 (PART_LEN + 1) // Unique fft coefficients
|
||||
#define PART_LEN2 (PART_LEN * 2) // Length of partition * 2
|
||||
#define NUM_HIGH_BANDS_MAX 2 // Max number of high bands
|
||||
#define NUM_HIGH_BANDS_MAX 2 // Max number of high bands
|
||||
|
||||
typedef float complex_t[2];
|
||||
// For performance reasons, some arrays of complex numbers are replaced by twice
|
||||
@ -35,9 +35,7 @@ typedef float complex_t[2];
|
||||
// compile time.
|
||||
|
||||
// Metrics
|
||||
enum {
|
||||
kOffsetLevel = -100
|
||||
};
|
||||
enum { kOffsetLevel = -100 };
|
||||
|
||||
typedef struct Stats {
|
||||
float instant;
|
||||
@ -83,7 +81,9 @@ int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements);
|
||||
// values we mean values that most likely will cause the AEC to perform poorly.
|
||||
// TODO(bjornv): Consider changing tests and tools to handle constant
|
||||
// constant aggregation window throughout the session instead.
|
||||
int WebRtcAec_GetDelayMetricsCore(AecCore* self, int* median, int* std,
|
||||
int WebRtcAec_GetDelayMetricsCore(AecCore* self,
|
||||
int* median,
|
||||
int* std,
|
||||
float* fraction_poor_delays);
|
||||
|
||||
// Returns the echo state (1: echo, 0: no echo).
|
||||
|
||||
@ -19,16 +19,12 @@
|
||||
|
||||
// Number of partitions for the extended filter mode. The first one is an enum
|
||||
// to be used in array declarations, as it represents the maximum filter length.
|
||||
enum {
|
||||
kExtendedNumPartitions = 32
|
||||
};
|
||||
enum { kExtendedNumPartitions = 32 };
|
||||
static const int kNormalNumPartitions = 12;
|
||||
|
||||
// Delay estimator constants, used for logging and delay compensation if
|
||||
// if reported delays are disabled.
|
||||
enum {
|
||||
kLookaheadBlocks = 15
|
||||
};
|
||||
enum { kLookaheadBlocks = 15 };
|
||||
enum {
|
||||
// 500 ms for 16 kHz which is equivalent with the limit of reported delays.
|
||||
kHistorySizeBlocks = 125
|
||||
|
||||
@ -44,7 +44,7 @@ void WebRtcAec_ComfortNoise_mips(AecCore* aec,
|
||||
float randTemp, randTemp2, randTemp3, randTemp4;
|
||||
int32_t tmp1s, tmp2s, tmp3s, tmp4s;
|
||||
|
||||
for (i = 0; i < PART_LEN; i+=4) {
|
||||
for (i = 0; i < PART_LEN; i += 4) {
|
||||
__asm __volatile (
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
@ -75,14 +75,14 @@ void WebRtcAec_ComfortNoise_mips(AecCore* aec,
|
||||
: "memory"
|
||||
);
|
||||
|
||||
u[i+1][0] = cosf(randTemp);
|
||||
u[i+1][1] = sinf(randTemp);
|
||||
u[i+2][0] = cosf(randTemp2);
|
||||
u[i+2][1] = sinf(randTemp2);
|
||||
u[i+3][0] = cosf(randTemp3);
|
||||
u[i+3][1] = sinf(randTemp3);
|
||||
u[i+4][0] = cosf(randTemp4);
|
||||
u[i+4][1] = sinf(randTemp4);
|
||||
u[i + 1][0] = cosf(randTemp);
|
||||
u[i + 1][1] = sinf(randTemp);
|
||||
u[i + 2][0] = cosf(randTemp2);
|
||||
u[i + 2][1] = sinf(randTemp2);
|
||||
u[i + 3][0] = cosf(randTemp3);
|
||||
u[i + 3][1] = sinf(randTemp3);
|
||||
u[i + 4][0] = cosf(randTemp4);
|
||||
u[i + 4][1] = sinf(randTemp4);
|
||||
}
|
||||
|
||||
// Reject LF noise
|
||||
@ -92,7 +92,7 @@ void WebRtcAec_ComfortNoise_mips(AecCore* aec,
|
||||
|
||||
u[0][0] = 0;
|
||||
u[0][1] = 0;
|
||||
for (i = 1; i < PART_LEN1; i+=4) {
|
||||
for (i = 1; i < PART_LEN1; i += 4) {
|
||||
__asm __volatile (
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
@ -264,7 +264,7 @@ void WebRtcAec_ComfortNoise_mips(AecCore* aec,
|
||||
|
||||
lambda -= PART_LEN;
|
||||
tmp = sqrtf(WEBRTC_SPL_MAX(1 - lambda[PART_LEN] * lambda[PART_LEN], 0));
|
||||
//tmp = 1 - lambda[i];
|
||||
// tmp = 1 - lambda[i];
|
||||
efw[0][PART_LEN] += tmp * u[PART_LEN][0];
|
||||
efw[1][PART_LEN] += tmp * u[PART_LEN][1];
|
||||
|
||||
@ -333,8 +333,8 @@ void WebRtcAec_FilterFar_mips(
|
||||
int xPos = (i + x_fft_buf_block_pos) * PART_LEN1;
|
||||
int pos = i * PART_LEN1;
|
||||
// Check for wrap
|
||||
if (i + x_fft_buf_block_pos >= num_partitions) {
|
||||
xPos -= num_partitions * (PART_LEN1);
|
||||
if (i + x_fft_buf_block_pos >= num_partitions) {
|
||||
xPos -= num_partitions * (PART_LEN1);
|
||||
}
|
||||
float* yf0 = y_fft[0];
|
||||
float* yf1 = y_fft[1];
|
||||
@ -448,7 +448,7 @@ void WebRtcAec_FilterAdaptation_mips(
|
||||
float fft[PART_LEN2];
|
||||
int i;
|
||||
for (i = 0; i < num_partitions; i++) {
|
||||
int xPos = (i + x_fft_buf_block_pos)*(PART_LEN1);
|
||||
int xPos = (i + x_fft_buf_block_pos) * (PART_LEN1);
|
||||
int pos;
|
||||
// Check for wrap
|
||||
if (i + x_fft_buf_block_pos >= num_partitions) {
|
||||
@ -462,7 +462,7 @@ void WebRtcAec_FilterAdaptation_mips(
|
||||
float* bIm = e_fft[1];
|
||||
float* fft_tmp;
|
||||
|
||||
float f0, f1, f2, f3, f4, f5, f6 ,f7, f8, f9, f10, f11, f12;
|
||||
float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12;
|
||||
int len = PART_LEN >> 1;
|
||||
|
||||
__asm __volatile (
|
||||
|
||||
@ -34,12 +34,13 @@ __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) {
|
||||
return aRe * bIm + aIm * bRe;
|
||||
}
|
||||
|
||||
static void FilterFarNEON(
|
||||
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]) {
|
||||
static void FilterFarNEON(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;
|
||||
@ -69,20 +70,16 @@ static void FilterFarNEON(
|
||||
}
|
||||
// scalar code for the remaining items.
|
||||
for (; j < PART_LEN1; 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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ARM64's arm_neon.h has already defined vdivq_f32 vsqrtq_f32.
|
||||
#if !defined (WEBRTC_ARCH_ARM64)
|
||||
#if !defined(WEBRTC_ARCH_ARM64)
|
||||
static float32x4_t vdivq_f32(float32x4_t a, float32x4_t b) {
|
||||
int i;
|
||||
float32x4_t x = vrecpeq_f32(b);
|
||||
@ -110,8 +107,8 @@ static float32x4_t vsqrtq_f32(float32x4_t s) {
|
||||
// check for divide by zero
|
||||
const uint32x4_t div_by_zero = vceqq_u32(vec_p_inf, vreinterpretq_u32_f32(x));
|
||||
// zero out the positive infinity results
|
||||
x = vreinterpretq_f32_u32(vandq_u32(vmvnq_u32(div_by_zero),
|
||||
vreinterpretq_u32_f32(x)));
|
||||
x = vreinterpretq_f32_u32(
|
||||
vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(x)));
|
||||
// from arm documentation
|
||||
// The Newton-Raphson iteration:
|
||||
// x[n+1] = x[n] * (3 - d * (x[n] * x[n])) / 2)
|
||||
@ -122,7 +119,8 @@ static float32x4_t vsqrtq_f32(float32x4_t s) {
|
||||
x = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x, x), s), x);
|
||||
}
|
||||
// sqrt(s) = s * 1/sqrt(s)
|
||||
return vmulq_f32(s, x);;
|
||||
return vmulq_f32(s, x);
|
||||
;
|
||||
}
|
||||
#endif // WEBRTC_ARCH_ARM64
|
||||
|
||||
@ -132,8 +130,9 @@ static void ScaleErrorSignalNEON(int extended_filter_enabled,
|
||||
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;
|
||||
const float error_threshold = extended_filter_enabled
|
||||
? kExtendedErrorThreshold
|
||||
: normal_error_threshold;
|
||||
const float32x4_t k1e_10f = vdupq_n_f32(1e-10f);
|
||||
const float32x4_t kMu = vmovq_n_f32(mu);
|
||||
const float32x4_t kThresh = vmovq_n_f32(error_threshold);
|
||||
@ -154,10 +153,10 @@ static void ScaleErrorSignalNEON(int extended_filter_enabled,
|
||||
const float32x4_t absEfInv = vdivq_f32(kThresh, absEfPlus);
|
||||
uint32x4_t ef_re_if = vreinterpretq_u32_f32(vmulq_f32(ef_re, absEfInv));
|
||||
uint32x4_t ef_im_if = vreinterpretq_u32_f32(vmulq_f32(ef_im, absEfInv));
|
||||
uint32x4_t ef_re_u32 = vandq_u32(vmvnq_u32(bigger),
|
||||
vreinterpretq_u32_f32(ef_re));
|
||||
uint32x4_t ef_im_u32 = vandq_u32(vmvnq_u32(bigger),
|
||||
vreinterpretq_u32_f32(ef_im));
|
||||
uint32x4_t ef_re_u32 =
|
||||
vandq_u32(vmvnq_u32(bigger), vreinterpretq_u32_f32(ef_re));
|
||||
uint32x4_t ef_im_u32 =
|
||||
vandq_u32(vmvnq_u32(bigger), vreinterpretq_u32_f32(ef_im));
|
||||
ef_re_if = vandq_u32(bigger, ef_re_if);
|
||||
ef_im_if = vandq_u32(bigger, ef_im_if);
|
||||
ef_re_u32 = vorrq_u32(ef_re_u32, ef_re_if);
|
||||
@ -224,10 +223,9 @@ static void FilterAdaptationNEON(
|
||||
vst1q_f32(&fft[2 * j + 4], g_n_h.val[1]);
|
||||
}
|
||||
// ... and fixup the first imaginary entry.
|
||||
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]);
|
||||
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);
|
||||
@ -292,8 +290,8 @@ static float32x4_t vpowq_f32(float32x4_t a, float32x4_t b) {
|
||||
const uint32x4_t vec_float_exponent_mask = vdupq_n_u32(0x7F800000);
|
||||
const uint32x4_t vec_eight_biased_exponent = vdupq_n_u32(0x43800000);
|
||||
const uint32x4_t vec_implicit_leading_one = vdupq_n_u32(0x43BF8000);
|
||||
const uint32x4_t two_n = vandq_u32(vreinterpretq_u32_f32(a),
|
||||
vec_float_exponent_mask);
|
||||
const uint32x4_t two_n =
|
||||
vandq_u32(vreinterpretq_u32_f32(a), vec_float_exponent_mask);
|
||||
const uint32x4_t n_1 = vshrq_n_u32(two_n, kShiftExponentIntoTopMantissa);
|
||||
const uint32x4_t n_0 = vorrq_u32(n_1, vec_eight_biased_exponent);
|
||||
const float32x4_t n =
|
||||
@ -302,11 +300,10 @@ static float32x4_t vpowq_f32(float32x4_t a, float32x4_t b) {
|
||||
// Compute y.
|
||||
const uint32x4_t vec_mantissa_mask = vdupq_n_u32(0x007FFFFF);
|
||||
const uint32x4_t vec_zero_biased_exponent_is_one = vdupq_n_u32(0x3F800000);
|
||||
const uint32x4_t mantissa = vandq_u32(vreinterpretq_u32_f32(a),
|
||||
vec_mantissa_mask);
|
||||
const float32x4_t y =
|
||||
vreinterpretq_f32_u32(vorrq_u32(mantissa,
|
||||
vec_zero_biased_exponent_is_one));
|
||||
const uint32x4_t mantissa =
|
||||
vandq_u32(vreinterpretq_u32_f32(a), vec_mantissa_mask);
|
||||
const float32x4_t y = vreinterpretq_f32_u32(
|
||||
vorrq_u32(mantissa, vec_zero_biased_exponent_is_one));
|
||||
// Approximate log2(y) ~= (y - 1) * pol5(y).
|
||||
// pol5(y) = C5 * y^5 + C4 * y^4 + C3 * y^3 + C2 * y^2 + C1 * y + C0
|
||||
const float32x4_t C5 = vdupq_n_f32(-3.4436006e-2f);
|
||||
@ -395,13 +392,13 @@ static void OverdriveAndSuppressNEON(AecCore* aec,
|
||||
float32x4_t vec_hNl = vld1q_f32(&hNl[i]);
|
||||
const float32x4_t vec_weightCurve = vld1q_f32(&WebRtcAec_weightCurve[i]);
|
||||
const uint32x4_t bigger = vcgtq_f32(vec_hNl, vec_hNlFb);
|
||||
const float32x4_t vec_weightCurve_hNlFb = vmulq_f32(vec_weightCurve,
|
||||
vec_hNlFb);
|
||||
const float32x4_t vec_weightCurve_hNlFb =
|
||||
vmulq_f32(vec_weightCurve, vec_hNlFb);
|
||||
const float32x4_t vec_one_weightCurve = vsubq_f32(vec_one, vec_weightCurve);
|
||||
const float32x4_t vec_one_weightCurve_hNl = vmulq_f32(vec_one_weightCurve,
|
||||
vec_hNl);
|
||||
const uint32x4_t vec_if0 = vandq_u32(vmvnq_u32(bigger),
|
||||
vreinterpretq_u32_f32(vec_hNl));
|
||||
const float32x4_t vec_one_weightCurve_hNl =
|
||||
vmulq_f32(vec_one_weightCurve, vec_hNl);
|
||||
const uint32x4_t vec_if0 =
|
||||
vandq_u32(vmvnq_u32(bigger), vreinterpretq_u32_f32(vec_hNl));
|
||||
const float32x4_t vec_one_weightCurve_add =
|
||||
vaddq_f32(vec_weightCurve_hNlFb, vec_one_weightCurve_hNl);
|
||||
const uint32x4_t vec_if1 =
|
||||
@ -513,12 +510,13 @@ static void SmoothedPSD(AecCore* aec,
|
||||
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]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
const float* ptrGCoh =
|
||||
aec->extended_filter_enabled
|
||||
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
int i;
|
||||
float sdSum = 0, seSum = 0;
|
||||
const float32x4_t vec_15 = vdupq_n_f32(WebRtcAec_kMinFarendPSD);
|
||||
const float32x4_t vec_15 = vdupq_n_f32(WebRtcAec_kMinFarendPSD);
|
||||
float32x4_t vec_sdSum = vdupq_n_f32(0.0f);
|
||||
float32x4_t vec_seSum = vdupq_n_f32(0.0f);
|
||||
|
||||
@ -581,10 +579,10 @@ static void SmoothedPSD(AecCore* aec,
|
||||
float32x2_t vec_sdSum_total;
|
||||
float32x2_t vec_seSum_total;
|
||||
// A B C D
|
||||
vec_sdSum_total = vpadd_f32(vget_low_f32(vec_sdSum),
|
||||
vget_high_f32(vec_sdSum));
|
||||
vec_seSum_total = vpadd_f32(vget_low_f32(vec_seSum),
|
||||
vget_high_f32(vec_seSum));
|
||||
vec_sdSum_total =
|
||||
vpadd_f32(vget_low_f32(vec_sdSum), vget_high_f32(vec_sdSum));
|
||||
vec_seSum_total =
|
||||
vpadd_f32(vget_low_f32(vec_seSum), vget_high_f32(vec_seSum));
|
||||
// A+B C+D
|
||||
vec_sdSum_total = vpadd_f32(vec_sdSum_total, vec_sdSum_total);
|
||||
vec_seSum_total = vpadd_f32(vec_seSum_total, vec_seSum_total);
|
||||
@ -603,11 +601,10 @@ static void SmoothedPSD(AecCore* aec,
|
||||
// The threshold is not arbitrarily chosen, but balances protection and
|
||||
// adverse interaction with the algorithm's tuning.
|
||||
// TODO(bjornv): investigate further why this is so sensitive.
|
||||
aec->sx[i] =
|
||||
ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
aec->sx[i] = ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
|
||||
aec->sde[i][0] =
|
||||
ptrGCoh[0] * aec->sde[i][0] +
|
||||
@ -652,7 +649,7 @@ static void WindowDataNEON(float* x_windowed, const float* x) {
|
||||
vget_low_f32(vec_sqrtHanning_rev));
|
||||
vst1q_f32(&x_windowed[i], vmulq_f32(vec_Buf1, vec_sqrtHanning));
|
||||
vst1q_f32(&x_windowed[PART_LEN + i],
|
||||
vmulq_f32(vec_Buf2, vec_sqrtHanning_rev));
|
||||
vmulq_f32(vec_Buf2, vec_sqrtHanning_rev));
|
||||
}
|
||||
}
|
||||
|
||||
@ -685,7 +682,7 @@ static void SubbandCoherenceNEON(AecCore* aec,
|
||||
SmoothedPSD(aec, efw, dfw, xfw, extreme_filter_divergence);
|
||||
|
||||
{
|
||||
const float32x4_t vec_1eminus10 = vdupq_n_f32(1e-10f);
|
||||
const float32x4_t vec_1eminus10 = vdupq_n_f32(1e-10f);
|
||||
|
||||
// Subband coherence
|
||||
for (i = 0; i + 3 < PART_LEN1; i += 4) {
|
||||
|
||||
@ -29,13 +29,13 @@ __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) {
|
||||
return aRe * bIm + aIm * bRe;
|
||||
}
|
||||
|
||||
static void FilterFarSSE2(
|
||||
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]) {
|
||||
|
||||
static void FilterFarSSE2(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;
|
||||
@ -67,14 +67,10 @@ static void FilterFarSSE2(
|
||||
}
|
||||
// scalar code for the remaining items.
|
||||
for (; j < PART_LEN1; 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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +82,7 @@ static void ScaleErrorSignalSSE2(int extended_filter_enabled,
|
||||
float ef[2][PART_LEN1]) {
|
||||
const __m128 k1e_10f = _mm_set1_ps(1e-10f);
|
||||
const __m128 kMu = extended_filter_enabled ? _mm_set1_ps(kExtendedMu)
|
||||
: _mm_set1_ps(normal_mu);
|
||||
: _mm_set1_ps(normal_mu);
|
||||
const __m128 kThresh = extended_filter_enabled
|
||||
? _mm_set1_ps(kExtendedErrorThreshold)
|
||||
: _mm_set1_ps(normal_error_threshold);
|
||||
@ -124,8 +120,7 @@ static void ScaleErrorSignalSSE2(int extended_filter_enabled,
|
||||
}
|
||||
// scalar code for the remaining items.
|
||||
{
|
||||
const float mu =
|
||||
extended_filter_enabled ? kExtendedMu : normal_mu;
|
||||
const float mu = extended_filter_enabled ? kExtendedMu : normal_mu;
|
||||
const float error_threshold = extended_filter_enabled
|
||||
? kExtendedErrorThreshold
|
||||
: normal_error_threshold;
|
||||
@ -188,10 +183,9 @@ static void FilterAdaptationSSE2(
|
||||
_mm_storeu_ps(&fft[2 * j + 4], h);
|
||||
}
|
||||
// ... and fixup the first imaginary entry.
|
||||
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]);
|
||||
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);
|
||||
@ -281,16 +275,16 @@ static __m128 mm_pow_ps(__m128 a, __m128 b) {
|
||||
// pol5(y) = C5 * y^5 + C4 * y^4 + C3 * y^3 + C2 * y^2 + C1 * y + C0
|
||||
static const ALIGN16_BEG float ALIGN16_END C5[4] = {
|
||||
-3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f};
|
||||
static const ALIGN16_BEG float ALIGN16_END
|
||||
C4[4] = {3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f};
|
||||
static const ALIGN16_BEG float ALIGN16_END
|
||||
C3[4] = {-1.2315303f, -1.2315303f, -1.2315303f, -1.2315303f};
|
||||
static const ALIGN16_BEG float ALIGN16_END
|
||||
C2[4] = {2.5988452f, 2.5988452f, 2.5988452f, 2.5988452f};
|
||||
static const ALIGN16_BEG float ALIGN16_END
|
||||
C1[4] = {-3.3241990f, -3.3241990f, -3.3241990f, -3.3241990f};
|
||||
static const ALIGN16_BEG float ALIGN16_END
|
||||
C0[4] = {3.1157899f, 3.1157899f, 3.1157899f, 3.1157899f};
|
||||
static const ALIGN16_BEG float ALIGN16_END C4[4] = {
|
||||
3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f};
|
||||
static const ALIGN16_BEG float ALIGN16_END C3[4] = {
|
||||
-1.2315303f, -1.2315303f, -1.2315303f, -1.2315303f};
|
||||
static const ALIGN16_BEG float ALIGN16_END C2[4] = {2.5988452f, 2.5988452f,
|
||||
2.5988452f, 2.5988452f};
|
||||
static const ALIGN16_BEG float ALIGN16_END C1[4] = {
|
||||
-3.3241990f, -3.3241990f, -3.3241990f, -3.3241990f};
|
||||
static const ALIGN16_BEG float ALIGN16_END C0[4] = {3.1157899f, 3.1157899f,
|
||||
3.1157899f, 3.1157899f};
|
||||
const __m128 pol5_y_0 = _mm_mul_ps(y, *((__m128*)C5));
|
||||
const __m128 pol5_y_1 = _mm_add_ps(pol5_y_0, *((__m128*)C4));
|
||||
const __m128 pol5_y_2 = _mm_mul_ps(pol5_y_1, y);
|
||||
@ -334,8 +328,8 @@ static __m128 mm_pow_ps(__m128 a, __m128 b) {
|
||||
const __m128 x_min = _mm_min_ps(b_log2_a, *((__m128*)max_input));
|
||||
const __m128 x_max = _mm_max_ps(x_min, *((__m128*)min_input));
|
||||
// Compute n.
|
||||
static const ALIGN16_BEG float half[4] ALIGN16_END = {0.5f, 0.5f,
|
||||
0.5f, 0.5f};
|
||||
static const ALIGN16_BEG float half[4] ALIGN16_END = {0.5f, 0.5f, 0.5f,
|
||||
0.5f};
|
||||
const __m128 x_minus_half = _mm_sub_ps(x_max, *((__m128*)half));
|
||||
const __m128i x_minus_half_floor = _mm_cvtps_epi32(x_minus_half);
|
||||
// Compute 2^n.
|
||||
@ -432,7 +426,7 @@ static void OverdriveAndSuppressSSE2(AecCore* aec,
|
||||
}
|
||||
}
|
||||
|
||||
__inline static void _mm_add_ps_4x1(__m128 sum, float *dst) {
|
||||
__inline static void _mm_add_ps_4x1(__m128 sum, float* dst) {
|
||||
// A+B C+D
|
||||
sum = _mm_add_ps(sum, _mm_shuffle_ps(sum, sum, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
// A+B+C+D A+B+C+D
|
||||
@ -492,12 +486,13 @@ static void SmoothedPSD(AecCore* aec,
|
||||
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]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
const float* ptrGCoh =
|
||||
aec->extended_filter_enabled
|
||||
? WebRtcAec_kExtendedSmoothingCoefficients[aec->mult - 1]
|
||||
: WebRtcAec_kNormalSmoothingCoefficients[aec->mult - 1];
|
||||
int i;
|
||||
float sdSum = 0, seSum = 0;
|
||||
const __m128 vec_15 = _mm_set1_ps(WebRtcAec_kMinFarendPSD);
|
||||
const __m128 vec_15 = _mm_set1_ps(WebRtcAec_kMinFarendPSD);
|
||||
const __m128 vec_GCoh0 = _mm_set1_ps(ptrGCoh[0]);
|
||||
const __m128 vec_GCoh1 = _mm_set1_ps(ptrGCoh[1]);
|
||||
__m128 vec_sdSum = _mm_set1_ps(0.0f);
|
||||
@ -530,18 +525,18 @@ static void SmoothedPSD(AecCore* aec,
|
||||
{
|
||||
const __m128 vec_3210 = _mm_loadu_ps(&aec->sde[i][0]);
|
||||
const __m128 vec_7654 = _mm_loadu_ps(&aec->sde[i + 2][0]);
|
||||
__m128 vec_a = _mm_shuffle_ps(vec_3210, vec_7654,
|
||||
_MM_SHUFFLE(2, 0, 2, 0));
|
||||
__m128 vec_b = _mm_shuffle_ps(vec_3210, vec_7654,
|
||||
_MM_SHUFFLE(3, 1, 3, 1));
|
||||
__m128 vec_a =
|
||||
_mm_shuffle_ps(vec_3210, vec_7654, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
__m128 vec_b =
|
||||
_mm_shuffle_ps(vec_3210, vec_7654, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
__m128 vec_dfwefw0011 = _mm_mul_ps(vec_dfw0, vec_efw0);
|
||||
__m128 vec_dfwefw0110 = _mm_mul_ps(vec_dfw0, vec_efw1);
|
||||
vec_a = _mm_mul_ps(vec_a, vec_GCoh0);
|
||||
vec_b = _mm_mul_ps(vec_b, vec_GCoh0);
|
||||
vec_dfwefw0011 = _mm_add_ps(vec_dfwefw0011,
|
||||
_mm_mul_ps(vec_dfw1, vec_efw1));
|
||||
vec_dfwefw0110 = _mm_sub_ps(vec_dfwefw0110,
|
||||
_mm_mul_ps(vec_dfw1, vec_efw0));
|
||||
vec_dfwefw0011 =
|
||||
_mm_add_ps(vec_dfwefw0011, _mm_mul_ps(vec_dfw1, vec_efw1));
|
||||
vec_dfwefw0110 =
|
||||
_mm_sub_ps(vec_dfwefw0110, _mm_mul_ps(vec_dfw1, vec_efw0));
|
||||
vec_a = _mm_add_ps(vec_a, _mm_mul_ps(vec_dfwefw0011, vec_GCoh1));
|
||||
vec_b = _mm_add_ps(vec_b, _mm_mul_ps(vec_dfwefw0110, vec_GCoh1));
|
||||
_mm_storeu_ps(&aec->sde[i][0], _mm_unpacklo_ps(vec_a, vec_b));
|
||||
@ -551,18 +546,18 @@ static void SmoothedPSD(AecCore* aec,
|
||||
{
|
||||
const __m128 vec_3210 = _mm_loadu_ps(&aec->sxd[i][0]);
|
||||
const __m128 vec_7654 = _mm_loadu_ps(&aec->sxd[i + 2][0]);
|
||||
__m128 vec_a = _mm_shuffle_ps(vec_3210, vec_7654,
|
||||
_MM_SHUFFLE(2, 0, 2, 0));
|
||||
__m128 vec_b = _mm_shuffle_ps(vec_3210, vec_7654,
|
||||
_MM_SHUFFLE(3, 1, 3, 1));
|
||||
__m128 vec_a =
|
||||
_mm_shuffle_ps(vec_3210, vec_7654, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
__m128 vec_b =
|
||||
_mm_shuffle_ps(vec_3210, vec_7654, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
__m128 vec_dfwxfw0011 = _mm_mul_ps(vec_dfw0, vec_xfw0);
|
||||
__m128 vec_dfwxfw0110 = _mm_mul_ps(vec_dfw0, vec_xfw1);
|
||||
vec_a = _mm_mul_ps(vec_a, vec_GCoh0);
|
||||
vec_b = _mm_mul_ps(vec_b, vec_GCoh0);
|
||||
vec_dfwxfw0011 = _mm_add_ps(vec_dfwxfw0011,
|
||||
_mm_mul_ps(vec_dfw1, vec_xfw1));
|
||||
vec_dfwxfw0110 = _mm_sub_ps(vec_dfwxfw0110,
|
||||
_mm_mul_ps(vec_dfw1, vec_xfw0));
|
||||
vec_dfwxfw0011 =
|
||||
_mm_add_ps(vec_dfwxfw0011, _mm_mul_ps(vec_dfw1, vec_xfw1));
|
||||
vec_dfwxfw0110 =
|
||||
_mm_sub_ps(vec_dfwxfw0110, _mm_mul_ps(vec_dfw1, vec_xfw0));
|
||||
vec_a = _mm_add_ps(vec_a, _mm_mul_ps(vec_dfwxfw0011, vec_GCoh1));
|
||||
vec_b = _mm_add_ps(vec_b, _mm_mul_ps(vec_dfwxfw0110, vec_GCoh1));
|
||||
_mm_storeu_ps(&aec->sxd[i][0], _mm_unpacklo_ps(vec_a, vec_b));
|
||||
@ -585,11 +580,10 @@ static void SmoothedPSD(AecCore* aec,
|
||||
// The threshold is not arbitrarily chosen, but balances protection and
|
||||
// adverse interaction with the algorithm's tuning.
|
||||
// TODO(bjornv): investigate further why this is so sensitive.
|
||||
aec->sx[i] =
|
||||
ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
aec->sx[i] = ptrGCoh[0] * aec->sx[i] +
|
||||
ptrGCoh[1] * WEBRTC_SPL_MAX(
|
||||
xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i],
|
||||
WebRtcAec_kMinFarendPSD);
|
||||
|
||||
aec->sde[i][0] =
|
||||
ptrGCoh[0] * aec->sde[i][0] +
|
||||
@ -628,9 +622,8 @@ static void WindowDataSSE2(float* x_windowed, const float* x) {
|
||||
__m128 vec_sqrtHanning_rev =
|
||||
_mm_loadu_ps(&WebRtcAec_sqrtHanning[PART_LEN - i - 3]);
|
||||
// D C B A
|
||||
vec_sqrtHanning_rev =
|
||||
_mm_shuffle_ps(vec_sqrtHanning_rev, vec_sqrtHanning_rev,
|
||||
_MM_SHUFFLE(0, 1, 2, 3));
|
||||
vec_sqrtHanning_rev = _mm_shuffle_ps(
|
||||
vec_sqrtHanning_rev, vec_sqrtHanning_rev, _MM_SHUFFLE(0, 1, 2, 3));
|
||||
_mm_storeu_ps(&x_windowed[i], _mm_mul_ps(vec_Buf1, vec_sqrtHanning));
|
||||
_mm_storeu_ps(&x_windowed[PART_LEN + i],
|
||||
_mm_mul_ps(vec_Buf2, vec_sqrtHanning_rev));
|
||||
@ -644,10 +637,10 @@ static void StoreAsComplexSSE2(const float* data,
|
||||
for (i = 0; i < PART_LEN; i += 4) {
|
||||
const __m128 vec_fft0 = _mm_loadu_ps(&data[2 * i]);
|
||||
const __m128 vec_fft4 = _mm_loadu_ps(&data[2 * i + 4]);
|
||||
const __m128 vec_a = _mm_shuffle_ps(vec_fft0, vec_fft4,
|
||||
_MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_b = _mm_shuffle_ps(vec_fft0, vec_fft4,
|
||||
_MM_SHUFFLE(3, 1, 3, 1));
|
||||
const __m128 vec_a =
|
||||
_mm_shuffle_ps(vec_fft0, vec_fft4, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_b =
|
||||
_mm_shuffle_ps(vec_fft0, vec_fft4, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
_mm_storeu_ps(&data_complex[0][i], vec_a);
|
||||
_mm_storeu_ps(&data_complex[1][i], vec_b);
|
||||
}
|
||||
@ -671,29 +664,29 @@ static void SubbandCoherenceSSE2(AecCore* aec,
|
||||
SmoothedPSD(aec, efw, dfw, xfw, extreme_filter_divergence);
|
||||
|
||||
{
|
||||
const __m128 vec_1eminus10 = _mm_set1_ps(1e-10f);
|
||||
const __m128 vec_1eminus10 = _mm_set1_ps(1e-10f);
|
||||
|
||||
// Subband coherence
|
||||
for (i = 0; i + 3 < PART_LEN1; i += 4) {
|
||||
const __m128 vec_sd = _mm_loadu_ps(&aec->sd[i]);
|
||||
const __m128 vec_se = _mm_loadu_ps(&aec->se[i]);
|
||||
const __m128 vec_sx = _mm_loadu_ps(&aec->sx[i]);
|
||||
const __m128 vec_sdse = _mm_add_ps(vec_1eminus10,
|
||||
_mm_mul_ps(vec_sd, vec_se));
|
||||
const __m128 vec_sdsx = _mm_add_ps(vec_1eminus10,
|
||||
_mm_mul_ps(vec_sd, vec_sx));
|
||||
const __m128 vec_sdse =
|
||||
_mm_add_ps(vec_1eminus10, _mm_mul_ps(vec_sd, vec_se));
|
||||
const __m128 vec_sdsx =
|
||||
_mm_add_ps(vec_1eminus10, _mm_mul_ps(vec_sd, vec_sx));
|
||||
const __m128 vec_sde_3210 = _mm_loadu_ps(&aec->sde[i][0]);
|
||||
const __m128 vec_sde_7654 = _mm_loadu_ps(&aec->sde[i + 2][0]);
|
||||
const __m128 vec_sxd_3210 = _mm_loadu_ps(&aec->sxd[i][0]);
|
||||
const __m128 vec_sxd_7654 = _mm_loadu_ps(&aec->sxd[i + 2][0]);
|
||||
const __m128 vec_sde_0 = _mm_shuffle_ps(vec_sde_3210, vec_sde_7654,
|
||||
_MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_sde_1 = _mm_shuffle_ps(vec_sde_3210, vec_sde_7654,
|
||||
_MM_SHUFFLE(3, 1, 3, 1));
|
||||
const __m128 vec_sxd_0 = _mm_shuffle_ps(vec_sxd_3210, vec_sxd_7654,
|
||||
_MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_sxd_1 = _mm_shuffle_ps(vec_sxd_3210, vec_sxd_7654,
|
||||
_MM_SHUFFLE(3, 1, 3, 1));
|
||||
const __m128 vec_sde_0 =
|
||||
_mm_shuffle_ps(vec_sde_3210, vec_sde_7654, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_sde_1 =
|
||||
_mm_shuffle_ps(vec_sde_3210, vec_sde_7654, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
const __m128 vec_sxd_0 =
|
||||
_mm_shuffle_ps(vec_sxd_3210, vec_sxd_7654, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
const __m128 vec_sxd_1 =
|
||||
_mm_shuffle_ps(vec_sxd_3210, vec_sxd_7654, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
__m128 vec_cohde = _mm_mul_ps(vec_sde_0, vec_sde_0);
|
||||
__m128 vec_cohxd = _mm_mul_ps(vec_sxd_0, vec_sxd_0);
|
||||
vec_cohde = _mm_add_ps(vec_cohde, _mm_mul_ps(vec_sde_1, vec_sde_1));
|
||||
|
||||
@ -21,9 +21,7 @@
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec/aec_core.h"
|
||||
|
||||
enum {
|
||||
kEstimateLengthFrames = 400
|
||||
};
|
||||
enum { kEstimateLengthFrames = 400 };
|
||||
|
||||
typedef struct {
|
||||
float buffer[kResamplerBufferSize];
|
||||
@ -81,8 +79,7 @@ void WebRtcAec_ResampleLinear(void* resampInst,
|
||||
assert(size_out != NULL);
|
||||
|
||||
// Add new frame data in lookahead
|
||||
memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay],
|
||||
inspeech,
|
||||
memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay], inspeech,
|
||||
size * sizeof(inspeech[0]));
|
||||
|
||||
// Sample rate ratio
|
||||
@ -96,7 +93,6 @@ void WebRtcAec_ResampleLinear(void* resampInst,
|
||||
tn = (size_t)tnew;
|
||||
|
||||
while (tn < size) {
|
||||
|
||||
// Interpolation
|
||||
outspeech[mm] = y[tn] + (tnew - tn) * (y[tn + 1] - y[tn]);
|
||||
mm++;
|
||||
@ -109,8 +105,7 @@ void WebRtcAec_ResampleLinear(void* resampInst,
|
||||
obj->position += (*size_out) * be - size;
|
||||
|
||||
// Shift buffer
|
||||
memmove(obj->buffer,
|
||||
&obj->buffer[size],
|
||||
memmove(obj->buffer, &obj->buffer[size],
|
||||
(kResamplerBufferSize - size) * sizeof(obj->buffer[0]));
|
||||
}
|
||||
|
||||
@ -122,8 +117,8 @@ int WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst) {
|
||||
obj->skewData[obj->skewDataIndex] = rawSkew;
|
||||
obj->skewDataIndex++;
|
||||
} else if (obj->skewDataIndex == kEstimateLengthFrames) {
|
||||
err = EstimateSkew(
|
||||
obj->skewData, kEstimateLengthFrames, obj->deviceSampleRateHz, skewEst);
|
||||
err = EstimateSkew(obj->skewData, kEstimateLengthFrames,
|
||||
obj->deviceSampleRateHz, skewEst);
|
||||
obj->skewEstimate = *skewEst;
|
||||
obj->skewDataIndex++;
|
||||
} else {
|
||||
|
||||
@ -13,12 +13,8 @@
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec/aec_core.h"
|
||||
|
||||
enum {
|
||||
kResamplingDelay = 1
|
||||
};
|
||||
enum {
|
||||
kResamplerBufferSize = FRAME_LEN * 4
|
||||
};
|
||||
enum { kResamplingDelay = 1 };
|
||||
enum { kResamplerBufferSize = FRAME_LEN * 4 };
|
||||
|
||||
// Unless otherwise specified, functions return 0 on success and -1 on error.
|
||||
void* WebRtcAec_CreateResampler(); // Returns NULL on error.
|
||||
|
||||
@ -187,9 +187,7 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
|
||||
Aec* aecpc = aecInst;
|
||||
AecConfig aecConfig;
|
||||
|
||||
if (sampFreq != 8000 &&
|
||||
sampFreq != 16000 &&
|
||||
sampFreq != 32000 &&
|
||||
if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000 &&
|
||||
sampFreq != 48000) {
|
||||
return AEC_BAD_PARAMETER_ERROR;
|
||||
}
|
||||
@ -233,7 +231,7 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
|
||||
// We skip the startup_phase completely (setting to 0) if DA-AEC is enabled,
|
||||
// but not extended_filter mode.
|
||||
aecpc->startup_phase = WebRtcAec_extended_filter_enabled(aecpc->aec) ||
|
||||
!WebRtcAec_delay_agnostic_enabled(aecpc->aec);
|
||||
!WebRtcAec_delay_agnostic_enabled(aecpc->aec);
|
||||
aecpc->bufSizeStart = 0;
|
||||
aecpc->checkBufSizeCtr = 0;
|
||||
aecpc->msInSndCardBuf = 0;
|
||||
@ -292,21 +290,16 @@ int32_t WebRtcAec_BufferFarend(void* aecInst,
|
||||
const float* farend_ptr = farend;
|
||||
|
||||
// Get any error caused by buffering the farend signal.
|
||||
int32_t error_code = WebRtcAec_GetBufferFarendError(aecInst, farend,
|
||||
nrOfSamples);
|
||||
int32_t error_code =
|
||||
WebRtcAec_GetBufferFarendError(aecInst, farend, nrOfSamples);
|
||||
|
||||
if (error_code != 0)
|
||||
return error_code;
|
||||
|
||||
|
||||
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
|
||||
// Resample and get a new number of samples
|
||||
WebRtcAec_ResampleLinear(aecpc->resampler,
|
||||
farend,
|
||||
nrOfSamples,
|
||||
aecpc->skew,
|
||||
new_farend,
|
||||
&newNrOfSamples);
|
||||
WebRtcAec_ResampleLinear(aecpc->resampler, farend, nrOfSamples, aecpc->skew,
|
||||
new_farend, &newNrOfSamples);
|
||||
farend_ptr = new_farend;
|
||||
}
|
||||
|
||||
@ -368,21 +361,11 @@ int32_t WebRtcAec_Process(void* aecInst,
|
||||
|
||||
// This returns the value of aec->extended_filter_enabled.
|
||||
if (WebRtcAec_extended_filter_enabled(aecpc->aec)) {
|
||||
ProcessExtended(aecpc,
|
||||
nearend,
|
||||
num_bands,
|
||||
out,
|
||||
nrOfSamples,
|
||||
msInSndCardBuf,
|
||||
ProcessExtended(aecpc, nearend, num_bands, out, nrOfSamples, msInSndCardBuf,
|
||||
skew);
|
||||
} else {
|
||||
retVal = ProcessNormal(aecpc,
|
||||
nearend,
|
||||
num_bands,
|
||||
out,
|
||||
nrOfSamples,
|
||||
msInSndCardBuf,
|
||||
skew);
|
||||
retVal = ProcessNormal(aecpc, nearend, num_bands, out, nrOfSamples,
|
||||
msInSndCardBuf, skew);
|
||||
}
|
||||
|
||||
#ifdef WEBRTC_AEC_DEBUG_DUMP
|
||||
@ -390,8 +373,8 @@ int32_t WebRtcAec_Process(void* aecInst,
|
||||
int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) /
|
||||
(sampMsNb * aecpc->rate_factor));
|
||||
(void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile);
|
||||
(void)fwrite(
|
||||
&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, aecpc->delayFile);
|
||||
(void)fwrite(&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1,
|
||||
aecpc->delayFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -423,8 +406,8 @@ int WebRtcAec_set_config(void* handle, AecConfig config) {
|
||||
return AEC_BAD_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
WebRtcAec_SetConfigCore(
|
||||
self->aec, config.nlpMode, config.metricsMode, config.delay_logging);
|
||||
WebRtcAec_SetConfigCore(self->aec, config.nlpMode, config.metricsMode,
|
||||
config.delay_logging);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -552,8 +535,7 @@ int WebRtcAec_GetDelayMetrics(void* handle,
|
||||
return AEC_UNINITIALIZED_ERROR;
|
||||
}
|
||||
if (WebRtcAec_GetDelayMetricsCore(self->aec, median, std,
|
||||
fraction_poor_delays) ==
|
||||
-1) {
|
||||
fraction_poor_delays) == -1) {
|
||||
// Logging disabled.
|
||||
return AEC_UNSUPPORTED_FUNCTION_ERROR;
|
||||
}
|
||||
@ -561,7 +543,6 @@ int WebRtcAec_GetDelayMetrics(void* handle,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AecCore* WebRtcAec_aec_core(void* handle) {
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
@ -706,12 +687,8 @@ static int ProcessNormal(Aec* aecpc,
|
||||
// TODO(bjornv): Re-structure such that we don't have to pass
|
||||
// |aecpc->knownDelay| as input. Change name to something like
|
||||
// |system_buffer_diff|.
|
||||
WebRtcAec_ProcessFrames(aecpc->aec,
|
||||
nearend,
|
||||
num_bands,
|
||||
nrOfSamples,
|
||||
aecpc->knownDelay,
|
||||
out);
|
||||
WebRtcAec_ProcessFrames(aecpc->aec, nearend, num_bands, nrOfSamples,
|
||||
aecpc->knownDelay, out);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@ -785,12 +762,8 @@ static void ProcessExtended(Aec* self,
|
||||
const int adjusted_known_delay =
|
||||
WEBRTC_SPL_MAX(0, self->knownDelay + delay_diff_offset);
|
||||
|
||||
WebRtcAec_ProcessFrames(self->aec,
|
||||
near,
|
||||
num_bands,
|
||||
num_samples,
|
||||
adjusted_known_delay,
|
||||
out);
|
||||
WebRtcAec_ProcessFrames(self->aec, near, num_bands, num_samples,
|
||||
adjusted_known_delay, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,16 +25,9 @@
|
||||
// Warnings
|
||||
#define AEC_BAD_PARAMETER_WARNING 12050
|
||||
|
||||
enum {
|
||||
kAecNlpConservative = 0,
|
||||
kAecNlpModerate,
|
||||
kAecNlpAggressive
|
||||
};
|
||||
enum { kAecNlpConservative = 0, kAecNlpModerate, kAecNlpAggressive };
|
||||
|
||||
enum {
|
||||
kAecFalse = 0,
|
||||
kAecTrue
|
||||
};
|
||||
enum { kAecFalse = 0, kAecTrue };
|
||||
|
||||
typedef struct {
|
||||
int16_t nlpMode; // default kAecNlpModerate
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user