Adds possibility to log delay estimates in AEC.
Review URL: http://webrtc-codereview.appspot.com/178001 git-svn-id: http://webrtc.googlecode.com/svn/trunk@674 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -38,6 +38,7 @@ typedef struct {
|
|||||||
WebRtc_Word16 nlpMode; // default kAecNlpModerate
|
WebRtc_Word16 nlpMode; // default kAecNlpModerate
|
||||||
WebRtc_Word16 skewMode; // default kAecFalse
|
WebRtc_Word16 skewMode; // default kAecFalse
|
||||||
WebRtc_Word16 metricsMode; // default kAecFalse
|
WebRtc_Word16 metricsMode; // default kAecFalse
|
||||||
|
int delay_logging; // default kAecFalse
|
||||||
//float realSkew;
|
//float realSkew;
|
||||||
} AecConfig;
|
} AecConfig;
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ extern "C" {
|
|||||||
* Inputs Description
|
* Inputs Description
|
||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
* void **aecInst Pointer to the AEC instance to be created
|
* void **aecInst Pointer to the AEC instance to be created
|
||||||
* and initilized
|
* and initialized
|
||||||
*
|
*
|
||||||
* Outputs Description
|
* Outputs Description
|
||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
@@ -225,6 +226,23 @@ WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status);
|
|||||||
*/
|
*/
|
||||||
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
|
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the current delay metrics for the session.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void* handle Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* int* median Delay median value.
|
||||||
|
* int* std Delay standard deviation.
|
||||||
|
*
|
||||||
|
* int return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets the last error code.
|
* Gets the last error code.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
* The core AEC algorithm, which is presented with time-aligned signals.
|
* The core AEC algorithm, which is presented with time-aligned signals.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "aec_core.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "aec_core.h"
|
|
||||||
#include "aec_rdft.h"
|
#include "aec_rdft.h"
|
||||||
|
#include "delay_estimator_float.h"
|
||||||
#include "ring_buffer.h"
|
#include "ring_buffer.h"
|
||||||
#include "system_wrappers/interface/cpu_features_wrapper.h"
|
#include "system_wrappers/interface/cpu_features_wrapper.h"
|
||||||
|
|
||||||
@@ -174,6 +176,15 @@ int WebRtcAec_CreateAec(aec_t **aecInst)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WebRtc_CreateDelayEstimatorFloat(&aec->delay_estimator,
|
||||||
|
PART_LEN1,
|
||||||
|
kMaxDelay,
|
||||||
|
0) == -1) {
|
||||||
|
WebRtcAec_FreeAec(aec);
|
||||||
|
aec = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +201,8 @@ int WebRtcAec_FreeAec(aec_t *aec)
|
|||||||
WebRtcApm_FreeBuffer(aec->nearFrBufH);
|
WebRtcApm_FreeBuffer(aec->nearFrBufH);
|
||||||
WebRtcApm_FreeBuffer(aec->outFrBufH);
|
WebRtcApm_FreeBuffer(aec->outFrBufH);
|
||||||
|
|
||||||
|
WebRtc_FreeDelayEstimatorFloat(aec->delay_estimator);
|
||||||
|
|
||||||
free(aec);
|
free(aec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -371,6 +384,12 @@ int WebRtcAec_InitAec(aec_t *aec, int sampFreq)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WebRtc_InitDelayEstimatorFloat(aec->delay_estimator) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aec->delay_logging_enabled = 0;
|
||||||
|
memset(aec->delay_histogram, 0, sizeof(aec->delay_histogram));
|
||||||
|
|
||||||
// Default target suppression level
|
// Default target suppression level
|
||||||
aec->targetSupp = -11.5;
|
aec->targetSupp = -11.5;
|
||||||
aec->minOverDrive = 2.0;
|
aec->minOverDrive = 2.0;
|
||||||
@@ -561,6 +580,10 @@ static void ProcessBlock(aec_t *aec, const short *farend,
|
|||||||
float fft[PART_LEN2];
|
float fft[PART_LEN2];
|
||||||
float xf[2][PART_LEN1], yf[2][PART_LEN1], ef[2][PART_LEN1];
|
float xf[2][PART_LEN1], yf[2][PART_LEN1], ef[2][PART_LEN1];
|
||||||
complex_t df[PART_LEN1];
|
complex_t df[PART_LEN1];
|
||||||
|
float far_spectrum = 0.0f;
|
||||||
|
float near_spectrum = 0.0f;
|
||||||
|
float abs_far_spectrum[PART_LEN1];
|
||||||
|
float abs_near_spectrum[PART_LEN1];
|
||||||
|
|
||||||
const float gPow[2] = {0.9f, 0.1f};
|
const float gPow[2] = {0.9f, 0.1f};
|
||||||
|
|
||||||
@@ -625,10 +648,15 @@ static void ProcessBlock(aec_t *aec, const short *farend,
|
|||||||
|
|
||||||
// Power smoothing
|
// Power smoothing
|
||||||
for (i = 0; i < PART_LEN1; i++) {
|
for (i = 0; i < PART_LEN1; i++) {
|
||||||
aec->xPow[i] = gPow[0] * aec->xPow[i] + gPow[1] * NR_PART *
|
far_spectrum = xf[0][i] * xf[0][i] + xf[1][i] * xf[1][i];
|
||||||
(xf[0][i] * xf[0][i] + xf[1][i] * xf[1][i]);
|
aec->xPow[i] = gPow[0] * aec->xPow[i] + gPow[1] * NR_PART * far_spectrum;
|
||||||
aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] *
|
// Calculate absolute spectra
|
||||||
(df[i][0] * df[i][0] + df[i][1] * df[i][1]);
|
abs_far_spectrum[i] = sqrtf(far_spectrum);
|
||||||
|
|
||||||
|
near_spectrum = df[i][0] * df[i][0] + df[i][1] * df[i][1];
|
||||||
|
aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] * near_spectrum;
|
||||||
|
// Calculate absolute spectra
|
||||||
|
abs_near_spectrum[i] = sqrtf(near_spectrum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimate noise power. Wait until dPow is more stable.
|
// Estimate noise power. Wait until dPow is more stable.
|
||||||
@@ -663,6 +691,20 @@ static void ProcessBlock(aec_t *aec, const short *farend,
|
|||||||
aec->noisePow = aec->dMinPow;
|
aec->noisePow = aec->dMinPow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
aec->echoState);
|
||||||
|
if (delay_estimate >= 0) {
|
||||||
|
// Update delay estimate buffer
|
||||||
|
aec->delay_histogram[delay_estimate]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the xfBuf block position.
|
// Update the xfBuf block position.
|
||||||
aec->xfBufBlockPos--;
|
aec->xfBufBlockPos--;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#define PREF_BAND_SIZE 24
|
#define PREF_BAND_SIZE 24
|
||||||
|
|
||||||
#define BLOCKL_MAX FRAME_LEN
|
#define BLOCKL_MAX FRAME_LEN
|
||||||
|
// Maximum delay in fixed point delay estimator, used for logging
|
||||||
|
enum {kMaxDelay = 100};
|
||||||
|
|
||||||
typedef float complex_t[2];
|
typedef float complex_t[2];
|
||||||
// For performance reasons, some arrays of complex numbers are replaced by twice
|
// For performance reasons, some arrays of complex numbers are replaced by twice
|
||||||
@@ -141,6 +143,10 @@ typedef struct {
|
|||||||
int flag_Hband_cn; //for comfort noise
|
int flag_Hband_cn; //for comfort noise
|
||||||
float cn_scale_Hband; //scale for comfort noise in H band
|
float cn_scale_Hband; //scale for comfort noise in H band
|
||||||
|
|
||||||
|
int delay_histogram[kMaxDelay];
|
||||||
|
int delay_logging_enabled;
|
||||||
|
void* delay_estimator;
|
||||||
|
|
||||||
#ifdef AEC_DEBUG
|
#ifdef AEC_DEBUG
|
||||||
FILE *farFile;
|
FILE *farFile;
|
||||||
FILE *nearFile;
|
FILE *nearFile;
|
||||||
|
|||||||
@@ -11,16 +11,18 @@
|
|||||||
/*
|
/*
|
||||||
* Contains the API functions for the AEC.
|
* Contains the API functions for the AEC.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "echo_cancellation.h"
|
#include "echo_cancellation.h"
|
||||||
#include "aec_core.h"
|
|
||||||
#include "ring_buffer.h"
|
#include <math.h>
|
||||||
#include "resampler.h"
|
|
||||||
#ifdef AEC_DEBUG
|
#ifdef AEC_DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aec_core.h"
|
||||||
|
#include "resampler.h"
|
||||||
|
#include "ring_buffer.h"
|
||||||
|
|
||||||
#define BUF_SIZE_FRAMES 50 // buffer size (frames)
|
#define BUF_SIZE_FRAMES 50 // buffer size (frames)
|
||||||
// Maximum length of resampled signal. Must be an integer multiple of frames
|
// Maximum length of resampled signal. Must be an integer multiple of frames
|
||||||
@@ -215,7 +217,7 @@ WebRtc_Word32 WebRtcAec_Init(void *aecInst, WebRtc_Word32 sampFreq, WebRtc_Word3
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
aecpc->initFlag = initCheck; // indicates that initilisation has been done
|
aecpc->initFlag = initCheck; // indicates that initialization has been done
|
||||||
|
|
||||||
if (aecpc->sampFreq == 32000) {
|
if (aecpc->sampFreq == 32000) {
|
||||||
aecpc->splitSampFreq = 16000;
|
aecpc->splitSampFreq = 16000;
|
||||||
@@ -254,6 +256,7 @@ WebRtc_Word32 WebRtcAec_Init(void *aecInst, WebRtc_Word32 sampFreq, WebRtc_Word3
|
|||||||
aecConfig.nlpMode = kAecNlpModerate;
|
aecConfig.nlpMode = kAecNlpModerate;
|
||||||
aecConfig.skewMode = kAecFalse;
|
aecConfig.skewMode = kAecFalse;
|
||||||
aecConfig.metricsMode = kAecFalse;
|
aecConfig.metricsMode = kAecFalse;
|
||||||
|
aecConfig.delay_logging = kAecFalse;
|
||||||
|
|
||||||
if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
|
if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
|
||||||
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
||||||
@@ -566,6 +569,15 @@ WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config)
|
|||||||
WebRtcAec_InitMetrics(aecpc->aec);
|
WebRtcAec_InitMetrics(aecpc->aec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.delay_logging != kAecFalse && config.delay_logging != kAecTrue) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->aec->delay_logging_enabled = config.delay_logging;
|
||||||
|
if (aecpc->aec->delay_logging_enabled == kAecTrue) {
|
||||||
|
memset(aecpc->aec->delay_histogram, 0, sizeof(aecpc->aec->delay_histogram));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,6 +602,7 @@ WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config)
|
|||||||
config->nlpMode = aecpc->nlpMode;
|
config->nlpMode = aecpc->nlpMode;
|
||||||
config->skewMode = aecpc->skewMode;
|
config->skewMode = aecpc->skewMode;
|
||||||
config->metricsMode = aecpc->aec->metricsMode;
|
config->metricsMode = aecpc->aec->metricsMode;
|
||||||
|
config->delay_logging = aecpc->aec->delay_logging_enabled;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -717,6 +730,69 @@ WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
|
||||||
|
aecpc_t* self = handle;
|
||||||
|
int i = 0;
|
||||||
|
int delay_values = 0;
|
||||||
|
int num_delay_values = 0;
|
||||||
|
int my_median = 0;
|
||||||
|
float l1_norm = 0;
|
||||||
|
|
||||||
|
if (self == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (median == NULL) {
|
||||||
|
self->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (std == NULL) {
|
||||||
|
self->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (self->initFlag != initCheck) {
|
||||||
|
self->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (self->aec->delay_logging_enabled == 0) {
|
||||||
|
// Logging disabled
|
||||||
|
self->lastError = AEC_UNSUPPORTED_FUNCTION_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get number of delay values since last update
|
||||||
|
for (i = 0; i < kMaxDelay; i++) {
|
||||||
|
num_delay_values += self->aec->delay_histogram[i];
|
||||||
|
}
|
||||||
|
if (num_delay_values == 0) {
|
||||||
|
// We have no new delay value data
|
||||||
|
*median = -1;
|
||||||
|
*std = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay_values = num_delay_values >> 1; // Start value for median count down
|
||||||
|
// Get median of delay values since last update
|
||||||
|
for (i = 0; i < kMaxDelay; i++) {
|
||||||
|
delay_values -= self->aec->delay_histogram[i];
|
||||||
|
if (delay_values < 0) {
|
||||||
|
my_median = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*median = my_median;
|
||||||
|
|
||||||
|
// Calculate the L1 norm, with median value as central moment
|
||||||
|
for (i = 0; i < kMaxDelay; i++) {
|
||||||
|
l1_norm += (float) (fabs(i - my_median) * self->aec->delay_histogram[i]);
|
||||||
|
}
|
||||||
|
*std = (int) (l1_norm / (float) num_delay_values + 0.5f);
|
||||||
|
|
||||||
|
// Reset histogram
|
||||||
|
memset(self->aec->delay_histogram, 0, sizeof(self->aec->delay_histogram));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
|
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
|
||||||
{
|
{
|
||||||
const char version[] = "AEC 2.5.0";
|
const char version[] = "AEC 2.5.0";
|
||||||
|
|||||||
@@ -322,6 +322,16 @@ class EchoCancellation {
|
|||||||
// TODO(ajm): discuss the metrics update period.
|
// TODO(ajm): discuss the metrics update period.
|
||||||
virtual int GetMetrics(Metrics* metrics) = 0;
|
virtual int GetMetrics(Metrics* metrics) = 0;
|
||||||
|
|
||||||
|
// Enables computation and logging of delay values. Statistics are obtained
|
||||||
|
// through |GetDelayMetrics()|.
|
||||||
|
virtual int enable_delay_logging(bool enable) = 0;
|
||||||
|
virtual bool is_delay_logging_enabled() const = 0;
|
||||||
|
|
||||||
|
// The delay metrics consists of the delay |median| and the delay standard
|
||||||
|
// deviation |std|. The values are averaged over the time period since the
|
||||||
|
// last call to |GetDelayMetrics()|.
|
||||||
|
virtual int GetDelayMetrics(int* median, int* std) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~EchoCancellation() {};
|
virtual ~EchoCancellation() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ EchoCancellationImpl::EchoCancellationImpl(const AudioProcessingImpl* apm)
|
|||||||
device_sample_rate_hz_(48000),
|
device_sample_rate_hz_(48000),
|
||||||
stream_drift_samples_(0),
|
stream_drift_samples_(0),
|
||||||
was_stream_drift_set_(false),
|
was_stream_drift_set_(false),
|
||||||
stream_has_echo_(false) {}
|
stream_has_echo_(false),
|
||||||
|
delay_logging_enabled_(false) {}
|
||||||
|
|
||||||
EchoCancellationImpl::~EchoCancellationImpl() {}
|
EchoCancellationImpl::~EchoCancellationImpl() {}
|
||||||
|
|
||||||
@@ -283,6 +284,39 @@ bool EchoCancellationImpl::stream_has_echo() const {
|
|||||||
return stream_has_echo_;
|
return stream_has_echo_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EchoCancellationImpl::enable_delay_logging(bool enable) {
|
||||||
|
CriticalSectionScoped crit_scoped(*apm_->crit());
|
||||||
|
delay_logging_enabled_ = enable;
|
||||||
|
return Configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EchoCancellationImpl::is_delay_logging_enabled() const {
|
||||||
|
return delay_logging_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bjornv): How should we handle the multi-channel case?
|
||||||
|
int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) {
|
||||||
|
CriticalSectionScoped crit_scoped(*apm_->crit());
|
||||||
|
if (median == NULL) {
|
||||||
|
return apm_->kNullPointerError;
|
||||||
|
}
|
||||||
|
if (std == NULL) {
|
||||||
|
return apm_->kNullPointerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_component_enabled() || !delay_logging_enabled_) {
|
||||||
|
return apm_->kNotEnabledError;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle* my_handle = static_cast<Handle*>(handle(0));
|
||||||
|
if (WebRtcAec_GetDelayMetrics(my_handle, median, std) !=
|
||||||
|
apm_->kNoError) {
|
||||||
|
return GetHandleError(my_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apm_->kNoError;
|
||||||
|
}
|
||||||
|
|
||||||
int EchoCancellationImpl::Initialize() {
|
int EchoCancellationImpl::Initialize() {
|
||||||
int err = ProcessingComponent::Initialize();
|
int err = ProcessingComponent::Initialize();
|
||||||
if (err != apm_->kNoError || !is_component_enabled()) {
|
if (err != apm_->kNoError || !is_component_enabled()) {
|
||||||
@@ -332,6 +366,7 @@ int EchoCancellationImpl::ConfigureHandle(void* handle) const {
|
|||||||
config.metricsMode = metrics_enabled_;
|
config.metricsMode = metrics_enabled_;
|
||||||
config.nlpMode = MapSetting(suppression_level_);
|
config.nlpMode = MapSetting(suppression_level_);
|
||||||
config.skewMode = drift_compensation_enabled_;
|
config.skewMode = drift_compensation_enabled_;
|
||||||
|
config.delay_logging = delay_logging_enabled_;
|
||||||
|
|
||||||
return WebRtcAec_set_config(static_cast<Handle*>(handle), config);
|
return WebRtcAec_set_config(static_cast<Handle*>(handle), config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class EchoCancellationImpl : public EchoCancellation,
|
|||||||
virtual bool are_metrics_enabled() const;
|
virtual bool are_metrics_enabled() const;
|
||||||
virtual bool stream_has_echo() const;
|
virtual bool stream_has_echo() const;
|
||||||
virtual int GetMetrics(Metrics* metrics);
|
virtual int GetMetrics(Metrics* metrics);
|
||||||
|
virtual int enable_delay_logging(bool enable);
|
||||||
|
virtual bool is_delay_logging_enabled() const;
|
||||||
|
virtual int GetDelayMetrics(int* median, int* std);
|
||||||
|
|
||||||
// ProcessingComponent implementation.
|
// ProcessingComponent implementation.
|
||||||
virtual void* CreateHandle() const;
|
virtual void* CreateHandle() const;
|
||||||
@@ -66,6 +69,7 @@ class EchoCancellationImpl : public EchoCancellation,
|
|||||||
int stream_drift_samples_;
|
int stream_drift_samples_;
|
||||||
bool was_stream_drift_set_;
|
bool was_stream_drift_set_;
|
||||||
bool stream_has_echo_;
|
bool stream_has_echo_;
|
||||||
|
bool delay_logging_enabled_;
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ void usage() {
|
|||||||
printf("\n -aec Echo cancellation\n");
|
printf("\n -aec Echo cancellation\n");
|
||||||
printf(" --drift_compensation\n");
|
printf(" --drift_compensation\n");
|
||||||
printf(" --no_drift_compensation\n");
|
printf(" --no_drift_compensation\n");
|
||||||
printf(" --echo_metrics\n");
|
|
||||||
printf(" --no_echo_metrics\n");
|
printf(" --no_echo_metrics\n");
|
||||||
|
printf(" --no_delay_logging\n");
|
||||||
printf("\n -aecm Echo control mobile\n");
|
printf("\n -aecm Echo control mobile\n");
|
||||||
printf(" --aecm_echo_path_in_file FILE\n");
|
printf(" --aecm_echo_path_in_file FILE\n");
|
||||||
printf(" --aecm_echo_path_out_file FILE\n");
|
printf(" --aecm_echo_path_out_file FILE\n");
|
||||||
@@ -218,6 +218,10 @@ void void_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
} else if (strcmp(argv[i], "-aec") == 0) {
|
} else if (strcmp(argv[i], "-aec") == 0) {
|
||||||
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
||||||
|
ASSERT_EQ(apm->kNoError,
|
||||||
|
apm->echo_cancellation()->enable_metrics(true));
|
||||||
|
ASSERT_EQ(apm->kNoError,
|
||||||
|
apm->echo_cancellation()->enable_delay_logging(true));
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "--drift_compensation") == 0) {
|
} else if (strcmp(argv[i], "--drift_compensation") == 0) {
|
||||||
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
||||||
@@ -230,16 +234,16 @@ void void_main(int argc, char* argv[]) {
|
|||||||
ASSERT_EQ(apm->kNoError,
|
ASSERT_EQ(apm->kNoError,
|
||||||
apm->echo_cancellation()->enable_drift_compensation(false));
|
apm->echo_cancellation()->enable_drift_compensation(false));
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "--echo_metrics") == 0) {
|
|
||||||
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
|
||||||
ASSERT_EQ(apm->kNoError,
|
|
||||||
apm->echo_cancellation()->enable_metrics(true));
|
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "--no_echo_metrics") == 0) {
|
} else if (strcmp(argv[i], "--no_echo_metrics") == 0) {
|
||||||
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
||||||
ASSERT_EQ(apm->kNoError,
|
ASSERT_EQ(apm->kNoError,
|
||||||
apm->echo_cancellation()->enable_metrics(false));
|
apm->echo_cancellation()->enable_metrics(false));
|
||||||
|
|
||||||
|
} else if (strcmp(argv[i], "--no_delay_logging") == 0) {
|
||||||
|
ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
|
||||||
|
ASSERT_EQ(apm->kNoError,
|
||||||
|
apm->echo_cancellation()->enable_delay_logging(false));
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "-aecm") == 0) {
|
} else if (strcmp(argv[i], "-aecm") == 0) {
|
||||||
ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
|
ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
|
||||||
|
|
||||||
@@ -884,6 +888,14 @@ void void_main(int argc, char* argv[]) {
|
|||||||
printf("ANLP: ");
|
printf("ANLP: ");
|
||||||
PrintStat(metrics.a_nlp);
|
PrintStat(metrics.a_nlp);
|
||||||
}
|
}
|
||||||
|
if (apm->echo_cancellation()->is_delay_logging_enabled()) {
|
||||||
|
int median = 0;
|
||||||
|
int std = 0;
|
||||||
|
apm->echo_cancellation()->GetDelayMetrics(&median, &std);
|
||||||
|
printf("\n--Delay metrics--\n");
|
||||||
|
printf("Median: %3d\n", median);
|
||||||
|
printf("Standard deviation: %3d\n", std);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pb_file) {
|
if (!pb_file) {
|
||||||
|
|||||||
@@ -457,6 +457,8 @@ TEST_F(ApmTest, Process) {
|
|||||||
apm_->echo_cancellation()->enable_drift_compensation(true));
|
apm_->echo_cancellation()->enable_drift_compensation(true));
|
||||||
EXPECT_EQ(apm_->kNoError,
|
EXPECT_EQ(apm_->kNoError,
|
||||||
apm_->echo_cancellation()->enable_metrics(true));
|
apm_->echo_cancellation()->enable_metrics(true));
|
||||||
|
EXPECT_EQ(apm_->kNoError,
|
||||||
|
apm_->echo_cancellation()->enable_delay_logging(true));
|
||||||
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
|
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
|
||||||
|
|
||||||
EXPECT_EQ(apm_->kNoError,
|
EXPECT_EQ(apm_->kNoError,
|
||||||
@@ -591,6 +593,10 @@ TEST_F(ApmTest, Process) {
|
|||||||
EchoCancellation::Metrics echo_metrics;
|
EchoCancellation::Metrics echo_metrics;
|
||||||
EXPECT_EQ(apm_->kNoError,
|
EXPECT_EQ(apm_->kNoError,
|
||||||
apm_->echo_cancellation()->GetMetrics(&echo_metrics));
|
apm_->echo_cancellation()->GetMetrics(&echo_metrics));
|
||||||
|
int median = 0;
|
||||||
|
int std = 0;
|
||||||
|
EXPECT_EQ(apm_->kNoError,
|
||||||
|
apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!write_output_data) {
|
if (!write_output_data) {
|
||||||
@@ -612,6 +618,11 @@ TEST_F(ApmTest, Process) {
|
|||||||
reference.echo_return_loss_enhancement());
|
reference.echo_return_loss_enhancement());
|
||||||
TestStats(echo_metrics.a_nlp,
|
TestStats(echo_metrics.a_nlp,
|
||||||
reference.a_nlp());
|
reference.a_nlp());
|
||||||
|
|
||||||
|
webrtc::audioproc::Test::DelayMetrics reference_delay =
|
||||||
|
test->delay_metrics();
|
||||||
|
EXPECT_EQ(median, reference_delay.median());
|
||||||
|
EXPECT_EQ(std, reference_delay.std());
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
test->set_has_echo_count(has_echo_count);
|
test->set_has_echo_count(has_echo_count);
|
||||||
@@ -632,6 +643,11 @@ TEST_F(ApmTest, Process) {
|
|||||||
message->mutable_echo_return_loss_enhancement());
|
message->mutable_echo_return_loss_enhancement());
|
||||||
WriteStatsMessage(echo_metrics.a_nlp,
|
WriteStatsMessage(echo_metrics.a_nlp,
|
||||||
message->mutable_a_nlp());
|
message->mutable_a_nlp());
|
||||||
|
|
||||||
|
webrtc::audioproc::Test::DelayMetrics* message_delay =
|
||||||
|
test->mutable_delay_metrics();
|
||||||
|
message_delay->set_median(median);
|
||||||
|
message_delay->set_std(std);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +712,18 @@ TEST_F(ApmTest, EchoCancellation) {
|
|||||||
apm_->echo_cancellation()->enable_metrics(false));
|
apm_->echo_cancellation()->enable_metrics(false));
|
||||||
EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled());
|
EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled());
|
||||||
|
|
||||||
|
int median = 0;
|
||||||
|
int std = 0;
|
||||||
|
EXPECT_EQ(apm_->kNotEnabledError,
|
||||||
|
apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
|
||||||
|
|
||||||
|
EXPECT_EQ(apm_->kNoError,
|
||||||
|
apm_->echo_cancellation()->enable_delay_logging(true));
|
||||||
|
EXPECT_TRUE(apm_->echo_cancellation()->is_delay_logging_enabled());
|
||||||
|
EXPECT_EQ(apm_->kNoError,
|
||||||
|
apm_->echo_cancellation()->enable_delay_logging(false));
|
||||||
|
EXPECT_FALSE(apm_->echo_cancellation()->is_delay_logging_enabled());
|
||||||
|
|
||||||
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
|
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
|
||||||
EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
|
EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
|
||||||
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
|
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ message Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optional EchoMetrics echo_metrics = 11;
|
optional EchoMetrics echo_metrics = 11;
|
||||||
|
|
||||||
|
message DelayMetrics {
|
||||||
|
optional int32 median = 1;
|
||||||
|
optional int32 std = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional DelayMetrics delay_metrics = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message OutputData {
|
message OutputData {
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user