From 61ec7daa57969564e23b5b596a1a2538f6a65c6f Mon Sep 17 00:00:00 2001 From: "bjornv@webrtc.org" Date: Tue, 29 Jan 2013 18:55:59 +0000 Subject: [PATCH] Delay estimator wrapper API changes. This should finalize the changes to delay estimator making it work for multi-probe. The changes are summarized here: delay_estimator.* ----------------- Replaced assert() with correct error check. This is consistent with previous versions of the delay_estimator, i.e., to check for valid parameters where they are actually used and not high up in a wrapper layer. delay_estimator_internal.h -------------------------- Pulled out the far-end part of DelayEstimator struct and put it in DelayEstimatorFarend. The only common parameter is spectrum_size, which we store in both and thereby avoiding having a Farend pointer in DelayEstimator. delay_estimator_wrapper.* ------------------------- Added and updated descriptions. From Free(), Create(), Init() the far-end parts have been put in separate Farend versions. Same goes for the Process() which now has an AddFarSpectrum() version. The flow of calls should be something like (in pseudo-code) far* = CreateFarend(history_size) near* = Create(far, lookahead) InitFarend(far) Init(near) while call ongoing AddFarSpectrum(far, far_spectrum) Process(near, near_spectrum) end while Free(near) FreeFarend(far) delay_estimator_unittest.cc --------------------------- Added farend support setting up calls as mentioned above. aecm_core.* ----------- Cleaned up some lint warnings. Added delay_estimator_farend pointer. Called Create(), Init() and Free() in above mentioned order. If AddFarSpectrumFix() was not successfully done, we end and return -1. This is what we would have done for Process(). aec_core.* ---------- Cleaned up some lint warnings. Added delay_estimator_farend pointer. Calls in proper order. Since we only use the delay estimator for logging there is no error handling. We only call Process() if AddFarSpectrum() was successful though. TEST=audioproc_unittest, trybots BUG=None Review URL: https://webrtc-codereview.appspot.com/1076006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3428 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../modules/audio_processing/aec/aec_core.c | 34 ++- .../modules/audio_processing/aec/aec_core.h | 37 +-- .../modules/audio_processing/aecm/aecm_core.c | 37 ++- .../modules/audio_processing/aecm/aecm_core.h | 71 +++--- .../utility/delay_estimator.c | 9 +- .../utility/delay_estimator.h | 8 +- .../utility/delay_estimator_internal.h | 21 +- .../utility/delay_estimator_unittest.cc | 151 ++++++++---- .../utility/delay_estimator_wrapper.c | 223 ++++++++++++------ .../utility/delay_estimator_wrapper.h | 89 +++++-- 10 files changed, 452 insertions(+), 228 deletions(-) diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c index 1f3123f9a..191a5058c 100644 --- a/webrtc/modules/audio_processing/aec/aec_core.c +++ b/webrtc/modules/audio_processing/aec/aec_core.c @@ -206,9 +206,16 @@ int WebRtcAec_CreateAec(aec_t **aecInst) return -1; } #endif - aec->delay_estimator = WebRtc_CreateDelayEstimator(PART_LEN1, - kMaxDelayBlocks, - kLookaheadBlocks); + aec->delay_estimator_farend = + WebRtc_CreateDelayEstimatorFarend(PART_LEN1, kHistorySizeBlocks); + if (aec->delay_estimator_farend == NULL) { + WebRtcAec_FreeAec(aec); + aec = NULL; + return -1; + } + aec->delay_estimator = + WebRtc_CreateDelayEstimator(aec->delay_estimator_farend, + kLookaheadBlocks); if (aec->delay_estimator == NULL) { WebRtcAec_FreeAec(aec); aec = NULL; @@ -236,6 +243,7 @@ int WebRtcAec_FreeAec(aec_t *aec) WebRtc_FreeBuffer(aec->far_time_buf); #endif WebRtc_FreeDelayEstimator(aec->delay_estimator); + WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); free(aec); return 0; @@ -428,6 +436,9 @@ int WebRtcAec_InitAec(aec_t *aec, int sampFreq) #endif aec->system_delay = 0; + if (WebRtc_InitDelayEstimatorFarend(aec->delay_estimator_farend) != 0) { + return -1; + } if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) { return -1; } @@ -748,14 +759,15 @@ static void ProcessBlock(aec_t* aec) { // Block wise delay estimation used for logging if (aec->delay_logging_enabled) { int delay_estimate = 0; - // Estimate the delay - delay_estimate = WebRtc_DelayEstimatorProcessFloat(aec->delay_estimator, - abs_far_spectrum, - abs_near_spectrum, - PART_LEN1); - if (delay_estimate >= 0) { - // Update delay estimate buffer. - aec->delay_histogram[delay_estimate]++; + if (WebRtc_AddFarSpectrumFloat(aec->delay_estimator_farend, + abs_far_spectrum, PART_LEN1) == 0) { + delay_estimate = WebRtc_DelayEstimatorProcessFloat(aec->delay_estimator, + abs_near_spectrum, + PART_LEN1); + if (delay_estimate >= 0) { + // Update delay estimate buffer. + aec->delay_histogram[delay_estimate]++; + } } } diff --git a/webrtc/modules/audio_processing/aec/aec_core.h b/webrtc/modules/audio_processing/aec/aec_core.h index c07528d64..43b69b316 100644 --- a/webrtc/modules/audio_processing/aec/aec_core.h +++ b/webrtc/modules/audio_processing/aec/aec_core.h @@ -19,12 +19,12 @@ #include #endif -#include "typedefs.h" +#include "webrtc/typedefs.h" #define FRAME_LEN 80 -#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 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 NR_PART 12 // Number of partitions in filter. #define PREF_BAND_SIZE 24 @@ -79,10 +79,10 @@ typedef struct { void *nearFrBufH; void *outFrBufH; - float dBuf[PART_LEN2]; // nearend - float eBuf[PART_LEN2]; // error + float dBuf[PART_LEN2]; // nearend + float eBuf[PART_LEN2]; // error - float dBufH[PART_LEN2]; // nearend + float dBufH[PART_LEN2]; // nearend float xPow[PART_LEN1]; float dPow[PART_LEN1]; @@ -90,13 +90,13 @@ typedef struct { float dInitMinPow[PART_LEN1]; float *noisePow; - float xfBuf[2][NR_PART * PART_LEN1]; // farend fft buffer - float wfBuf[2][NR_PART * PART_LEN1]; // filter fft - complex_t sde[PART_LEN1]; // cross-psd of nearend and error - complex_t sxd[PART_LEN1]; // cross-psd of farend and nearend - complex_t xfwBuf[NR_PART * PART_LEN1]; // farend windowed fft buffer + float xfBuf[2][NR_PART * PART_LEN1]; // farend fft buffer + float wfBuf[2][NR_PART * PART_LEN1]; // filter fft + complex_t sde[PART_LEN1]; // cross-psd of nearend and error + complex_t sxd[PART_LEN1]; // cross-psd of farend and nearend + complex_t xfwBuf[NR_PART * PART_LEN1]; // farend windowed fft buffer - float sx[PART_LEN1], sd[PART_LEN1], se[PART_LEN1]; // far, near and error psd + float sx[PART_LEN1], sd[PART_LEN1], se[PART_LEN1]; // far, near, error psd float hNs[PART_LEN1]; float hNlFbMin, hNlFbLocalMin; float hNlXdAvgMin; @@ -119,8 +119,8 @@ typedef struct { int sampFreq; WebRtc_UWord32 seed; - float mu; // stepsize - float errThresh; // error threshold + float mu; // stepsize + float errThresh; // error threshold int noiseEstCtr; @@ -137,12 +137,13 @@ typedef struct { stats_t rerl; // Quantities to control H band scaling for SWB input - int freq_avg_ic; //initial bin for averaging nlp gain - int flag_Hband_cn; //for comfort noise - float cn_scale_Hband; //scale for comfort noise in H band + int freq_avg_ic; // initial bin for averaging nlp gain + int flag_Hband_cn; // for comfort noise + float cn_scale_Hband; // scale for comfort noise in H band int delay_histogram[kHistorySizeBlocks]; int delay_logging_enabled; + void* delay_estimator_farend; void* delay_estimator; #ifdef WEBRTC_AEC_DEBUG_DUMP diff --git a/webrtc/modules/audio_processing/aecm/aecm_core.c b/webrtc/modules/audio_processing/aecm/aecm_core.c index 28eb4f232..a81912e46 100644 --- a/webrtc/modules/audio_processing/aecm/aecm_core.c +++ b/webrtc/modules/audio_processing/aecm/aecm_core.c @@ -8,19 +8,19 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "aecm_core.h" +#include "webrtc/modules/audio_processing/aecm/aecm_core.h" #include #include #include -#include "common_audio/signal_processing/include/real_fft.h" -#include "cpu_features_wrapper.h" -#include "delay_estimator_wrapper.h" -#include "echo_control_mobile.h" -#include "ring_buffer.h" -#include "system_wrappers/interface/compile_assert.h" -#include "typedefs.h" +#include "webrtc/common_audio/signal_processing/include/real_fft.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" +#include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h" +#include "webrtc/modules/audio_processing/utility/ring_buffer.h" +#include "webrtc/system_wrappers/interface/compile_assert.h" +#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" +#include "webrtc/typedefs.h" #ifdef AEC_DEBUG FILE *dfile; @@ -288,8 +288,15 @@ int WebRtcAecm_CreateCore(AecmCore_t **aecmInst) return -1; } - aecm->delay_estimator = WebRtc_CreateDelayEstimator(PART_LEN1, MAX_DELAY, - 0); + aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1, + MAX_DELAY); + if (aecm->delay_estimator_farend == NULL) { + WebRtcAecm_FreeCore(aecm); + aecm = NULL; + return -1; + } + aecm->delay_estimator = + WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0); if (aecm->delay_estimator == NULL) { WebRtcAecm_FreeCore(aecm); aecm = NULL; @@ -565,6 +572,9 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq) aecm->seed = 666; aecm->totCount = 0; + if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) { + return -1; + } if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) { return -1; } @@ -682,6 +692,7 @@ int WebRtcAecm_FreeCore(AecmCore_t *aecm) WebRtc_FreeBuffer(aecm->outFrameBuf); WebRtc_FreeDelayEstimator(aecm->delay_estimator); + WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend); WebRtcSpl_FreeRealFFT(aecm->real_fft); free(aecm); @@ -1592,11 +1603,13 @@ int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, // Get the delay // Save far-end history and estimate delay UpdateFarHistory(aecm, xfa, far_q); + if (WebRtc_AddFarSpectrumFix(aecm->delay_estimator_farend, xfa, PART_LEN1, + far_q) == -1) { + return -1; + } delay = WebRtc_DelayEstimatorProcessFix(aecm->delay_estimator, - xfa, dfaNoisy, PART_LEN1, - far_q, zerosDBufNoisy); if (delay == -1) { diff --git a/webrtc/modules/audio_processing/aecm/aecm_core.h b/webrtc/modules/audio_processing/aecm/aecm_core.h index 3e0816fba..1038258d6 100644 --- a/webrtc/modules/audio_processing/aecm/aecm_core.h +++ b/webrtc/modules/audio_processing/aecm/aecm_core.h @@ -17,10 +17,10 @@ #include "modules/audio_processing/aecm/aecm_defines.h" #include "typedefs.h" -#ifdef _MSC_VER // visual c++ +#ifdef _MSC_VER // visual c++ #define ALIGN8_BEG __declspec(align(8)) #define ALIGN8_END -#else // gcc or icc +#else // gcc or icc #define ALIGN8_BEG #define ALIGN8_END __attribute__((aligned(8))) #endif @@ -30,13 +30,12 @@ typedef struct { WebRtc_Word16 imag; } complex16_t; -typedef struct -{ +typedef struct { int farBufWritePos; int farBufReadPos; int knownDelay; int lastKnownDelay; - int firstVAD; // Parameter to control poorly initialized channels + int firstVAD; // Parameter to control poorly initialized channels void *farFrameBuf; void *nearNoisyFrameBuf; @@ -49,6 +48,7 @@ typedef struct WebRtc_UWord32 seed; // Delay estimation variables + void* delay_estimator_farend; void* delay_estimator; WebRtc_UWord16 currentDelay; // Far end history variables @@ -72,15 +72,16 @@ typedef struct WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN]; WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN]; - // The extra 16 or 32 bytes in the following buffers are for alignment based Neon code. - // It's designed this way since the current GCC compiler can't align a buffer in 16 or 32 - // byte boundaries properly. + // The extra 16 or 32 bytes in the following buffers are for alignment based + // Neon code. + // It's designed this way since the current GCC compiler can't align a + // buffer in 16 or 32 byte boundaries properly. WebRtc_Word16 channelStored_buf[PART_LEN1 + 8]; WebRtc_Word16 channelAdapt16_buf[PART_LEN1 + 8]; WebRtc_Word32 channelAdapt32_buf[PART_LEN1 + 8]; - WebRtc_Word16 xBuf_buf[PART_LEN2 + 16]; // farend - WebRtc_Word16 dBufClean_buf[PART_LEN2 + 16]; // nearend - WebRtc_Word16 dBufNoisy_buf[PART_LEN2 + 16]; // nearend + WebRtc_Word16 xBuf_buf[PART_LEN2 + 16]; // farend + WebRtc_Word16 dBufClean_buf[PART_LEN2 + 16]; // nearend + WebRtc_Word16 dBufNoisy_buf[PART_LEN2 + 16]; // nearend WebRtc_Word16 outBuf_buf[PART_LEN + 8]; // Pointers to the above buffers @@ -131,7 +132,7 @@ typedef struct #endif } AecmCore_t; -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_CreateCore(...) // // Allocates the memory needed by the AECM. The memory needs to be @@ -148,10 +149,11 @@ typedef struct // int WebRtcAecm_CreateCore(AecmCore_t **aecm); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_InitCore(...) // -// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...) +// This function initializes the AECM instant created with +// WebRtcAecm_CreateCore(...) // Input: // - aecm : Pointer to the AECM instance // - samplingFreq : Sampling Frequency @@ -164,7 +166,7 @@ int WebRtcAecm_CreateCore(AecmCore_t **aecm); // int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_FreeCore(...) // // This function releases the memory allocated by WebRtcAecm_CreateCore() @@ -179,29 +181,34 @@ int WebRtcAecm_FreeCore(AecmCore_t *aecm); int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_InitEchoPathCore(...) // // This function resets the echo channel adaptation with the specified channel. // Input: // - aecm : Pointer to the AECM instance -// - echo_path : Pointer to the data that should initialize the echo path +// - echo_path : Pointer to the data that should initialize the echo +// path // // Output: // - aecm : Initialized instance // -void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path); +void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, + const WebRtc_Word16* echo_path); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_ProcessFrame(...) // -// This function processes frames and sends blocks to WebRtcAecm_ProcessBlock(...) +// This function processes frames and sends blocks to +// WebRtcAecm_ProcessBlock(...) // // Inputs: // - aecm : Pointer to the AECM instance // - farend : In buffer containing one frame of echo signal -// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS -// - nearendClean : In buffer containing one frame of nearend+echo signal with NS +// - nearendNoisy : In buffer containing one frame of nearend+echo signal +// without NS +// - nearendClean : In buffer containing one frame of nearend+echo signal +// with NS // // Output: // - out : Out buffer, one frame of nearend signal : @@ -212,7 +219,7 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const WebRtc_Word16 * farend, const WebRtc_Word16 * nearendClean, WebRtc_Word16 * out); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_ProcessBlock(...) // // This function is called for every block within one frame @@ -221,8 +228,10 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const WebRtc_Word16 * farend, // Inputs: // - aecm : Pointer to the AECM instance // - farend : In buffer containing one block of echo signal -// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS -// - nearendClean : In buffer containing one frame of nearend+echo signal with NS +// - nearendNoisy : In buffer containing one frame of nearend+echo signal +// without NS +// - nearendClean : In buffer containing one frame of nearend+echo signal +// with NS // // Output: // - out : Out buffer, one block of nearend signal : @@ -233,7 +242,7 @@ int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const WebRtc_Word16 * farend, const WebRtc_Word16 * noisyClean, WebRtc_Word16 * out); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_BufferFarFrame() // // Inserts a frame of data into farend buffer. @@ -243,10 +252,11 @@ int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const WebRtc_Word16 * farend, // - farend : In buffer containing one frame of farend signal // - farLen : Length of frame // -void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend, +void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, + const WebRtc_Word16 * const farend, const int farLen); -/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // WebRtcAecm_FetchFarFrame() // // Read the farend buffer to account for known delay @@ -257,11 +267,12 @@ void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * co // - farLen : Length of frame // - knownDelay : known delay // -void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend, +void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, + WebRtc_Word16 * const farend, const int farLen, const int knownDelay); /////////////////////////////////////////////////////////////////////////////// -// Some function pointers, for internal functions shared by ARM NEON and +// Some function pointers, for internal functions shared by ARM NEON and // generic C code. // typedef void (*CalcLinearEnergies)( diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.c b/webrtc/modules/audio_processing/utility/delay_estimator.c index 2ef5c5f35..bcbb00aa8 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator.c +++ b/webrtc/modules/audio_processing/utility/delay_estimator.c @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "delay_estimator.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator.h" #include #include @@ -76,9 +76,12 @@ void WebRtc_FreeBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self) { BinaryDelayEstimatorFarend* WebRtc_CreateBinaryDelayEstimatorFarend( int history_size) { - BinaryDelayEstimatorFarend* self = malloc(sizeof(BinaryDelayEstimatorFarend)); + BinaryDelayEstimatorFarend* self = NULL; - assert(history_size > 1); + if (history_size > 1) { + // Sanity conditions fulfilled. + self = malloc(sizeof(BinaryDelayEstimatorFarend)); + } if (self != NULL) { int malloc_fail = 0; diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.h b/webrtc/modules/audio_processing/utility/delay_estimator.h index 11468f289..bf2b08a21 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator.h +++ b/webrtc/modules/audio_processing/utility/delay_estimator.h @@ -14,14 +14,13 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_ -#include "typedefs.h" +#include "webrtc/typedefs.h" typedef struct { // Pointer to bit counts. int* far_bit_counts; // Binary history variables. uint32_t* binary_far_history; - // Buffer size. int history_size; } BinaryDelayEstimatorFarend; @@ -34,6 +33,7 @@ typedef struct { // Binary history variables. uint32_t* binary_near_history; + int near_history_size; // Delay estimation variables. int32_t minimum_probability; @@ -42,8 +42,6 @@ typedef struct { // Delay memory. int last_delay; - // Near-end buffer size. - int near_history_size; // Far-end binary spectrum history buffer etc. BinaryDelayEstimatorFarend* farend; } BinaryDelayEstimator; @@ -94,7 +92,7 @@ void WebRtc_InitBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self); // - binary_far_spectrum : Far-end binary spectrum. // // Output: -// - handle : Updated far-end instance. +// - self : Updated far-end instance. // void WebRtc_AddBinaryFarSpectrum(BinaryDelayEstimatorFarend* self, uint32_t binary_far_spectrum); diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_internal.h b/webrtc/modules/audio_processing/utility/delay_estimator_internal.h index 43bbc4d01..fd11028fd 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator_internal.h +++ b/webrtc/modules/audio_processing/utility/delay_estimator_internal.h @@ -13,8 +13,8 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ -#include "modules/audio_processing/utility/delay_estimator.h" -#include "typedefs.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator.h" +#include "webrtc/typedefs.h" typedef union { float float_; @@ -24,18 +24,25 @@ typedef union { typedef struct { // Pointers to mean values of spectrum. SpectrumType* mean_far_spectrum; - SpectrumType* mean_near_spectrum; - // |mean_*_spectrum| initialization indicator. + // |mean_far_spectrum| initialization indicator. int far_spectrum_initialized; + + int spectrum_size; + + // Far-end part of binary spectrum based delay estimation. + BinaryDelayEstimatorFarend* binary_farend; +} DelayEstimatorFarend; + +typedef struct { + // Pointers to mean values of spectrum. + SpectrumType* mean_near_spectrum; + // |mean_near_spectrum| initialization indicator. int near_spectrum_initialized; int spectrum_size; // Binary spectrum based delay estimator BinaryDelayEstimator* binary_handle; - // TODO(bjornv): This is an intermediate member variable. To be removed when - // we complete full support. - BinaryDelayEstimatorFarend* binary_farend; } DelayEstimator; #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc index 27f883272..ac3bc1646 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc +++ b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc @@ -11,11 +11,11 @@ #include "gtest/gtest.h" extern "C" { -#include "modules/audio_processing/utility/delay_estimator.h" -#include "modules/audio_processing/utility/delay_estimator_internal.h" -#include "modules/audio_processing/utility/delay_estimator_wrapper.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator_internal.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" } -#include "typedefs.h" +#include "webrtc/typedefs.h" namespace { @@ -42,6 +42,8 @@ class DelayEstimatorTest : public ::testing::Test { void* handle_; DelayEstimator* self_; + void* farend_handle_; + DelayEstimatorFarend* farend_self_; BinaryDelayEstimator* binary_; BinaryDelayEstimatorFarend* binary_farend_; int spectrum_size_; @@ -56,6 +58,8 @@ class DelayEstimatorTest : public ::testing::Test { DelayEstimatorTest::DelayEstimatorTest() : handle_(NULL), self_(NULL), + farend_handle_(NULL), + farend_self_(NULL), binary_(NULL), binary_farend_(NULL), spectrum_size_(kSpectrumSize) { @@ -74,7 +78,11 @@ DelayEstimatorTest::DelayEstimatorTest() } void DelayEstimatorTest::SetUp() { - handle_ = WebRtc_CreateDelayEstimator(kSpectrumSize, kMaxDelay, kLookahead); + farend_handle_ = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize, + kMaxDelay + kLookahead); + ASSERT_TRUE(farend_handle_ != NULL); + farend_self_ = reinterpret_cast(farend_handle_); + handle_ = WebRtc_CreateDelayEstimator(farend_handle_, kLookahead); ASSERT_TRUE(handle_ != NULL); self_ = reinterpret_cast(handle_); binary_farend_ = WebRtc_CreateBinaryDelayEstimatorFarend(kMaxDelay + @@ -88,6 +96,9 @@ void DelayEstimatorTest::TearDown() { WebRtc_FreeDelayEstimator(handle_); handle_ = NULL; self_ = NULL; + WebRtc_FreeDelayEstimatorFarend(farend_handle_); + farend_handle_ = NULL; + farend_self_ = NULL; WebRtc_FreeBinaryDelayEstimator(binary_); binary_ = NULL; WebRtc_FreeBinaryDelayEstimatorFarend(binary_farend_); @@ -96,9 +107,10 @@ void DelayEstimatorTest::TearDown() { void DelayEstimatorTest::Init() { // Initialize Delay Estimator + EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_)); EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_)); // Verify initialization. - EXPECT_EQ(0, self_->far_spectrum_initialized); + EXPECT_EQ(0, farend_self_->far_spectrum_initialized); EXPECT_EQ(0, self_->near_spectrum_initialized); EXPECT_EQ(-2, WebRtc_last_delay(handle_)); // Delay in initial state. EXPECT_EQ(0, WebRtc_last_delay_quality(handle_)); // Zero quality. @@ -187,59 +199,78 @@ void DelayEstimatorTest::RunBinarySpectraTest(int near_offset, TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfWrapper) { // In this test we verify correct error returns on invalid API calls. - // WebRtc_CreateDelayEstimator() should return a NULL pointer on invalid input - // values. + // WebRtc_CreateDelayEstimatorFarend() and WebRtc_CreateDelayEstimator() + // should return a NULL pointer on invalid input values. // Make sure we have a non-NULL value at start, so we can detect NULL after // create failure. - void* handle = handle_; - handle = WebRtc_CreateDelayEstimator(33, kMaxDelay, kLookahead); + void* handle = farend_handle_; + handle = WebRtc_CreateDelayEstimatorFarend(33, kMaxDelay + kLookahead); EXPECT_TRUE(handle == NULL); - handle = handle_; - handle = WebRtc_CreateDelayEstimator(kSpectrumSize, kMaxDelay, -1); - EXPECT_TRUE(handle == NULL); - handle = handle_; - handle = WebRtc_CreateDelayEstimator(kSpectrumSize, 0, 0); + handle = farend_handle_; + handle = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize, 1); EXPECT_TRUE(handle == NULL); - // WebRtc_InitDelayEstimator() should return -1 if we have a NULL pointer as - // |handle|. + handle = handle_; + handle = WebRtc_CreateDelayEstimator(NULL, kLookahead); + EXPECT_TRUE(handle == NULL); + handle = handle_; + handle = WebRtc_CreateDelayEstimator(farend_handle_, -1); + EXPECT_TRUE(handle == NULL); + + // WebRtc_InitDelayEstimatorFarend() and WebRtc_InitDelayEstimator() should + // return -1 if we have a NULL pointer as |handle|. + EXPECT_EQ(-1, WebRtc_InitDelayEstimatorFarend(NULL)); EXPECT_EQ(-1, WebRtc_InitDelayEstimator(NULL)); + // WebRtc_AddFarSpectrumFloat() should return -1 if we have: + // 1) NULL pointer as |handle|. + // 2) NULL pointer as far-end spectrum. + // 3) Incorrect spectrum size. + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(NULL, far_f_, spectrum_size_)); + // Use |farend_handle_| which is properly created at SetUp(). + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(farend_handle_, NULL, + spectrum_size_)); + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_, + spectrum_size_ + 1)); + + // WebRtc_AddFarSpectrumFix() should return -1 if we have: + // 1) NULL pointer as |handle|. + // 2) NULL pointer as far-end spectrum. + // 3) Incorrect spectrum size. + // 4) Too high precision in far-end spectrum (Q-domain > 15). + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(NULL, far_u16_, spectrum_size_, 0)); + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, NULL, spectrum_size_, + 0)); + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_, + spectrum_size_ + 1, 0)); + EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_, + spectrum_size_, 16)); + // WebRtc_DelayEstimatorProcessFloat() should return -1 if we have: // 1) NULL pointer as |handle|. - // 2) NULL pointer as far-end spectrum. - // 3) NULL pointer as near-end spectrum. - // 4) Incorrect spectrum size. - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(NULL, far_f_, near_f_, + // 2) NULL pointer as near-end spectrum. + // 3) Incorrect spectrum size. + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(NULL, near_f_, spectrum_size_)); // Use |handle_| which is properly created at SetUp(). - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, NULL, near_f_, + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, NULL, spectrum_size_)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, NULL, - spectrum_size_)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_, + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, near_f_, spectrum_size_ + 1)); // WebRtc_DelayEstimatorProcessFix() should return -1 if we have: // 1) NULL pointer as |handle|. - // 2) NULL pointer as far-end spectrum. // 3) NULL pointer as near-end spectrum. // 4) Incorrect spectrum size. - // 5) Too high precision in far-end spectrum (Q-domain > 15). // 6) Too high precision in near-end spectrum (Q-domain > 15). - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(NULL, far_u16_, near_u16_, - spectrum_size_, 0, 0)); - // Use |handle_| which is properly created at SetUp(). - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, NULL, near_u16_, - spectrum_size_, 0, 0)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, NULL, - spectrum_size_, 0, 0)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_, - spectrum_size_ + 1, 0, 0)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_, - spectrum_size_, 16, 0)); - EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_, - spectrum_size_, 0, 16)); + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(NULL, near_u16_, spectrum_size_, + 0)); + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, NULL, spectrum_size_, + 0)); + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_, + spectrum_size_ + 1, 0)); + EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_, + spectrum_size_, 16)); // WebRtc_last_delay() should return -1 if we have a NULL pointer as |handle|. EXPECT_EQ(-1, WebRtc_last_delay(NULL)); @@ -254,22 +285,26 @@ TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfWrapper) { TEST_F(DelayEstimatorTest, InitializedSpectrumAfterProcess) { // In this test we verify that the mean spectra are initialized after first - // time we call Process(). + // time we call WebRtc_AddFarSpectrum() and Process() respectively. // For floating point operations, process one frame and verify initialization // flag. Init(); - EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_, + EXPECT_EQ(0, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_, + spectrum_size_)); + EXPECT_EQ(1, farend_self_->far_spectrum_initialized); + EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFloat(handle_, near_f_, spectrum_size_)); - EXPECT_EQ(1, self_->far_spectrum_initialized); EXPECT_EQ(1, self_->near_spectrum_initialized); // For fixed point operations, process one frame and verify initialization // flag. Init(); - EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_, - spectrum_size_, 0, 0)); - EXPECT_EQ(1, self_->far_spectrum_initialized); + EXPECT_EQ(0, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_, + spectrum_size_, 0)); + EXPECT_EQ(1, farend_self_->far_spectrum_initialized); + EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_, + spectrum_size_, 0)); EXPECT_EQ(1, self_->near_spectrum_initialized); } @@ -283,7 +318,9 @@ TEST_F(DelayEstimatorTest, CorrectLastDelay) { // Floating point operations. Init(); for (int i = 0; i < 200; i++) { - last_delay = WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_, + EXPECT_EQ(0, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_, + spectrum_size_)); + last_delay = WebRtc_DelayEstimatorProcessFloat(handle_, near_f_, spectrum_size_); if (last_delay != -2) { EXPECT_EQ(last_delay, WebRtc_last_delay(handle_)); @@ -298,8 +335,10 @@ TEST_F(DelayEstimatorTest, CorrectLastDelay) { // Fixed point operations. Init(); for (int i = 0; i < 200; i++) { - last_delay = WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_, - spectrum_size_, 0, 0); + EXPECT_EQ(0, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_, + spectrum_size_, 0)); + last_delay = WebRtc_DelayEstimatorProcessFix(handle_, near_u16_, + spectrum_size_, 0); if (last_delay != -2) { EXPECT_EQ(last_delay, WebRtc_last_delay(handle_)); EXPECT_EQ(7203, WebRtc_last_delay_quality(handle_)); @@ -311,6 +350,20 @@ TEST_F(DelayEstimatorTest, CorrectLastDelay) { EXPECT_NE(0, WebRtc_last_delay_quality(handle_)); } +TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimatorFarend) { + // In this test we verify correct output on invalid API calls to the Binary + // Delay Estimator (far-end part). + + BinaryDelayEstimatorFarend* binary = binary_farend_; + // WebRtc_CreateBinaryDelayEstimatorFarend() should return -1 if the input + // history size is less than 2. This is to make sure the buffer shifting + // applies properly. + // Make sure we have a non-NULL value at start, so we can detect NULL after + // create failure. + binary = WebRtc_CreateBinaryDelayEstimatorFarend(1); + EXPECT_TRUE(binary == NULL); +} + TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimator) { // In this test we verify correct output on invalid API calls to the Binary // Delay Estimator. diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c index a00923f66..c358f1383 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c +++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c @@ -8,19 +8,20 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "delay_estimator_wrapper.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" #include #include #include -#include "delay_estimator.h" -#include "modules/audio_processing/utility/delay_estimator_internal.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator.h" +#include "webrtc/modules/audio_processing/utility/delay_estimator_internal.h" +#include "webrtc/system_wrappers/interface/compile_assert.h" // Only bit |kBandFirst| through bit |kBandLast| are processed and // |kBandFirst| - |kBandLast| must be < 32. -static const int kBandFirst = 12; -static const int kBandLast = 43; +enum { kBandFirst = 12 }; +enum { kBandLast = 43 }; static __inline uint32_t SetBit(uint32_t in, int pos) { uint32_t mask = (1 << pos); @@ -122,8 +123,8 @@ static uint32_t BinarySpectrumFloat(float* spectrum, return out; } -void WebRtc_FreeDelayEstimator(void* handle) { - DelayEstimator* self = (DelayEstimator*) handle; +void WebRtc_FreeDelayEstimatorFarend(void* handle) { + DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; if (handle == NULL) { return; @@ -132,54 +133,156 @@ void WebRtc_FreeDelayEstimator(void* handle) { free(self->mean_far_spectrum); self->mean_far_spectrum = NULL; - free(self->mean_near_spectrum); - self->mean_near_spectrum = NULL; - - WebRtc_FreeBinaryDelayEstimator(self->binary_handle); - self->binary_handle = NULL; - WebRtc_FreeBinaryDelayEstimatorFarend(self->binary_farend); self->binary_farend = NULL; free(self); } -void* WebRtc_CreateDelayEstimator(int spectrum_size, int max_delay, - int lookahead) { - DelayEstimator* self = NULL; - const int history_size = max_delay + lookahead; // For buffer shifting: > 1 +void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size) { + DelayEstimatorFarend* self = NULL; - // TODO(bjornv): Make this a static assert. // Check if the sub band used in the delay estimation is small enough to fit // the binary spectra in a uint32_t. - assert(kBandLast - kBandFirst < 32); + COMPILE_ASSERT(kBandLast - kBandFirst < 32); - if ((spectrum_size >= kBandLast) && (history_size > 1)) { + if (spectrum_size >= kBandLast) { self = malloc(sizeof(DelayEstimator)); } if (self != NULL) { int memory_fail = 0; - self->mean_far_spectrum = NULL; - self->mean_near_spectrum = NULL; - self->binary_farend = NULL; - - // Allocate memory for the farend spectrum handling. + // Allocate memory for the binary far-end spectrum handling. self->binary_farend = WebRtc_CreateBinaryDelayEstimatorFarend(history_size); - - self->binary_handle = WebRtc_CreateBinaryDelayEstimator(self->binary_farend, - lookahead); - memory_fail |= (self->binary_handle == NULL); + memory_fail |= (self->binary_farend == NULL); // Allocate memory for spectrum buffers. self->mean_far_spectrum = malloc(spectrum_size * sizeof(SpectrumType)); memory_fail |= (self->mean_far_spectrum == NULL); - self->mean_near_spectrum = malloc(spectrum_size * sizeof(SpectrumType)); + self->spectrum_size = spectrum_size; + + if (memory_fail) { + WebRtc_FreeDelayEstimatorFarend(self); + self = NULL; + } + } + + return self; +} + +int WebRtc_InitDelayEstimatorFarend(void* handle) { + DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; + + if (self == NULL) { + return -1; + } + + // Initialize far-end part of binary delay estimator. + WebRtc_InitBinaryDelayEstimatorFarend(self->binary_farend); + + // Set averaged far and near end spectra to zero. + memset(self->mean_far_spectrum, 0, + sizeof(SpectrumType) * self->spectrum_size); + // Reset initialization indicators. + self->far_spectrum_initialized = 0; + + return 0; +} + +int WebRtc_AddFarSpectrumFix(void* handle, uint16_t* far_spectrum, + int spectrum_size, int far_q) { + DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; + uint32_t binary_spectrum = 0; + + if (self == NULL) { + return -1; + } + if (far_spectrum == NULL) { + // Empty far end spectrum. + return -1; + } + if (spectrum_size != self->spectrum_size) { + // Data sizes don't match. + return -1; + } + if (far_q > 15) { + // If |far_q| is larger than 15 we cannot guarantee no wrap around. + return -1; + } + + // Get binary spectrum. + binary_spectrum = BinarySpectrumFix(far_spectrum, self->mean_far_spectrum, + far_q, &(self->far_spectrum_initialized)); + WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); + + return 0; +} + +int WebRtc_AddFarSpectrumFloat(void* handle, float* far_spectrum, + int spectrum_size) { + DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; + uint32_t binary_spectrum = 0; + + if (self == NULL) { + return -1; + } + if (far_spectrum == NULL) { + // Empty far end spectrum. + return -1; + } + if (spectrum_size != self->spectrum_size) { + // Data sizes don't match. + return -1; + } + + // Get binary spectrum. + binary_spectrum = BinarySpectrumFloat(far_spectrum, self->mean_far_spectrum, + &(self->far_spectrum_initialized)); + WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); + + return 0; +} + +void WebRtc_FreeDelayEstimator(void* handle) { + DelayEstimator* self = (DelayEstimator*) handle; + + if (handle == NULL) { + return; + } + + free(self->mean_near_spectrum); + self->mean_near_spectrum = NULL; + + WebRtc_FreeBinaryDelayEstimator(self->binary_handle); + self->binary_handle = NULL; + + free(self); +} + +void* WebRtc_CreateDelayEstimator(void* farend_handle, int lookahead) { + DelayEstimator* self = NULL; + DelayEstimatorFarend* farend = (DelayEstimatorFarend*) farend_handle; + + if (farend_handle != NULL) { + self = malloc(sizeof(DelayEstimator)); + } + + if (self != NULL) { + int memory_fail = 0; + + // Allocate memory for the farend spectrum handling. + self->binary_handle = + WebRtc_CreateBinaryDelayEstimator(farend->binary_farend, lookahead); + memory_fail |= (self->binary_handle == NULL); + + // Allocate memory for spectrum buffers. + self->mean_near_spectrum = malloc(farend->spectrum_size * + sizeof(SpectrumType)); memory_fail |= (self->mean_near_spectrum == NULL); - self->spectrum_size = spectrum_size; + self->spectrum_size = farend->spectrum_size; if (memory_fail) { WebRtc_FreeDelayEstimator(self); @@ -197,40 +300,28 @@ int WebRtc_InitDelayEstimator(void* handle) { return -1; } - // Initialize far-end part of binary delay estimator. - WebRtc_InitBinaryDelayEstimatorFarend(self->binary_farend); // Initialize binary delay estimator. WebRtc_InitBinaryDelayEstimator(self->binary_handle); // Set averaged far and near end spectra to zero. - memset(self->mean_far_spectrum, 0, - sizeof(SpectrumType) * self->spectrum_size); memset(self->mean_near_spectrum, 0, sizeof(SpectrumType) * self->spectrum_size); // Reset initialization indicators. - self->far_spectrum_initialized = 0; self->near_spectrum_initialized = 0; return 0; } int WebRtc_DelayEstimatorProcessFix(void* handle, - uint16_t* far_spectrum, uint16_t* near_spectrum, int spectrum_size, - int far_q, int near_q) { DelayEstimator* self = (DelayEstimator*) handle; - uint32_t binary_far_spectrum = 0; - uint32_t binary_near_spectrum = 0; + uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } - if (far_spectrum == NULL) { - // Empty far end spectrum. - return -1; - } if (near_spectrum == NULL) { // Empty near end spectrum. return -1; @@ -239,46 +330,29 @@ int WebRtc_DelayEstimatorProcessFix(void* handle, // Data sizes don't match. return -1; } - if (far_q > 15) { - // If |far_q| is larger than 15 we cannot guarantee no wrap around. - return -1; - } if (near_q > 15) { // If |near_q| is larger than 15 we cannot guarantee no wrap around. return -1; } // Get binary spectra. - binary_far_spectrum = BinarySpectrumFix(far_spectrum, - self->mean_far_spectrum, - far_q, - &(self->far_spectrum_initialized)); - binary_near_spectrum = BinarySpectrumFix(near_spectrum, - self->mean_near_spectrum, - near_q, - &(self->near_spectrum_initialized)); + binary_spectrum = BinarySpectrumFix(near_spectrum, + self->mean_near_spectrum, + near_q, + &(self->near_spectrum_initialized)); - WebRtc_AddBinaryFarSpectrum(self->binary_handle->farend, binary_far_spectrum); - - return WebRtc_ProcessBinarySpectrum(self->binary_handle, - binary_near_spectrum); + return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); } int WebRtc_DelayEstimatorProcessFloat(void* handle, - float* far_spectrum, float* near_spectrum, int spectrum_size) { DelayEstimator* self = (DelayEstimator*) handle; - uint32_t binary_far_spectrum = 0; - uint32_t binary_near_spectrum = 0; + uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } - if (far_spectrum == NULL) { - // Empty far end spectrum. - return -1; - } if (near_spectrum == NULL) { // Empty near end spectrum. return -1; @@ -288,18 +362,11 @@ int WebRtc_DelayEstimatorProcessFloat(void* handle, return -1; } - // Get binary spectra. - binary_far_spectrum = BinarySpectrumFloat(far_spectrum, - self->mean_far_spectrum, - &(self->far_spectrum_initialized)); - binary_near_spectrum = - BinarySpectrumFloat(near_spectrum, self->mean_near_spectrum, - &(self->near_spectrum_initialized)); + // Get binary spectrum. + binary_spectrum = BinarySpectrumFloat(near_spectrum, self->mean_near_spectrum, + &(self->near_spectrum_initialized)); - WebRtc_AddBinaryFarSpectrum(self->binary_handle->farend, binary_far_spectrum); - - return WebRtc_ProcessBinarySpectrum(self->binary_handle, - binary_near_spectrum); + return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); } int WebRtc_last_delay(void* handle) { diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h index 3d243db06..51b9a0a1d 100644 --- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h +++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h @@ -14,7 +14,64 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_ -#include "typedefs.h" +#include "webrtc/typedefs.h" + +// Releases the memory allocated by WebRtc_CreateDelayEstimatorFarend(...) +// Input: +// - handle : Pointer to the delay estimation far-end instance. +// +void WebRtc_FreeDelayEstimatorFarend(void* handle); + +// Allocates the memory needed by the far-end part of the delay estimation. The +// memory needs to be initialized separately through +// WebRtc_InitDelayEstimatorFarend(...). +// +// Inputs: +// - spectrum_size : Size of the spectrum used both in far-end and +// near-end. Used to allocate memory for spectrum +// specific buffers. +// - history_size : The far-end history buffer size. Note that the maximum +// delay which can be estimated is controlled together +// with |lookahead| through +// WebRtc_CreateDelayEstimator(). +// +// Return value: +// - void* : Created |handle|. If the memory can't be allocated or +// if any of the input parameters are invalid NULL is +// returned. +// +void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size); + +// Initializes the far-end part of the delay estimation instance returned by +// WebRtc_CreateDelayEstimatorFarend(...) +// Input: +// - handle : Pointer to the delay estimation far-end instance. +// +// Output: +// - handle : Initialized instance. +// +int WebRtc_InitDelayEstimatorFarend(void* handle); + +// Adds the far-end spectrum to the far-end history buffer. This spectrum is +// used as reference when calculating the delay using +// WebRtc_ProcessSpectrum(). +// +// Inputs: +// - handle : Pointer to the delay estimation far-end instance. +// - far_spectrum : Far-end spectrum. +// - spectrum_size : The size of the data arrays (same for both far- and +// near-end). +// - far_q : The Q-domain of the far-end data. +// +// Output: +// - handle : Updated far-end instance. +// +int WebRtc_AddFarSpectrumFix(void* handle, uint16_t* far_spectrum, + int spectrum_size, int far_q); + +// See WebRtc_AddFarSpectrumFix() for description. +int WebRtc_AddFarSpectrumFloat(void* handle, float* far_spectrum, + int spectrum_size); // Releases the memory allocated by WebRtc_CreateDelayEstimator(...) // Input: @@ -26,11 +83,14 @@ void WebRtc_FreeDelayEstimator(void* handle); // initialized separately through WebRtc_InitDelayEstimator(...). // // Inputs: -// - spectrum_size : Size of the spectrum used both in far-end and -// near-end. Used to allocate memory for spectrum -// specific buffers. -// - max_delay : The maximum delay which can be estimated. Needed to -// allocate memory for history buffers. +// - farend_handle : Pointer to the far-end part of the delay estimation +// instance created prior to this call using +// WebRtc_CreateDelayEstimatorFarend(). +// +// Note that WebRtc_CreateDelayEstimator does not take +// ownership of |farend_handle|, which has to be torn +// down properly after this instance. +// // - lookahead : Amount of non-causal lookahead to use. This can // detect cases in which a near-end signal occurs before // the corresponding far-end signal. It will delay the @@ -41,13 +101,17 @@ void WebRtc_FreeDelayEstimator(void* handle); // This also represents the minimum delay which can be // estimated. // +// Note that the effective range of delay estimates is +// [-|lookahead|,... ,|history_size|-|lookahead|) +// where |history_size| was set upon creating the far-end +// history buffer size. +// // Return value: // - void* : Created |handle|. If the memory can't be allocated or // if any of the input parameters are invalid NULL is // returned. // -void* WebRtc_CreateDelayEstimator(int spectrum_size, int max_delay, - int lookahead); +void* WebRtc_CreateDelayEstimator(void* farend_handle, int lookahead); // Initializes the delay estimation instance returned by // WebRtc_CreateDelayEstimator(...) @@ -64,12 +128,10 @@ int WebRtc_InitDelayEstimator(void* handle); // subtracted from the returned value). // Inputs: // - handle : Pointer to the delay estimation instance. -// - far_spectrum : Pointer to the far-end spectrum data. // - near_spectrum : Pointer to the near-end spectrum data of the current // block. // - spectrum_size : The size of the data arrays (same for both far- and // near-end). -// - far_q : The Q-domain of the far-end data. // - near_q : The Q-domain of the near-end data. // // Output: @@ -81,15 +143,12 @@ int WebRtc_InitDelayEstimator(void* handle); // -2 - Insufficient data for estimation. // int WebRtc_DelayEstimatorProcessFix(void* handle, - uint16_t* far_spectrum, uint16_t* near_spectrum, int spectrum_size, - int far_q, int near_q); // See WebRtc_DelayEstimatorProcessFix() for description. int WebRtc_DelayEstimatorProcessFloat(void* handle, - float* far_spectrum, float* near_spectrum, int spectrum_size); @@ -100,7 +159,7 @@ int WebRtc_DelayEstimatorProcessFloat(void* handle, // - handle : Pointer to the delay estimation instance. // // Return value: -// - delay : >= 0 - Last calculated delay value. +// - delay : >= 0 - Last calculated delay value. // -1 - Error. // -2 - Insufficient data for estimation. // @@ -115,7 +174,7 @@ int WebRtc_last_delay(void* handle); // - handle : Pointer to the delay estimation instance. // // Return value: -// - delay_quality : >= 0 - Estimation quality (in Q9) of last calculated +// - delay_quality : >= 0 - Estimation quality (in Q9) of last calculated // delay value. // -1 - Error. // -2 - Insufficient data for estimation.