This changelist is basically a code cleanup and restructuring. Main things is that we now have a function for time to frequency transformation and the delay estimator is separated into its own struct and files.
Review URL: http://webrtc-codereview.appspot.com/90004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@300 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
ce7c2a231e
commit
55ce2d8a25
@ -31,6 +31,8 @@
|
|||||||
'echo_control_mobile.c',
|
'echo_control_mobile.c',
|
||||||
'aecm_core.c',
|
'aecm_core.c',
|
||||||
'aecm_core.h',
|
'aecm_core.h',
|
||||||
|
'aecm_delay_estimator.c',
|
||||||
|
'aecm_delay_estimator.h',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,14 +17,8 @@
|
|||||||
//#define AECM_WITH_ABS_APPROX
|
//#define AECM_WITH_ABS_APPROX
|
||||||
//#define AECM_SHORT // for 32 sample partition length (otherwise 64)
|
//#define AECM_SHORT // for 32 sample partition length (otherwise 64)
|
||||||
|
|
||||||
// TODO(bjornv): These defines will be removed in final version.
|
|
||||||
//#define STORE_CHANNEL_DATA
|
|
||||||
//#define VAD_DATA
|
|
||||||
|
|
||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
#include "signal_processing_library.h"
|
#include "signal_processing_library.h"
|
||||||
// TODO(bjornv): Will be removed in final version.
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
// Algorithm parameters
|
// Algorithm parameters
|
||||||
|
|
||||||
@ -127,29 +121,21 @@ typedef struct
|
|||||||
WebRtc_UWord32 seed;
|
WebRtc_UWord32 seed;
|
||||||
|
|
||||||
// Delay estimation variables
|
// Delay estimation variables
|
||||||
WebRtc_UWord16 medianYlogspec[PART_LEN1];
|
void* delay_estimator;
|
||||||
WebRtc_UWord16 medianXlogspec[PART_LEN1];
|
|
||||||
WebRtc_UWord16 medianBCount[MAX_DELAY];
|
|
||||||
WebRtc_UWord16 xfaHistory[PART_LEN1][MAX_DELAY];
|
|
||||||
WebRtc_Word16 delHistoryPos;
|
|
||||||
WebRtc_UWord32 bxHistory[MAX_DELAY];
|
|
||||||
WebRtc_UWord16 currentDelay;
|
WebRtc_UWord16 currentDelay;
|
||||||
WebRtc_UWord16 previousDelay;
|
|
||||||
WebRtc_Word16 delayAdjust;
|
|
||||||
|
|
||||||
WebRtc_Word16 nlpFlag;
|
WebRtc_Word16 nlpFlag;
|
||||||
WebRtc_Word16 fixedDelay;
|
WebRtc_Word16 fixedDelay;
|
||||||
|
|
||||||
WebRtc_UWord32 totCount;
|
WebRtc_UWord32 totCount;
|
||||||
|
|
||||||
WebRtc_Word16 xfaQDomainBuf[MAX_DELAY];
|
|
||||||
WebRtc_Word16 dfaCleanQDomain;
|
WebRtc_Word16 dfaCleanQDomain;
|
||||||
WebRtc_Word16 dfaCleanQDomainOld;
|
WebRtc_Word16 dfaCleanQDomainOld;
|
||||||
WebRtc_Word16 dfaNoisyQDomain;
|
WebRtc_Word16 dfaNoisyQDomain;
|
||||||
WebRtc_Word16 dfaNoisyQDomainOld;
|
WebRtc_Word16 dfaNoisyQDomainOld;
|
||||||
|
|
||||||
WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN];
|
WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN];
|
||||||
WebRtc_Word16 farLogEnergy[MAX_BUF_LEN];
|
WebRtc_Word16 farLogEnergy;
|
||||||
WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN];
|
WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN];
|
||||||
WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN];
|
WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN];
|
||||||
|
|
||||||
@ -176,43 +162,16 @@ typedef struct
|
|||||||
WebRtc_Word16 currentVADValue;
|
WebRtc_Word16 currentVADValue;
|
||||||
WebRtc_Word16 vadUpdateCount;
|
WebRtc_Word16 vadUpdateCount;
|
||||||
|
|
||||||
WebRtc_Word16 delayHistogram[MAX_DELAY];
|
|
||||||
WebRtc_Word16 delayVadCount;
|
|
||||||
WebRtc_Word16 maxDelayHistIdx;
|
|
||||||
WebRtc_Word16 lastMinPos;
|
|
||||||
|
|
||||||
WebRtc_Word16 startupState;
|
WebRtc_Word16 startupState;
|
||||||
WebRtc_Word16 mseChannelCount;
|
WebRtc_Word16 mseChannelCount;
|
||||||
WebRtc_Word16 delayCount;
|
|
||||||
WebRtc_Word16 newDelayCorrData;
|
|
||||||
WebRtc_Word16 lastDelayUpdateCount;
|
|
||||||
WebRtc_Word16 delayCorrelation[CORR_BUF_LEN];
|
|
||||||
WebRtc_Word16 supGain;
|
WebRtc_Word16 supGain;
|
||||||
WebRtc_Word16 supGainOld;
|
WebRtc_Word16 supGainOld;
|
||||||
WebRtc_Word16 delayOffsetFlag;
|
|
||||||
|
|
||||||
WebRtc_Word16 supGainErrParamA;
|
WebRtc_Word16 supGainErrParamA;
|
||||||
WebRtc_Word16 supGainErrParamD;
|
WebRtc_Word16 supGainErrParamD;
|
||||||
WebRtc_Word16 supGainErrParamDiffAB;
|
WebRtc_Word16 supGainErrParamDiffAB;
|
||||||
WebRtc_Word16 supGainErrParamDiffBD;
|
WebRtc_Word16 supGainErrParamDiffBD;
|
||||||
|
|
||||||
// TODO(bjornv): Will be removed after final version has been committed.
|
|
||||||
#ifdef VAD_DATA
|
|
||||||
FILE *vad_file;
|
|
||||||
FILE *delay_file;
|
|
||||||
FILE *far_file;
|
|
||||||
FILE *far_cur_file;
|
|
||||||
FILE *far_min_file;
|
|
||||||
FILE *far_max_file;
|
|
||||||
FILE *far_vad_file;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO(bjornv): Will be removed after final version has been committed.
|
|
||||||
#ifdef STORE_CHANNEL_DATA
|
|
||||||
FILE *channel_file;
|
|
||||||
FILE *channel_file_init;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AEC_DEBUG
|
#ifdef AEC_DEBUG
|
||||||
FILE *farFile;
|
FILE *farFile;
|
||||||
FILE *nearFile;
|
FILE *nearFile;
|
||||||
@ -266,7 +225,7 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq);
|
|||||||
//
|
//
|
||||||
int WebRtcAecm_FreeCore(AecmCore_t *aecm);
|
int WebRtcAecm_FreeCore(AecmCore_t *aecm);
|
||||||
|
|
||||||
int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag, int delayOffsetFlag);
|
int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// WebRtcAecm_InitEchoPathCore(...)
|
// WebRtcAecm_InitEchoPathCore(...)
|
||||||
|
@ -0,0 +1,550 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "aecm_delay_estimator.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Pointers to mean values of spectrum and bit counts
|
||||||
|
WebRtc_Word32* mean_far_spectrum;
|
||||||
|
WebRtc_Word32* mean_near_spectrum;
|
||||||
|
WebRtc_Word32* mean_bit_counts;
|
||||||
|
|
||||||
|
// Binary history variables
|
||||||
|
WebRtc_UWord32* binary_far_history;
|
||||||
|
|
||||||
|
// Far end history variables
|
||||||
|
WebRtc_UWord16* far_history;
|
||||||
|
int far_history_position;
|
||||||
|
WebRtc_Word16* far_q_domains;
|
||||||
|
|
||||||
|
// Delay histogram variables
|
||||||
|
WebRtc_Word16* delay_histogram;
|
||||||
|
WebRtc_Word16 vad_counter;
|
||||||
|
|
||||||
|
// Delay memory
|
||||||
|
int last_delay;
|
||||||
|
|
||||||
|
// Buffer size parameters
|
||||||
|
int history_size;
|
||||||
|
int spectrum_size;
|
||||||
|
|
||||||
|
} DelayEstimator_t;
|
||||||
|
|
||||||
|
// Only bit |kBandFirst| through bit |kBandLast| are processed
|
||||||
|
// |kBandFirst| - |kBandLast| must be < 32
|
||||||
|
static const int kBandFirst = 12;
|
||||||
|
static const int kBandLast = 43;
|
||||||
|
|
||||||
|
static __inline WebRtc_UWord32 SetBit(WebRtc_UWord32 in,
|
||||||
|
WebRtc_Word32 pos)
|
||||||
|
{
|
||||||
|
WebRtc_UWord32 mask = WEBRTC_SPL_LSHIFT_W32(1, pos);
|
||||||
|
WebRtc_UWord32 out = (in | mask);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compares the binary vector |binary_vector| with all rows of the binary
|
||||||
|
// matrix |binary_matrix| and counts per row the number of times they have the
|
||||||
|
// same value.
|
||||||
|
// Input:
|
||||||
|
// - binary_vector : binary "vector" stored in a long
|
||||||
|
// - binary_matrix : binary "matrix" stored as a vector of long
|
||||||
|
// - matrix_size : size of binary "matrix"
|
||||||
|
// Output:
|
||||||
|
// - bit_counts : "Vector" stored as a long, containing for each
|
||||||
|
// row the number of times the matrix row and the
|
||||||
|
// input vector have the same value
|
||||||
|
//
|
||||||
|
static void BitCountComparison(const WebRtc_UWord32 binary_vector,
|
||||||
|
const WebRtc_UWord32* binary_matrix,
|
||||||
|
int matrix_size,
|
||||||
|
WebRtc_Word32* bit_counts)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
WebRtc_UWord32 a = binary_vector;
|
||||||
|
register WebRtc_UWord32 tmp;
|
||||||
|
|
||||||
|
// compare binary vector |binary_vector| with all rows of the binary matrix
|
||||||
|
// |binary_matrix|
|
||||||
|
for (; n < matrix_size; n++)
|
||||||
|
{
|
||||||
|
a = (binary_vector ^ binary_matrix[n]);
|
||||||
|
// Returns bit counts in tmp
|
||||||
|
tmp = a - ((a >> 1) & 033333333333) - ((a >> 2) & 011111111111);
|
||||||
|
tmp = ((tmp + (tmp >> 3)) & 030707070707);
|
||||||
|
tmp = (tmp + (tmp >> 6));
|
||||||
|
tmp = (tmp + (tmp >> 12) + (tmp >> 24)) & 077;
|
||||||
|
|
||||||
|
bit_counts[n] = (WebRtc_Word32)tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computes the binary spectrum by comparing the input |spectrum| with a
|
||||||
|
// |threshold_spectrum|.
|
||||||
|
//
|
||||||
|
// Input:
|
||||||
|
// - spectrum : Spectrum of which the binary spectrum should
|
||||||
|
// be calculated.
|
||||||
|
// - threshold_spectrum : Threshold spectrum with which the input
|
||||||
|
// spectrum is compared.
|
||||||
|
// Return:
|
||||||
|
// - out : Binary spectrum
|
||||||
|
//
|
||||||
|
static WebRtc_UWord32 GetBinarySpectrum(WebRtc_Word32* spectrum,
|
||||||
|
WebRtc_Word32* threshold_spectrum)
|
||||||
|
{
|
||||||
|
int k = kBandFirst;
|
||||||
|
WebRtc_UWord32 out = 0;
|
||||||
|
|
||||||
|
for (; k <= kBandLast; k++)
|
||||||
|
{
|
||||||
|
if (spectrum[k] > threshold_spectrum[k])
|
||||||
|
{
|
||||||
|
out = SetBit(out, k - kBandFirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the mean recursively.
|
||||||
|
//
|
||||||
|
// Input:
|
||||||
|
// - new_value : new additional value
|
||||||
|
// - factor : factor for smoothing
|
||||||
|
//
|
||||||
|
// Input/Output:
|
||||||
|
// - mean_value : pointer to the mean value that should be updated
|
||||||
|
//
|
||||||
|
static void MeanEstimator(const WebRtc_Word32 new_value,
|
||||||
|
int factor,
|
||||||
|
WebRtc_Word32* mean_value)
|
||||||
|
{
|
||||||
|
WebRtc_Word32 mean_new = *mean_value;
|
||||||
|
WebRtc_Word32 diff = new_value - mean_new;
|
||||||
|
|
||||||
|
// mean_new = mean_value + ((new_value - mean_value) >> factor);
|
||||||
|
if (diff < 0)
|
||||||
|
{
|
||||||
|
diff = -WEBRTC_SPL_RSHIFT_W32(-diff, factor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = WEBRTC_SPL_RSHIFT_W32(diff, factor);
|
||||||
|
}
|
||||||
|
mean_new += diff;
|
||||||
|
|
||||||
|
*mean_value = mean_new;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moves the pointer to the next entry and inserts new far end spectrum and
|
||||||
|
// corresponding Q-domain in its buffer.
|
||||||
|
//
|
||||||
|
// Input:
|
||||||
|
// - handle : Pointer to the delay estimation instance
|
||||||
|
// - far_spectrum : Pointer to the far end spectrum
|
||||||
|
// - far_q : Q-domain of far end spectrum
|
||||||
|
//
|
||||||
|
static void UpdateFarHistory(DelayEstimator_t* self,
|
||||||
|
WebRtc_UWord16* far_spectrum,
|
||||||
|
WebRtc_Word16 far_q)
|
||||||
|
{
|
||||||
|
// Get new buffer position
|
||||||
|
self->far_history_position++;
|
||||||
|
if (self->far_history_position >= self->history_size)
|
||||||
|
{
|
||||||
|
self->far_history_position = 0;
|
||||||
|
}
|
||||||
|
// Update Q-domain buffer
|
||||||
|
self->far_q_domains[self->far_history_position] = far_q;
|
||||||
|
// Update far end spectrum buffer
|
||||||
|
memcpy(&(self->far_history[self->far_history_position * self->spectrum_size]),
|
||||||
|
far_spectrum,
|
||||||
|
sizeof(WebRtc_UWord16) * self->spectrum_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAecm_FreeDelayEstimator(void* handle)
|
||||||
|
{
|
||||||
|
DelayEstimator_t* self = (DelayEstimator_t*)handle;
|
||||||
|
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->mean_far_spectrum != NULL)
|
||||||
|
{
|
||||||
|
free(self->mean_far_spectrum);
|
||||||
|
self->mean_far_spectrum = NULL;
|
||||||
|
}
|
||||||
|
if (self->mean_near_spectrum != NULL)
|
||||||
|
{
|
||||||
|
free(self->mean_near_spectrum);
|
||||||
|
self->mean_near_spectrum = NULL;
|
||||||
|
}
|
||||||
|
if (self->far_history != NULL)
|
||||||
|
{
|
||||||
|
free(self->far_history);
|
||||||
|
self->far_history = NULL;
|
||||||
|
}
|
||||||
|
if (self->mean_bit_counts != NULL)
|
||||||
|
{
|
||||||
|
free(self->mean_bit_counts);
|
||||||
|
self->mean_bit_counts = NULL;
|
||||||
|
}
|
||||||
|
if (self->binary_far_history != NULL)
|
||||||
|
{
|
||||||
|
free(self->binary_far_history);
|
||||||
|
self->binary_far_history = NULL;
|
||||||
|
}
|
||||||
|
if (self->far_q_domains != NULL)
|
||||||
|
{
|
||||||
|
free(self->far_q_domains);
|
||||||
|
self->far_q_domains = NULL;
|
||||||
|
}
|
||||||
|
if (self->delay_histogram != NULL)
|
||||||
|
{
|
||||||
|
free(self->delay_histogram);
|
||||||
|
self->delay_histogram = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAecm_CreateDelayEstimator(void** handle,
|
||||||
|
int spectrum_size,
|
||||||
|
int history_size)
|
||||||
|
{
|
||||||
|
// Check if the sub band used in the delay estimation is small enough to
|
||||||
|
// fit in a Word32.
|
||||||
|
assert(kBandLast - kBandFirst < 32);
|
||||||
|
|
||||||
|
DelayEstimator_t *self = NULL;
|
||||||
|
if (spectrum_size < kBandLast)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (history_size < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = malloc(sizeof(DelayEstimator_t));
|
||||||
|
*handle = self;
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->mean_far_spectrum = NULL;
|
||||||
|
self->mean_near_spectrum = NULL;
|
||||||
|
self->far_history = NULL;
|
||||||
|
self->mean_bit_counts = NULL;
|
||||||
|
self->binary_far_history = NULL;
|
||||||
|
self->far_q_domains = NULL;
|
||||||
|
self->delay_histogram = NULL;
|
||||||
|
|
||||||
|
// Allocate memory for spectrum buffers
|
||||||
|
self->mean_far_spectrum = malloc(spectrum_size * sizeof(WebRtc_Word32));
|
||||||
|
if (self->mean_far_spectrum == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self->mean_near_spectrum = malloc(spectrum_size * sizeof(WebRtc_Word32));
|
||||||
|
if (self->mean_near_spectrum == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Allocate memory for history buffers
|
||||||
|
self->far_history = malloc(spectrum_size * history_size *
|
||||||
|
sizeof(WebRtc_UWord16));
|
||||||
|
if (self->far_history == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self->mean_bit_counts = malloc(history_size * sizeof(WebRtc_Word32));
|
||||||
|
if (self->mean_bit_counts == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self->binary_far_history = malloc(history_size * sizeof(WebRtc_UWord32));
|
||||||
|
if (self->binary_far_history == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self->far_q_domains = malloc(history_size * sizeof(WebRtc_Word16));
|
||||||
|
if (self->far_q_domains == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self->delay_histogram = malloc(history_size * sizeof(WebRtc_Word16));
|
||||||
|
if (self->delay_histogram == NULL)
|
||||||
|
{
|
||||||
|
WebRtcAecm_FreeDelayEstimator(self);
|
||||||
|
self = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->spectrum_size = spectrum_size;
|
||||||
|
self->history_size = history_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAecm_InitDelayEstimator(void* handle)
|
||||||
|
{
|
||||||
|
DelayEstimator_t* self = (DelayEstimator_t*)handle;
|
||||||
|
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Set averaged far and near end spectra to zero
|
||||||
|
memset(self->mean_far_spectrum,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_Word32) * self->spectrum_size);
|
||||||
|
memset(self->mean_near_spectrum,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_Word32) * self->spectrum_size);
|
||||||
|
// Set averaged bit counts to zero
|
||||||
|
memset(self->mean_bit_counts,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_Word32) * self->history_size);
|
||||||
|
// Set far end histories to zero
|
||||||
|
memset(self->binary_far_history,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_UWord32) * self->history_size);
|
||||||
|
memset(self->far_history,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_UWord16) * self->spectrum_size *
|
||||||
|
self->history_size);
|
||||||
|
memset(self->far_q_domains,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_Word16) * self->history_size);
|
||||||
|
|
||||||
|
self->far_history_position = self->history_size;
|
||||||
|
// Set delay histogram to zero
|
||||||
|
memset(self->delay_histogram,
|
||||||
|
0,
|
||||||
|
sizeof(WebRtc_Word16) * self->history_size);
|
||||||
|
// Set VAD counter to zero
|
||||||
|
self->vad_counter = 0;
|
||||||
|
// Set delay memory to zero
|
||||||
|
self->last_delay = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAecm_DelayEstimatorProcess(void* handle,
|
||||||
|
WebRtc_UWord16* far_spectrum,
|
||||||
|
WebRtc_UWord16* near_spectrum,
|
||||||
|
int spectrum_size,
|
||||||
|
WebRtc_Word16 far_q,
|
||||||
|
WebRtc_Word16 vad_value)
|
||||||
|
{
|
||||||
|
DelayEstimator_t* self = (DelayEstimator_t*)handle;
|
||||||
|
|
||||||
|
WebRtc_UWord32 bxspectrum, byspectrum;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
WebRtc_Word32 dtmp1;
|
||||||
|
|
||||||
|
WebRtc_Word16 maxHistLvl = 0;
|
||||||
|
WebRtc_Word16 minpos = -1;
|
||||||
|
|
||||||
|
const int kVadCountThreshold = 25;
|
||||||
|
const int kMaxHistogram = 600;
|
||||||
|
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 bit_counts[self->history_size];
|
||||||
|
WebRtc_Word32 far_spectrum_32[self->spectrum_size];
|
||||||
|
WebRtc_Word32 near_spectrum_32[self->spectrum_size];
|
||||||
|
|
||||||
|
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 can not guarantee no wrap around
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update far end history
|
||||||
|
UpdateFarHistory(self, far_spectrum, far_q);
|
||||||
|
// Update the far and near end means
|
||||||
|
for (i = 0; i < self->spectrum_size; i++)
|
||||||
|
{
|
||||||
|
far_spectrum_32[i] = (WebRtc_Word32)far_spectrum[i];
|
||||||
|
MeanEstimator(far_spectrum_32[i], 6, &(self->mean_far_spectrum[i]));
|
||||||
|
|
||||||
|
near_spectrum_32[i] = (WebRtc_Word32)near_spectrum[i];
|
||||||
|
MeanEstimator(near_spectrum_32[i], 6, &(self->mean_near_spectrum[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift binary spectrum history
|
||||||
|
memmove(&(self->binary_far_history[1]),
|
||||||
|
&(self->binary_far_history[0]),
|
||||||
|
(self->history_size - 1) * sizeof(WebRtc_UWord32));
|
||||||
|
|
||||||
|
// Get binary spectra
|
||||||
|
bxspectrum = GetBinarySpectrum(far_spectrum_32, self->mean_far_spectrum);
|
||||||
|
byspectrum = GetBinarySpectrum(near_spectrum_32, self->mean_near_spectrum);
|
||||||
|
// Insert new binary spectrum
|
||||||
|
self->binary_far_history[0] = bxspectrum;
|
||||||
|
|
||||||
|
// Compare with delayed spectra
|
||||||
|
BitCountComparison(byspectrum,
|
||||||
|
self->binary_far_history,
|
||||||
|
self->history_size,
|
||||||
|
bit_counts);
|
||||||
|
|
||||||
|
// Smooth bit count curve
|
||||||
|
for (i = 0; i < self->history_size; i++)
|
||||||
|
{
|
||||||
|
// Update sum
|
||||||
|
// |bit_counts| is constrained to [0, 32], meaning we can smooth with a
|
||||||
|
// factor up to 2^26. We use Q9.
|
||||||
|
dtmp1 = WEBRTC_SPL_LSHIFT_W32(bit_counts[i], 9); // Q9
|
||||||
|
MeanEstimator(dtmp1, 9, &(self->mean_bit_counts[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find minimum position of bit count curve
|
||||||
|
minpos = WebRtcSpl_MinIndexW32(self->mean_bit_counts, self->history_size);
|
||||||
|
|
||||||
|
// If the farend has been active sufficiently long, begin accumulating a
|
||||||
|
// histogram of the minimum positions. Search for the maximum bin to
|
||||||
|
// determine the delay.
|
||||||
|
if (vad_value == 1)
|
||||||
|
{
|
||||||
|
if (self->vad_counter >= kVadCountThreshold)
|
||||||
|
{
|
||||||
|
// Increment the histogram at the current minimum position.
|
||||||
|
if (self->delay_histogram[minpos] < kMaxHistogram)
|
||||||
|
{
|
||||||
|
self->delay_histogram[minpos] += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (!defined ARM_WINM) && (!defined ARM9E_GCC) && (!defined ANDROID_AECOPT)
|
||||||
|
// Decrement the entire histogram.
|
||||||
|
// Select the histogram index corresponding to the maximum bin as
|
||||||
|
// the delay.
|
||||||
|
self->last_delay = 0;
|
||||||
|
for (i = 0; i < self->history_size; i++)
|
||||||
|
{
|
||||||
|
if (self->delay_histogram[i] > 0)
|
||||||
|
{
|
||||||
|
self->delay_histogram[i]--;
|
||||||
|
}
|
||||||
|
if (self->delay_histogram[i] > maxHistLvl)
|
||||||
|
{
|
||||||
|
maxHistLvl = self->delay_histogram[i];
|
||||||
|
self->last_delay = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
self->last_delay = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < self->history_size; i++)
|
||||||
|
{
|
||||||
|
WebRtc_Word16 tempVar = self->delay_histogram[i];
|
||||||
|
|
||||||
|
// Decrement the entire histogram.
|
||||||
|
if (tempVar > 0)
|
||||||
|
{
|
||||||
|
tempVar--;
|
||||||
|
self->delay_histogram[i] = tempVar;
|
||||||
|
|
||||||
|
// Select the histogram index corresponding to the maximum
|
||||||
|
// bin as the delay.
|
||||||
|
if (tempVar > maxHistLvl)
|
||||||
|
{
|
||||||
|
maxHistLvl = tempVar;
|
||||||
|
self->last_delay = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
self->vad_counter++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
self->vad_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self->last_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WebRtc_UWord16* WebRtcAecm_GetAlignedFarend(void* handle,
|
||||||
|
WebRtc_Word16* far_q)
|
||||||
|
{
|
||||||
|
DelayEstimator_t* self = (DelayEstimator_t*)handle;
|
||||||
|
int buffer_position = 0;
|
||||||
|
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get buffer position
|
||||||
|
buffer_position = self->far_history_position - self->last_delay;
|
||||||
|
if (buffer_position < 0)
|
||||||
|
{
|
||||||
|
buffer_position += self->history_size;
|
||||||
|
}
|
||||||
|
// Get Q-domain
|
||||||
|
*far_q = self->far_q_domains[buffer_position];
|
||||||
|
// Return far end spectrum
|
||||||
|
return (self->far_history + (buffer_position * self->spectrum_size));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAecm_GetLastDelay(void* handle)
|
||||||
|
{
|
||||||
|
DelayEstimator_t* self = (DelayEstimator_t*)handle;
|
||||||
|
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return last calculated delay
|
||||||
|
return self->last_delay;
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Performs delay estimation on a block by block basis
|
||||||
|
// The return value is 0 - OK and -1 - Error, unless otherwise stated.
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_DELAY_ESTIMATOR_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_DELAY_ESTIMATOR_H_
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
// Releases the memory allocated by WebRtcAecm_CreateDelayEstimator(...)
|
||||||
|
// Input:
|
||||||
|
// - handle : Pointer to the delay estimation instance
|
||||||
|
//
|
||||||
|
int WebRtcAecm_FreeDelayEstimator(void* handle);
|
||||||
|
|
||||||
|
// Allocates the memory needed by the delay estimation. The memory needs to be
|
||||||
|
// initialized separately using the WebRtcAecm_InitDelayEstimator(...) function.
|
||||||
|
//
|
||||||
|
// Input:
|
||||||
|
// - handle : Instance that should be created
|
||||||
|
// - spectrum_size : Size of the spectrum used both in far end and near
|
||||||
|
// end. Used to allocate memory for spectrum specific
|
||||||
|
// buffers.
|
||||||
|
// - history_size : Size of the far end history used to estimate the
|
||||||
|
// delay from. Used to allocate memory for history
|
||||||
|
// specific buffers.
|
||||||
|
//
|
||||||
|
// Output:
|
||||||
|
// - handle : Created instance
|
||||||
|
//
|
||||||
|
int WebRtcAecm_CreateDelayEstimator(void** handle,
|
||||||
|
int spectrum_size,
|
||||||
|
int history_size);
|
||||||
|
|
||||||
|
// Initializes the delay estimation instance created with
|
||||||
|
// WebRtcAecm_CreateDelayEstimator(...)
|
||||||
|
// Input:
|
||||||
|
// - handle : Pointer to the delay estimation instance
|
||||||
|
//
|
||||||
|
// Output:
|
||||||
|
// - handle : Initialized instance
|
||||||
|
//
|
||||||
|
int WebRtcAecm_InitDelayEstimator(void* handle);
|
||||||
|
|
||||||
|
// Estimates and returns the delay between the far end and near end blocks.
|
||||||
|
// Input:
|
||||||
|
// - 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
|
||||||
|
// - vad_value : The VAD decision of the current block
|
||||||
|
//
|
||||||
|
// Output:
|
||||||
|
// - handle : Updated instance
|
||||||
|
//
|
||||||
|
// Return value:
|
||||||
|
// - delay : >= 0 - Calculated delay value
|
||||||
|
// -1 - Error
|
||||||
|
//
|
||||||
|
int WebRtcAecm_DelayEstimatorProcess(void* handle,
|
||||||
|
WebRtc_UWord16* far_spectrum,
|
||||||
|
WebRtc_UWord16* near_spectrum,
|
||||||
|
int spectrum_size,
|
||||||
|
WebRtc_Word16 far_q,
|
||||||
|
WebRtc_Word16 vad_value);
|
||||||
|
|
||||||
|
// Returns a pointer to the far end spectrum aligned to current near end
|
||||||
|
// spectrum. The function WebRtcAecm_DelayEstimatorProcess(...) should
|
||||||
|
// have been called before WebRtcAecm_GetAlignedFarend(...). Otherwise, you get
|
||||||
|
// the pointer to the previous frame. The memory is only valid until the next
|
||||||
|
// call of WebRtcAecm_DelayEstimatorProcess(...).
|
||||||
|
//
|
||||||
|
// Inputs:
|
||||||
|
// - handle : Pointer to the delay estimation instance
|
||||||
|
//
|
||||||
|
// Output:
|
||||||
|
// - far_q : The Q-domain of the aligned far end spectrum
|
||||||
|
//
|
||||||
|
// Return value:
|
||||||
|
// - far_spectrum : Pointer to the aligned far end spectrum
|
||||||
|
// NULL - Error
|
||||||
|
//
|
||||||
|
const WebRtc_UWord16* WebRtcAecm_GetAlignedFarend(void* handle,
|
||||||
|
WebRtc_Word16* far_q);
|
||||||
|
|
||||||
|
// Returns the last calculated delay updated by the function
|
||||||
|
// WebRtcAecm_DelayEstimatorProcess(...)
|
||||||
|
//
|
||||||
|
// Inputs:
|
||||||
|
// - handle : Pointer to the delay estimation instance
|
||||||
|
//
|
||||||
|
// Return value:
|
||||||
|
// - delay : >= 0 - Last calculated delay value
|
||||||
|
// -1 - Error
|
||||||
|
//
|
||||||
|
int WebRtcAecm_GetLastDelay(void* handle);
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_DELAY_ESTIMATOR_H_
|
Loading…
Reference in New Issue
Block a user