summaryrefslogtreecommitdiff
path: root/modules/audio_processing/aec/echo_cancellation.c
diff options
context:
space:
mode:
authorasapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-09-25 12:27:27 +0000
committerasapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-09-25 12:27:27 +0000
commit99b6d9e8699a1fa767e0b053b6c513efc45481a7 (patch)
treebbf1b49e8cd37610336141d3a850130af4710759 /modules/audio_processing/aec/echo_cancellation.c
parent83c5f62d323530e8f393eaa3ad3aaf26ef250b5d (diff)
downloadwebrtc-99b6d9e8699a1fa767e0b053b6c513efc45481a7.tar.gz
Revert 4837 "Add an extended filter mode to AEC."
> Add an extended filter mode to AEC. > > This mode extends the filter length from the current 48 ms to 128 ms. > It is runtime selectable which allows it to be enabled through > experiment. We reuse the DelayCorrection infrastructure to avoid having > to replumb everything up to libjingle. > > Increases AEC complexity by ~50% on modern x86 CPUs. > Measurements (in percent of usage on one core): > > Machine/CPU Normal Extended > MacBook Retina (Early 2013), > Core i7 Ivy Bridge (2.7 GHz, hyperthreaded) 0.6% 0.9% > > MacBook Air (Late 2010), Core 2 Duo (2.13 GHz) 1.4% 2.7% > > Chromebook Pixel, Core i5 Ivy Bridge (1.8 GHz) 0.6% 1.0% > > Samsung ARM Chromebook, > Samsung Exynos 5 Dual (1.7 GHz) 3.2% 5.6% > > The relative value is large of course but the absolute should be > acceptable in order to have a working AEC on some platforms. > > Detailed changes to the algorithm: > - The filter length is changed from 48 to 128 ms. This comes with tuning > of several parameters: i) filter adaptation stepsize and error > threshold; ii) non-linear processing smoothing and overdrive. > - Option to ignore the reported delays on platforms which we deem > sufficiently unreliable. Currently this will be enabled in Chromium for > Mac. > - Faster startup times by removing the excessive "startup phase" > processing of reported delays. > - Much more conservative adjustments to the far-end read pointer. We > smooth the delay difference more heavily, and back off from the > difference more. Adjustments force a readaptation of the filter, so they > should be avoided except when really necessary. > > Corresponds to these changes: > https://chromereviews.googleplex.com/9412014 > https://chromereviews.googleplex.com/9514013 > https://chromereviews.googleplex.com/9960013 > > BUG=454,827,1261 > R=bjornv@webrtc.org > > Review URL: https://webrtc-codereview.appspot.com/2151007 TBR=andrew@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2296005 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4839 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'modules/audio_processing/aec/echo_cancellation.c')
-rw-r--r--modules/audio_processing/aec/echo_cancellation.c537
1 files changed, 183 insertions, 354 deletions
diff --git a/modules/audio_processing/aec/echo_cancellation.c b/modules/audio_processing/aec/echo_cancellation.c
index 07bca559..2d413598 100644
--- a/modules/audio_processing/aec/echo_cancellation.c
+++ b/modules/audio_processing/aec/echo_cancellation.c
@@ -27,61 +27,6 @@
#include "webrtc/modules/audio_processing/utility/ring_buffer.h"
#include "webrtc/typedefs.h"
-// Measured delays [ms]
-// Device Chrome GTP
-// MacBook Air 10
-// MacBook Retina 10 100
-// MacPro 30?
-//
-// Win7 Desktop 70 80?
-// Win7 T430s 110
-// Win8 T420s 70
-//
-// Daisy 50
-// Pixel (w/ preproc?) 240
-// Pixel (w/o preproc?) 110 110
-
-// The extended filter mode gives us the flexibility to ignore the system's
-// reported delays. We do this for platforms which we believe provide results
-// which are incompatible with the AEC's expectations. Based on measurements
-// (some provided above) we set a conservative (i.e. lower than measured)
-// fixed delay.
-//
-// WEBRTC_UNTRUSTED_DELAY will only have an impact when |extended_filter_mode|
-// is enabled. See the note along with |DelayCorrection| in
-// echo_cancellation_impl.h for more details on the mode.
-//
-// Justification:
-// Chromium/Mac: Here, the true latency is so low (~10-20 ms), that it plays
-// havoc with the AEC's buffering. To avoid this, we set a fixed delay of 20 ms
-// and then compensate by rewinding by 10 ms (in wideband) through
-// kDelayDiffOffsetSamples. This trick does not seem to work for larger rewind
-// values, but fortunately this is sufficient.
-//
-// Chromium/Linux(ChromeOS): The values we get on this platform don't correspond
-// well to reality. The variance doesn't match the AEC's buffer changes, and the
-// bulk values tend to be too low. However, the range across different hardware
-// appears to be too large to choose a single value.
-//
-// GTP/Linux(ChromeOS): TBD, but for the moment we will trust the values.
-#if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_MAC)
-#define WEBRTC_UNTRUSTED_DELAY
-#endif
-
-#if defined(WEBRTC_MAC)
-static const int kFixedDelayMs = 20;
-static const int kDelayDiffOffsetSamples = -160;
-#elif defined(WEBRTC_WIN)
-static const int kFixedDelayMs = 50;
-static const int kDelayDiffOffsetSamples = 0;
-#else
-// Essentially ChromeOS.
-static const int kFixedDelayMs = 50;
-static const int kDelayDiffOffsetSamples = 0;
-#endif
-static const int kMinTrustedDelayMs = 20;
-static const int kMaxTrustedDelayMs = 500;
-
// Maximum length of resampled signal. Must be an integer multiple of frames
// (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN
// The factor of 2 handles wb, and the + 1 is as a safety margin
@@ -98,14 +43,7 @@ int webrtc_aec_instance_count = 0;
// Estimates delay to set the position of the far-end buffer read pointer
// (controlled by knownDelay)
-static void EstBufDelayNormal(aecpc_t *aecInst);
-static void EstBufDelayExtended(aecpc_t *aecInst);
-static int ProcessNormal(aecpc_t* self, const int16_t* near,
- const int16_t* near_high, int16_t* out, int16_t* out_high,
- int16_t num_samples, int16_t reported_delay_ms, int32_t skew);
-static void ProcessExtended(aecpc_t* self, const int16_t* near,
- const int16_t* near_high, int16_t* out, int16_t* out_high,
- int16_t num_samples, int16_t reported_delay_ms, int32_t skew);
+static int EstBufDelay(aecpc_t *aecInst);
int32_t WebRtcAec_Create(void **aecInst)
{
@@ -197,6 +135,10 @@ int32_t WebRtcAec_Init(void *aecInst, int32_t sampFreq, int32_t scSampFreq)
aecpc_t *aecpc = aecInst;
AecConfig aecConfig;
+ if (aecpc == NULL) {
+ return -1;
+ }
+
if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
@@ -235,31 +177,31 @@ int32_t WebRtcAec_Init(void *aecInst, int32_t sampFreq, int32_t scSampFreq)
aecpc->splitSampFreq = sampFreq;
}
+ aecpc->skewFrCtr = 0;
+ aecpc->activity = 0;
+
aecpc->delayCtr = 0;
- aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq;
- // Sampling frequency multiplier (SWB is processed as 160 frame size).
- aecpc->rate_factor = aecpc->splitSampFreq / 8000;
aecpc->sum = 0;
aecpc->counter = 0;
aecpc->checkBuffSize = 1;
aecpc->firstVal = 0;
- aecpc->startup_phase = 1;
+ aecpc->ECstartup = 1;
aecpc->bufSizeStart = 0;
aecpc->checkBufSizeCtr = 0;
- aecpc->msInSndCardBuf = 0;
- aecpc->filtDelay = -1; // -1 indicates an initialized state.
+ aecpc->filtDelay = 0;
aecpc->timeForDelayChange = 0;
aecpc->knownDelay = 0;
aecpc->lastDelayDiff = 0;
- aecpc->skewFrCtr = 0;
+ aecpc->skew = 0;
aecpc->resample = kAecFalse;
aecpc->highSkewCtr = 0;
- aecpc->skew = 0;
+ aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq;
- aecpc->farend_started = 0;
+ // Sampling frequency multiplier (SWB is processed as 160 frame size).
+ aecpc->rate_factor = aecpc->splitSampFreq / 8000;
// Default settings.
aecConfig.nlpMode = kAecNlpModerate;
@@ -297,6 +239,10 @@ int32_t WebRtcAec_BufferFarend(void *aecInst, const int16_t *farend,
float skew;
int i = 0;
+ if (aecpc == NULL) {
+ return -1;
+ }
+
if (farend == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
@@ -322,7 +268,6 @@ int32_t WebRtcAec_BufferFarend(void *aecInst, const int16_t *farend,
farend_ptr = (const int16_t*) newFarend;
}
- aecpc->farend_started = 1;
WebRtcAec_SetSystemDelay(aecpc->aec, WebRtcAec_system_delay(aecpc->aec) +
newNrOfSamples);
@@ -366,6 +311,17 @@ int32_t WebRtcAec_Process(void *aecInst, const int16_t *nearend,
{
aecpc_t *aecpc = aecInst;
int32_t retVal = 0;
+ short i;
+ short nBlocks10ms;
+ short nFrames;
+ // Limit resampling to doubling/halving of signal
+ const float minSkewEst = -0.5f;
+ const float maxSkewEst = 1.0f;
+
+ if (aecpc == NULL) {
+ return -1;
+ }
+
if (nearend == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
@@ -398,21 +354,144 @@ int32_t WebRtcAec_Process(void *aecInst, const int16_t *nearend,
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
}
- else if (msInSndCardBuf > kMaxTrustedDelayMs) {
- // The clamping is now done in ProcessExtended/Normal().
+ else if (msInSndCardBuf > 500) {
+ msInSndCardBuf = 500;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
}
+ // TODO(andrew): we need to investigate if this +10 is really wanted.
+ msInSndCardBuf += 10;
+ aecpc->msInSndCardBuf = msInSndCardBuf;
+
+ if (aecpc->skewMode == kAecTrue) {
+ if (aecpc->skewFrCtr < 25) {
+ aecpc->skewFrCtr++;
+ }
+ else {
+ retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
+ if (retVal == -1) {
+ aecpc->skew = 0;
+ aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
+ }
+
+ aecpc->skew /= aecpc->sampFactor*nrOfSamples;
+
+ if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
+ aecpc->resample = kAecFalse;
+ }
+ else {
+ aecpc->resample = kAecTrue;
+ }
+
+ if (aecpc->skew < minSkewEst) {
+ aecpc->skew = minSkewEst;
+ }
+ else if (aecpc->skew > maxSkewEst) {
+ aecpc->skew = maxSkewEst;
+ }
- // This returns the value of aec->extended_filter_enabled.
- if (WebRtcAec_delay_correction_enabled(aecpc->aec)) {
- ProcessExtended(aecpc, nearend, nearendH, out, outH, nrOfSamples,
- msInSndCardBuf, skew);
+#ifdef WEBRTC_AEC_DEBUG_DUMP
+ (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile);
+#endif
+ }
+ }
+
+ nFrames = nrOfSamples / FRAME_LEN;
+ nBlocks10ms = nFrames / aecpc->rate_factor;
+
+ if (aecpc->ECstartup) {
+ if (nearend != out) {
+ // Only needed if they don't already point to the same place.
+ memcpy(out, nearend, sizeof(short) * nrOfSamples);
+ }
+
+ // The AEC is in the start up mode
+ // AEC is disabled until the system delay is OK
+
+ // Mechanism to ensure that the system delay is reasonably stable.
+ if (aecpc->checkBuffSize) {
+ aecpc->checkBufSizeCtr++;
+ // Before we fill up the far-end buffer we require the system delay
+ // to be stable (+/-8 ms) compared to the first value. This
+ // comparison is made during the following 6 consecutive 10 ms
+ // blocks. If it seems to be stable then we start to fill up the
+ // far-end buffer.
+ if (aecpc->counter == 0) {
+ aecpc->firstVal = aecpc->msInSndCardBuf;
+ aecpc->sum = 0;
+ }
+
+ if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) <
+ WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) {
+ aecpc->sum += aecpc->msInSndCardBuf;
+ aecpc->counter++;
+ }
+ else {
+ aecpc->counter = 0;
+ }
+
+ if (aecpc->counter * nBlocks10ms >= 6) {
+ // The far-end buffer size is determined in partitions of
+ // PART_LEN samples. Use 75% of the average value of the system
+ // delay as buffer size to start with.
+ aecpc->bufSizeStart = WEBRTC_SPL_MIN((3 * aecpc->sum *
+ aecpc->rate_factor * 8) / (4 * aecpc->counter * PART_LEN),
+ kMaxBufSizeStart);
+ // Buffer size has now been determined.
+ aecpc->checkBuffSize = 0;
+ }
+
+ if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) {
+ // For really bad systems, don't disable the echo canceller for
+ // more than 0.5 sec.
+ aecpc->bufSizeStart = WEBRTC_SPL_MIN((aecpc->msInSndCardBuf *
+ aecpc->rate_factor * 3) / 40, kMaxBufSizeStart);
+ aecpc->checkBuffSize = 0;
+ }
+ }
+
+ // If |checkBuffSize| changed in the if-statement above.
+ if (!aecpc->checkBuffSize) {
+ // The system delay is now reasonably stable (or has been unstable
+ // for too long). When the far-end buffer is filled with
+ // approximately the same amount of data as reported by the system
+ // we end the startup phase.
+ int overhead_elements =
+ WebRtcAec_system_delay(aecpc->aec) / PART_LEN -
+ aecpc->bufSizeStart;
+ if (overhead_elements == 0) {
+ // Enable the AEC
+ aecpc->ECstartup = 0;
+ } else if (overhead_elements > 0) {
+ // TODO(bjornv): Do we need a check on how much we actually
+ // moved the read pointer? It should always be possible to move
+ // the pointer |overhead_elements| since we have only added data
+ // to the buffer and no delay compensation nor AEC processing
+ // has been done.
+ WebRtcAec_MoveFarReadPtr(aecpc->aec, overhead_elements);
+
+ // Enable the AEC
+ aecpc->ECstartup = 0;
+ }
+ }
} else {
- if (ProcessNormal(aecpc, nearend, nearendH, out, outH, nrOfSamples,
- msInSndCardBuf, skew) != 0) {
- retVal = -1;
- }
+ // AEC is enabled.
+
+ EstBufDelay(aecpc);
+
+ // Note that 1 frame is supported for NB and 2 frames for WB.
+ for (i = 0; i < nFrames; i++) {
+ // Call the AEC.
+ WebRtcAec_ProcessFrame(aecpc->aec,
+ &nearend[FRAME_LEN * i],
+ &nearendH[FRAME_LEN * i],
+ aecpc->knownDelay,
+ &out[FRAME_LEN * i],
+ &outH[FRAME_LEN * i]);
+ // TODO(bjornv): Re-structure such that we don't have to pass
+ // |aecpc->knownDelay| as input. Change name to something like
+ // |system_buffer_diff|.
+ }
}
#ifdef WEBRTC_AEC_DEBUG_DUMP
@@ -430,6 +509,11 @@ int32_t WebRtcAec_Process(void *aecInst, const int16_t *nearend,
int WebRtcAec_set_config(void* handle, AecConfig config) {
aecpc_t* self = (aecpc_t*)handle;
+
+ if (handle == NULL ) {
+ return -1;
+ }
+
if (self->initFlag != initCheck) {
self->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
@@ -464,6 +548,10 @@ int WebRtcAec_set_config(void* handle, AecConfig config) {
int WebRtcAec_get_echo_status(void* handle, int* status) {
aecpc_t* self = (aecpc_t*)handle;
+
+ if (handle == NULL ) {
+ return -1;
+ }
if (status == NULL ) {
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
@@ -577,6 +665,10 @@ int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics) {
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
aecpc_t* self = handle;
+
+ if (handle == NULL) {
+ return -1;
+ }
if (median == NULL) {
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
@@ -601,6 +693,11 @@ int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
int32_t WebRtcAec_get_error_code(void *aecInst)
{
aecpc_t *aecpc = aecInst;
+
+ if (aecpc == NULL) {
+ return -1;
+ }
+
return aecpc->lastError;
}
@@ -611,220 +708,7 @@ AecCore* WebRtcAec_aec_core(void* handle) {
return ((aecpc_t*) handle)->aec;
}
-static int ProcessNormal(aecpc_t *aecpc, const int16_t *nearend,
- const int16_t *nearendH, int16_t *out, int16_t *outH,
- int16_t nrOfSamples, int16_t msInSndCardBuf,
- int32_t skew) {
- int retVal = 0;
- short i;
- short nBlocks10ms;
- short nFrames;
- // Limit resampling to doubling/halving of signal
- const float minSkewEst = -0.5f;
- const float maxSkewEst = 1.0f;
-
- msInSndCardBuf = msInSndCardBuf > kMaxTrustedDelayMs ?
- kMaxTrustedDelayMs : msInSndCardBuf;
- // TODO(andrew): we need to investigate if this +10 is really wanted.
- msInSndCardBuf += 10;
- aecpc->msInSndCardBuf = msInSndCardBuf;
-
- if (aecpc->skewMode == kAecTrue) {
- if (aecpc->skewFrCtr < 25) {
- aecpc->skewFrCtr++;
- }
- else {
- retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
- if (retVal == -1) {
- aecpc->skew = 0;
- aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
- }
-
- aecpc->skew /= aecpc->sampFactor*nrOfSamples;
-
- if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
- aecpc->resample = kAecFalse;
- }
- else {
- aecpc->resample = kAecTrue;
- }
-
- if (aecpc->skew < minSkewEst) {
- aecpc->skew = minSkewEst;
- }
- else if (aecpc->skew > maxSkewEst) {
- aecpc->skew = maxSkewEst;
- }
-
-#ifdef WEBRTC_AEC_DEBUG_DUMP
- (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile);
-#endif
- }
- }
-
- nFrames = nrOfSamples / FRAME_LEN;
- nBlocks10ms = nFrames / aecpc->rate_factor;
-
- if (aecpc->startup_phase) {
- // Only needed if they don't already point to the same place.
- if (nearend != out) {
- memcpy(out, nearend, sizeof(short) * nrOfSamples);
- }
- if (nearendH != outH) {
- memcpy(outH, nearendH, sizeof(short) * nrOfSamples);
- }
-
- // The AEC is in the start up mode
- // AEC is disabled until the system delay is OK
-
- // Mechanism to ensure that the system delay is reasonably stable.
- if (aecpc->checkBuffSize) {
- aecpc->checkBufSizeCtr++;
- // Before we fill up the far-end buffer we require the system delay
- // to be stable (+/-8 ms) compared to the first value. This
- // comparison is made during the following 6 consecutive 10 ms
- // blocks. If it seems to be stable then we start to fill up the
- // far-end buffer.
- if (aecpc->counter == 0) {
- aecpc->firstVal = aecpc->msInSndCardBuf;
- aecpc->sum = 0;
- }
-
- if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) <
- WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) {
- aecpc->sum += aecpc->msInSndCardBuf;
- aecpc->counter++;
- }
- else {
- aecpc->counter = 0;
- }
-
- if (aecpc->counter * nBlocks10ms >= 6) {
- // The far-end buffer size is determined in partitions of
- // PART_LEN samples. Use 75% of the average value of the system
- // delay as buffer size to start with.
- aecpc->bufSizeStart = WEBRTC_SPL_MIN((3 * aecpc->sum *
- aecpc->rate_factor * 8) / (4 * aecpc->counter * PART_LEN),
- kMaxBufSizeStart);
- // Buffer size has now been determined.
- aecpc->checkBuffSize = 0;
- }
-
- if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) {
- // For really bad systems, don't disable the echo canceller for
- // more than 0.5 sec.
- aecpc->bufSizeStart = WEBRTC_SPL_MIN((aecpc->msInSndCardBuf *
- aecpc->rate_factor * 3) / 40, kMaxBufSizeStart);
- aecpc->checkBuffSize = 0;
- }
- }
-
- // If |checkBuffSize| changed in the if-statement above.
- if (!aecpc->checkBuffSize) {
- // The system delay is now reasonably stable (or has been unstable
- // for too long). When the far-end buffer is filled with
- // approximately the same amount of data as reported by the system
- // we end the startup phase.
- int overhead_elements =
- WebRtcAec_system_delay(aecpc->aec) / PART_LEN - aecpc->bufSizeStart;
- if (overhead_elements == 0) {
- // Enable the AEC
- aecpc->startup_phase = 0;
- } else if (overhead_elements > 0) {
- // TODO(bjornv): Do we need a check on how much we actually
- // moved the read pointer? It should always be possible to move
- // the pointer |overhead_elements| since we have only added data
- // to the buffer and no delay compensation nor AEC processing
- // has been done.
- WebRtcAec_MoveFarReadPtr(aecpc->aec, overhead_elements);
-
- // Enable the AEC
- aecpc->startup_phase = 0;
- }
- }
- } else {
- // AEC is enabled.
- EstBufDelayNormal(aecpc);
-
- // Note that 1 frame is supported for NB and 2 frames for WB.
- for (i = 0; i < nFrames; i++) {
- // Call the AEC.
- WebRtcAec_ProcessFrame(aecpc->aec,
- &nearend[FRAME_LEN * i],
- &nearendH[FRAME_LEN * i],
- aecpc->knownDelay,
- &out[FRAME_LEN * i],
- &outH[FRAME_LEN * i]);
- // TODO(bjornv): Re-structure such that we don't have to pass
- // |aecpc->knownDelay| as input. Change name to something like
- // |system_buffer_diff|.
- }
- }
-
- return retVal;
-}
-
-static void ProcessExtended(aecpc_t* self, const int16_t* near,
- const int16_t* near_high, int16_t* out, int16_t* out_high,
- int16_t num_samples, int16_t reported_delay_ms, int32_t skew) {
- int i;
- const int num_frames = num_samples / FRAME_LEN;
-#if defined(WEBRTC_UNTRUSTED_DELAY)
- const int delay_diff_offset = kDelayDiffOffsetSamples;
- reported_delay_ms = kFixedDelayMs;
-#else
- // This is the usual mode where we trust the reported system delay values.
- const int delay_diff_offset = 0;
- // Due to the longer filter, we no longer add 10 ms to the reported delay
- // to reduce chance of non-causality. Instead we apply a minimum here to avoid
- // issues with the read pointer jumping around needlessly.
- reported_delay_ms = reported_delay_ms < kMinTrustedDelayMs ?
- kMinTrustedDelayMs : reported_delay_ms;
- // If the reported delay appears to be bogus, we attempt to recover by using
- // the measured fixed delay values. We use >= here because higher layers
- // may already clamp to this maximum value, and we would otherwise not
- // detect it here.
- reported_delay_ms = reported_delay_ms >= kMaxTrustedDelayMs ?
- kFixedDelayMs : reported_delay_ms;
-#endif
- self->msInSndCardBuf = reported_delay_ms;
-
- if (!self->farend_started) {
- // Only needed if they don't already point to the same place.
- if (near != out) {
- memcpy(out, near, sizeof(short) * num_samples);
- }
- if (near_high != out_high) {
- memcpy(out_high, near_high, sizeof(short) * num_samples);
- }
- return;
- }
- if (self->startup_phase) {
- // In the extended mode, there isn't a startup "phase", just a special
- // action on the first frame. In the trusted delay case, we'll take the
- // current reported delay, unless it's less then our conservative
- // measurement.
- int startup_size_ms = reported_delay_ms < kFixedDelayMs ?
- kFixedDelayMs : reported_delay_ms;
- int overhead_elements = (WebRtcAec_system_delay(self->aec) -
- startup_size_ms / 2 * self->rate_factor * 8) / PART_LEN;
- WebRtcAec_MoveFarReadPtr(self->aec, overhead_elements);
- self->startup_phase = 0;
- }
-
- EstBufDelayExtended(self);
-
- for (i = 0; i < num_frames; ++i) {
- // |delay_diff_offset| gives us the option to manually rewind the delay on
- // very low delay platforms which can't be expressed purely through
- // |reported_delay_ms|.
- WebRtcAec_ProcessFrame(self->aec, &near[FRAME_LEN * i],
- &near_high[FRAME_LEN * i], self->knownDelay + delay_diff_offset,
- &out[FRAME_LEN * i], &out_high[FRAME_LEN * i]);
- }
-}
-
-static void EstBufDelayNormal(aecpc_t* aecpc) {
+static int EstBufDelay(aecpc_t* aecpc) {
int nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->rate_factor;
int current_delay = nSampSndCard - WebRtcAec_system_delay(aecpc->aec);
int delay_difference = 0;
@@ -848,11 +732,8 @@ static void EstBufDelayNormal(aecpc_t* aecpc) {
current_delay += WebRtcAec_MoveFarReadPtr(aecpc->aec, 1) * PART_LEN;
}
- // We use -1 to signal an initialized state in the "extended" implementation;
- // compensate for that.
- aecpc->filtDelay = aecpc->filtDelay < 0 ? 0 : aecpc->filtDelay;
aecpc->filtDelay = WEBRTC_SPL_MAX(0, (short) (0.8 * aecpc->filtDelay +
- 0.2 * current_delay));
+ 0.2 * current_delay));
delay_difference = aecpc->filtDelay - aecpc->knownDelay;
if (delay_difference > 224) {
@@ -875,58 +756,6 @@ static void EstBufDelayNormal(aecpc_t* aecpc) {
if (aecpc->timeForDelayChange > 25) {
aecpc->knownDelay = WEBRTC_SPL_MAX((int) aecpc->filtDelay - 160, 0);
}
-}
-
-static void EstBufDelayExtended(aecpc_t* self) {
- int reported_delay = self->msInSndCardBuf * sampMsNb * self->rate_factor;
- int current_delay = reported_delay - WebRtcAec_system_delay(self->aec);
- int delay_difference = 0;
- // Before we proceed with the delay estimate filtering we:
- // 1) Compensate for the frame that will be read.
- // 2) Compensate for drift resampling.
- // 3) Compensate for non-causality if needed, since the estimated delay can't
- // be negative.
-
- // 1) Compensating for the frame(s) that will be read/processed.
- current_delay += FRAME_LEN * self->rate_factor;
-
- // 2) Account for resampling frame delay.
- if (self->skewMode == kAecTrue && self->resample == kAecTrue) {
- current_delay -= kResamplingDelay;
- }
-
- // 3) Compensate for non-causality, if needed, by flushing two blocks.
- if (current_delay < PART_LEN) {
- current_delay += WebRtcAec_MoveFarReadPtr(self->aec, 2) * PART_LEN;
- }
-
- if (self->filtDelay == -1) {
- self->filtDelay = WEBRTC_SPL_MAX(0, 0.5 * current_delay);
- } else {
- self->filtDelay = WEBRTC_SPL_MAX(0, (short) (0.95 * self->filtDelay +
- 0.05 * current_delay));
- }
-
- delay_difference = self->filtDelay - self->knownDelay;
- if (delay_difference > 384) {
- if (self->lastDelayDiff < 128) {
- self->timeForDelayChange = 0;
- } else {
- self->timeForDelayChange++;
- }
- } else if (delay_difference < 128 && self->knownDelay > 0) {
- if (self->lastDelayDiff > 384) {
- self->timeForDelayChange = 0;
- } else {
- self->timeForDelayChange++;
- }
- } else {
- self->timeForDelayChange = 0;
- }
- self->lastDelayDiff = delay_difference;
-
- if (self->timeForDelayChange > 25) {
- self->knownDelay = WEBRTC_SPL_MAX((int) self->filtDelay - 256, 0);
- }
+ return 0;
}