This refactoring CL contains an API to get low level echo metrics stats.
TEST=audioproc_unittest, trybots BUG=None Review URL: https://webrtc-codereview.appspot.com/1107007 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3523 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
21a2fc902d
commit
b4cd342eb9
@ -122,7 +122,7 @@ static void ComfortNoise(aec_t *aec, float efw[2][PART_LEN1],
|
|||||||
const float *noisePow, const float *lambda);
|
const float *noisePow, const float *lambda);
|
||||||
|
|
||||||
static void WebRtcAec_InitLevel(power_level_t *level);
|
static void WebRtcAec_InitLevel(power_level_t *level);
|
||||||
static void WebRtcAec_InitStats(stats_t *stats);
|
static void WebRtcAec_InitStats(stats* stats);
|
||||||
static void UpdateLevel(power_level_t* level, float in[2][PART_LEN1]);
|
static void UpdateLevel(power_level_t* level, float in[2][PART_LEN1]);
|
||||||
static void UpdateMetrics(aec_t *aec);
|
static void UpdateMetrics(aec_t *aec);
|
||||||
// Convert from time domain to frequency domain. Note that |time_data| are
|
// Convert from time domain to frequency domain. Note that |time_data| are
|
||||||
@ -721,6 +721,17 @@ int WebRtcAec_echo_state(aec_t* self) {
|
|||||||
return self->echoState;
|
return self->echoState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebRtcAec_GetEchoStats(aec_t* self, stats* erl, stats* erle,
|
||||||
|
stats* a_nlp) {
|
||||||
|
assert(self != NULL);
|
||||||
|
assert(erl != NULL);
|
||||||
|
assert(erle != NULL);
|
||||||
|
assert(a_nlp != NULL);
|
||||||
|
*erl = self->erl;
|
||||||
|
*erle = self->erle;
|
||||||
|
*a_nlp = self->aNlp;
|
||||||
|
}
|
||||||
|
|
||||||
static void ProcessBlock(aec_t* aec) {
|
static void ProcessBlock(aec_t* aec) {
|
||||||
int i;
|
int i;
|
||||||
float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN];
|
float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN];
|
||||||
@ -1391,7 +1402,7 @@ static void WebRtcAec_InitLevel(power_level_t *level)
|
|||||||
level->sfrcounter = 0;
|
level->sfrcounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WebRtcAec_InitStats(stats_t *stats)
|
static void WebRtcAec_InitStats(stats* stats)
|
||||||
{
|
{
|
||||||
stats->instant = offsetLevel;
|
stats->instant = offsetLevel;
|
||||||
stats->average = offsetLevel;
|
stats->average = offsetLevel;
|
||||||
|
@ -56,16 +56,16 @@ typedef struct {
|
|||||||
} power_level_t;
|
} power_level_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float instant;
|
float instant;
|
||||||
float average;
|
float average;
|
||||||
float min;
|
float min;
|
||||||
float max;
|
float max;
|
||||||
float sum;
|
float sum;
|
||||||
float hisum;
|
float hisum;
|
||||||
float himean;
|
float himean;
|
||||||
int counter;
|
int counter;
|
||||||
int hicounter;
|
int hicounter;
|
||||||
} stats_t;
|
} stats;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int farBufWritePos, farBufReadPos;
|
int farBufWritePos, farBufReadPos;
|
||||||
@ -131,10 +131,10 @@ typedef struct {
|
|||||||
|
|
||||||
int metricsMode;
|
int metricsMode;
|
||||||
int stateCounter;
|
int stateCounter;
|
||||||
stats_t erl;
|
stats erl;
|
||||||
stats_t erle;
|
stats erle;
|
||||||
stats_t aNlp;
|
stats aNlp;
|
||||||
stats_t rerl;
|
stats rerl;
|
||||||
|
|
||||||
// Quantities to control H band scaling for SWB input
|
// Quantities to control H band scaling for SWB input
|
||||||
int freq_avg_ic; // initial bin for averaging nlp gain
|
int freq_avg_ic; // initial bin for averaging nlp gain
|
||||||
@ -187,5 +187,7 @@ int WebRtcAec_MoveFarReadPtr(aec_t* aec, int elements);
|
|||||||
int WebRtcAec_GetDelayMetricsCore(aec_t* self, int* median, int* std);
|
int WebRtcAec_GetDelayMetricsCore(aec_t* self, int* median, int* std);
|
||||||
// Returns the echo state (1: echo, 0: no echo).
|
// Returns the echo state (1: echo, 0: no echo).
|
||||||
int WebRtcAec_echo_state(aec_t* self);
|
int WebRtcAec_echo_state(aec_t* self);
|
||||||
|
// Gets statistics of the echo metrics ERL, ERLE, A_NLP.
|
||||||
|
void WebRtcAec_GetEchoStats(aec_t* self, stats* erl, stats* erle, stats* a_nlp);
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
|
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
|
||||||
|
@ -629,104 +629,101 @@ int WebRtcAec_get_echo_status(void* handle, int* status) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
|
int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics) {
|
||||||
{
|
const float kUpWeight = 0.7f;
|
||||||
const float upweight = 0.7f;
|
float dtmp;
|
||||||
float dtmp;
|
int stmp;
|
||||||
short stmp;
|
aecpc_t* self = (aecpc_t*)handle;
|
||||||
aecpc_t *aecpc = aecInst;
|
stats erl;
|
||||||
|
stats erle;
|
||||||
|
stats a_nlp;
|
||||||
|
|
||||||
if (aecpc == NULL) {
|
if (handle == NULL ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (metrics == NULL ) {
|
||||||
|
self->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (self->initFlag != initCheck) {
|
||||||
|
self->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (metrics == NULL) {
|
WebRtcAec_GetEchoStats(self->aec, &erl, &erle, &a_nlp);
|
||||||
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aecpc->initFlag != initCheck) {
|
// ERL
|
||||||
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
metrics->erl.instant = (int) erl.instant;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ERL
|
if ((erl.himean > offsetLevel) && (erl.average > offsetLevel)) {
|
||||||
metrics->erl.instant = (short) aecpc->aec->erl.instant;
|
// Use a mix between regular average and upper part average.
|
||||||
|
dtmp = kUpWeight * erl.himean + (1 - kUpWeight) * erl.average;
|
||||||
|
metrics->erl.average = (int) dtmp;
|
||||||
|
} else {
|
||||||
|
metrics->erl.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if ((aecpc->aec->erl.himean > offsetLevel) && (aecpc->aec->erl.average > offsetLevel)) {
|
metrics->erl.max = (int) erl.max;
|
||||||
// Use a mix between regular average and upper part average
|
|
||||||
dtmp = upweight * aecpc->aec->erl.himean + (1 - upweight) * aecpc->aec->erl.average;
|
|
||||||
metrics->erl.average = (short) dtmp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
metrics->erl.average = offsetLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics->erl.max = (short) aecpc->aec->erl.max;
|
if (erl.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->erl.min = (int) erl.min;
|
||||||
|
} else {
|
||||||
|
metrics->erl.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if (aecpc->aec->erl.min < (offsetLevel * (-1))) {
|
// ERLE
|
||||||
metrics->erl.min = (short) aecpc->aec->erl.min;
|
metrics->erle.instant = (int) erle.instant;
|
||||||
}
|
|
||||||
else {
|
|
||||||
metrics->erl.min = offsetLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ERLE
|
if ((erle.himean > offsetLevel) && (erle.average > offsetLevel)) {
|
||||||
metrics->erle.instant = (short) aecpc->aec->erle.instant;
|
// Use a mix between regular average and upper part average.
|
||||||
|
dtmp = kUpWeight * erle.himean + (1 - kUpWeight) * erle.average;
|
||||||
|
metrics->erle.average = (int) dtmp;
|
||||||
|
} else {
|
||||||
|
metrics->erle.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if ((aecpc->aec->erle.himean > offsetLevel) && (aecpc->aec->erle.average > offsetLevel)) {
|
metrics->erle.max = (int) erle.max;
|
||||||
// Use a mix between regular average and upper part average
|
|
||||||
dtmp = upweight * aecpc->aec->erle.himean + (1 - upweight) * aecpc->aec->erle.average;
|
|
||||||
metrics->erle.average = (short) dtmp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
metrics->erle.average = offsetLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics->erle.max = (short) aecpc->aec->erle.max;
|
if (erle.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->erle.min = (int) erle.min;
|
||||||
|
} else {
|
||||||
|
metrics->erle.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if (aecpc->aec->erle.min < (offsetLevel * (-1))) {
|
// RERL
|
||||||
metrics->erle.min = (short) aecpc->aec->erle.min;
|
if ((metrics->erl.average > offsetLevel)
|
||||||
} else {
|
&& (metrics->erle.average > offsetLevel)) {
|
||||||
metrics->erle.min = offsetLevel;
|
stmp = metrics->erl.average + metrics->erle.average;
|
||||||
}
|
} else {
|
||||||
|
stmp = offsetLevel;
|
||||||
|
}
|
||||||
|
metrics->rerl.average = stmp;
|
||||||
|
|
||||||
// RERL
|
// No other statistics needed, but returned for completeness.
|
||||||
if ((metrics->erl.average > offsetLevel) && (metrics->erle.average > offsetLevel)) {
|
metrics->rerl.instant = stmp;
|
||||||
stmp = metrics->erl.average + metrics->erle.average;
|
metrics->rerl.max = stmp;
|
||||||
}
|
metrics->rerl.min = stmp;
|
||||||
else {
|
|
||||||
stmp = offsetLevel;
|
|
||||||
}
|
|
||||||
metrics->rerl.average = stmp;
|
|
||||||
|
|
||||||
// No other statistics needed, but returned for completeness
|
// A_NLP
|
||||||
metrics->rerl.instant = stmp;
|
metrics->aNlp.instant = (int) a_nlp.instant;
|
||||||
metrics->rerl.max = stmp;
|
|
||||||
metrics->rerl.min = stmp;
|
|
||||||
|
|
||||||
// A_NLP
|
if ((a_nlp.himean > offsetLevel) && (a_nlp.average > offsetLevel)) {
|
||||||
metrics->aNlp.instant = (short) aecpc->aec->aNlp.instant;
|
// Use a mix between regular average and upper part average.
|
||||||
|
dtmp = kUpWeight * a_nlp.himean + (1 - kUpWeight) * a_nlp.average;
|
||||||
|
metrics->aNlp.average = (int) dtmp;
|
||||||
|
} else {
|
||||||
|
metrics->aNlp.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if ((aecpc->aec->aNlp.himean > offsetLevel) && (aecpc->aec->aNlp.average > offsetLevel)) {
|
metrics->aNlp.max = (int) a_nlp.max;
|
||||||
// Use a mix between regular average and upper part average
|
|
||||||
dtmp = upweight * aecpc->aec->aNlp.himean + (1 - upweight) * aecpc->aec->aNlp.average;
|
|
||||||
metrics->aNlp.average = (short) dtmp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
metrics->aNlp.average = offsetLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics->aNlp.max = (short) aecpc->aec->aNlp.max;
|
if (a_nlp.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->aNlp.min = (int) a_nlp.min;
|
||||||
|
} else {
|
||||||
|
metrics->aNlp.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
if (aecpc->aec->aNlp.min < (offsetLevel * (-1))) {
|
return 0;
|
||||||
metrics->aNlp.min = (short) aecpc->aec->aNlp.min;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
metrics->aNlp.min = offsetLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
|
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
|
||||||
|
@ -43,10 +43,10 @@ typedef struct {
|
|||||||
} AecConfig;
|
} AecConfig;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WebRtc_Word16 instant;
|
int instant;
|
||||||
WebRtc_Word16 average;
|
int average;
|
||||||
WebRtc_Word16 max;
|
int max;
|
||||||
WebRtc_Word16 min;
|
int min;
|
||||||
} AecLevel;
|
} AecLevel;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -215,16 +215,16 @@ int WebRtcAec_get_echo_status(void* handle, int* status);
|
|||||||
*
|
*
|
||||||
* Inputs Description
|
* Inputs Description
|
||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
* void *aecInst Pointer to the AEC instance
|
* void *handle Pointer to the AEC instance
|
||||||
*
|
*
|
||||||
* Outputs Description
|
* Outputs Description
|
||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
* AecMetrics *metrics Struct which will be filled out with the
|
* AecMetrics *metrics Struct which will be filled out with the
|
||||||
* current echo metrics.
|
* current echo metrics.
|
||||||
* WebRtc_Word32 return 0: OK
|
* int return 0: OK
|
||||||
* -1: error
|
* -1: error
|
||||||
*/
|
*/
|
||||||
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
|
int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets the current delay metrics for the session.
|
* Gets the current delay metrics for the session.
|
||||||
|
Loading…
Reference in New Issue
Block a user