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
diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c
index 2dbd067..104b3dd 100644
--- a/webrtc/modules/audio_processing/aec/aec_core.c
+++ b/webrtc/modules/audio_processing/aec/aec_core.c
@@ -122,7 +122,7 @@
const float *noisePow, const float *lambda);
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 UpdateMetrics(aec_t *aec);
// Convert from time domain to frequency domain. Note that |time_data| are
@@ -721,6 +721,17 @@
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) {
int i;
float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN];
@@ -1391,7 +1402,7 @@
level->sfrcounter = 0;
}
-static void WebRtcAec_InitStats(stats_t *stats)
+static void WebRtcAec_InitStats(stats* stats)
{
stats->instant = offsetLevel;
stats->average = offsetLevel;
diff --git a/webrtc/modules/audio_processing/aec/aec_core.h b/webrtc/modules/audio_processing/aec/aec_core.h
index 7474ec7..a740b0d 100644
--- a/webrtc/modules/audio_processing/aec/aec_core.h
+++ b/webrtc/modules/audio_processing/aec/aec_core.h
@@ -56,16 +56,16 @@
} power_level_t;
typedef struct {
- float instant;
- float average;
- float min;
- float max;
- float sum;
- float hisum;
- float himean;
- int counter;
- int hicounter;
-} stats_t;
+ float instant;
+ float average;
+ float min;
+ float max;
+ float sum;
+ float hisum;
+ float himean;
+ int counter;
+ int hicounter;
+} stats;
typedef struct {
int farBufWritePos, farBufReadPos;
@@ -131,10 +131,10 @@
int metricsMode;
int stateCounter;
- stats_t erl;
- stats_t erle;
- stats_t aNlp;
- stats_t rerl;
+ stats erl;
+ stats erle;
+ stats aNlp;
+ stats rerl;
// Quantities to control H band scaling for SWB input
int freq_avg_ic; // initial bin for averaging nlp gain
@@ -187,5 +187,7 @@
int WebRtcAec_GetDelayMetricsCore(aec_t* self, int* median, int* std);
// Returns the echo state (1: echo, 0: no echo).
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_
diff --git a/webrtc/modules/audio_processing/aec/echo_cancellation.c b/webrtc/modules/audio_processing/aec/echo_cancellation.c
index c6aa454..25f44e2 100644
--- a/webrtc/modules/audio_processing/aec/echo_cancellation.c
+++ b/webrtc/modules/audio_processing/aec/echo_cancellation.c
@@ -629,104 +629,101 @@
return 0;
}
-WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
-{
- const float upweight = 0.7f;
- float dtmp;
- short stmp;
- aecpc_t *aecpc = aecInst;
+int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics) {
+ const float kUpWeight = 0.7f;
+ float dtmp;
+ int stmp;
+ aecpc_t* self = (aecpc_t*)handle;
+ stats erl;
+ stats erle;
+ stats a_nlp;
- if (aecpc == NULL) {
- return -1;
- }
+ if (handle == NULL ) {
+ 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) {
- aecpc->lastError = AEC_NULL_POINTER_ERROR;
- return -1;
- }
+ WebRtcAec_GetEchoStats(self->aec, &erl, &erle, &a_nlp);
- if (aecpc->initFlag != initCheck) {
- aecpc->lastError = AEC_UNINITIALIZED_ERROR;
- return -1;
- }
+ // ERL
+ metrics->erl.instant = (int) erl.instant;
- // ERL
- metrics->erl.instant = (short) aecpc->aec->erl.instant;
+ if ((erl.himean > offsetLevel) && (erl.average > offsetLevel)) {
+ // 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)) {
- // 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 = (int) erl.max;
- 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))) {
- metrics->erl.min = (short) aecpc->aec->erl.min;
- }
- else {
- metrics->erl.min = offsetLevel;
- }
+ // ERLE
+ metrics->erle.instant = (int) erle.instant;
- // ERLE
- metrics->erle.instant = (short) aecpc->aec->erle.instant;
+ if ((erle.himean > offsetLevel) && (erle.average > offsetLevel)) {
+ // 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)) {
- // 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 = (int) erle.max;
- 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))) {
- metrics->erle.min = (short) aecpc->aec->erle.min;
- } else {
- metrics->erle.min = offsetLevel;
- }
+ // RERL
+ if ((metrics->erl.average > offsetLevel)
+ && (metrics->erle.average > offsetLevel)) {
+ stmp = metrics->erl.average + metrics->erle.average;
+ } else {
+ stmp = offsetLevel;
+ }
+ metrics->rerl.average = stmp;
- // RERL
- if ((metrics->erl.average > offsetLevel) && (metrics->erle.average > offsetLevel)) {
- stmp = metrics->erl.average + metrics->erle.average;
- }
- else {
- stmp = offsetLevel;
- }
- metrics->rerl.average = stmp;
+ // No other statistics needed, but returned for completeness.
+ metrics->rerl.instant = stmp;
+ metrics->rerl.max = stmp;
+ metrics->rerl.min = stmp;
- // No other statistics needed, but returned for completeness
- metrics->rerl.instant = stmp;
- metrics->rerl.max = stmp;
- metrics->rerl.min = stmp;
+ // A_NLP
+ metrics->aNlp.instant = (int) a_nlp.instant;
- // A_NLP
- metrics->aNlp.instant = (short) aecpc->aec->aNlp.instant;
+ if ((a_nlp.himean > offsetLevel) && (a_nlp.average > offsetLevel)) {
+ // 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)) {
- // 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 = (int) a_nlp.max;
- 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))) {
- metrics->aNlp.min = (short) aecpc->aec->aNlp.min;
- }
- else {
- metrics->aNlp.min = offsetLevel;
- }
-
- return 0;
+ return 0;
}
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
diff --git a/webrtc/modules/audio_processing/aec/include/echo_cancellation.h b/webrtc/modules/audio_processing/aec/include/echo_cancellation.h
index 82dc0d3..367ed56 100644
--- a/webrtc/modules/audio_processing/aec/include/echo_cancellation.h
+++ b/webrtc/modules/audio_processing/aec/include/echo_cancellation.h
@@ -43,10 +43,10 @@
} AecConfig;
typedef struct {
- WebRtc_Word16 instant;
- WebRtc_Word16 average;
- WebRtc_Word16 max;
- WebRtc_Word16 min;
+ int instant;
+ int average;
+ int max;
+ int min;
} AecLevel;
typedef struct {
@@ -215,16 +215,16 @@
*
* Inputs Description
* -------------------------------------------------------------------
- * void *aecInst Pointer to the AEC instance
+ * void *handle Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecMetrics *metrics Struct which will be filled out with the
* current echo metrics.
- * WebRtc_Word32 return 0: OK
+ * int return 0: OK
* -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.