diff options
author | asapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-09-25 12:27:27 +0000 |
---|---|---|
committer | asapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-09-25 12:27:27 +0000 |
commit | 99b6d9e8699a1fa767e0b053b6c513efc45481a7 (patch) | |
tree | bbf1b49e8cd37610336141d3a850130af4710759 /modules/audio_processing/aec/echo_cancellation.c | |
parent | 83c5f62d323530e8f393eaa3ad3aaf26ef250b5d (diff) | |
download | webrtc-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.c | 537 |
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; } |