Added AEC delay logging metrics to VoE. Echo metrics and delay logging metrics are enabled simultaneously through the SetEcMetricsStatus(). Updated standard and extended VoE tests.

class VoEAudioProcessing
-API renaming:
  SetEchoMetricsStatus() to SetEcMetricsStatus()
  GetEchoMetricsStatus() to GetEcMetricsStatus()
  since delay logging is not strictly an echo metric.
-New API:
  GetEcDelayMetrics()
-Implementations
  --SetEcMetricsStatus() sets same status to all EC related metrics, currently Echo Metrics and Delay Logging.
  --GetEcMetricsStatus() gets an error if all EC related metrics don't have the same status.
  --GetEcDelayMetrics() gets the median and standard deviation of AEC internal delay (on a block by block basis).

class VoECallReport
The changes above leads to changes in the Call Report.
-New API:
  GetEcDelaySummary()
-API updates:
  ResetCallReportStatistics()
  WriteReportToFile()

auto_tests updates:
-Standard test, with new Call Report calls and APM calls
-Extended test, with new Call Report calls and APM calls
Review URL: http://webrtc-codereview.appspot.com/187004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@754 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
bjornv@webrtc.org 2011-10-17 08:49:23 +00:00
parent f10ea31211
commit 3765bd2cc2
6 changed files with 176 additions and 93 deletions

View File

@ -149,17 +149,22 @@ public:
// and 0 if silence. The output is always 1 if VAD is disabled.
virtual int VoiceActivityIndicator(int channel) = 0;
// Enables or disables the possibility to retrieve instantaneous
// echo metrics during an active call.
virtual int SetEchoMetricsStatus(bool enable) = 0;
// Enables or disables the possibility to retrieve echo metrics and delay
// logging values during an active call. The metrics are only supported in
// AEC.
virtual int SetEcMetricsStatus(bool enable) = 0;
// Gets the current echo metric status.
virtual int GetEchoMetricsStatus(bool& enabled) = 0;
// Gets the current EC metric status.
virtual int GetEcMetricsStatus(bool& enabled) = 0;
// Gets the instantaneous echo level metrics for the near-end and
// far-end signals.
// Gets the instantaneous echo level metrics.
virtual int GetEchoMetrics(int& ERL, int& ERLE, int& RERL, int& A_NLP) = 0;
// Gets the EC internal |delay_median| and |delay_std| in ms between
// near-end and far-end. The values are calculated over the time period
// since the last GetEcDelayMetrics() call.
virtual int GetEcDelayMetrics(int& delay_median, int& delay_std) = 0;
// Enables recording of Audio Processing (AP) debugging information.
// The file can later be used for off-line analysis of the AP performance.
virtual int StartDebugRecording(const char* fileNameUTF8) = 0;

View File

@ -946,9 +946,9 @@ int VoEAudioProcessingImpl::VoiceActivityIndicator(int channel)
return activity;
}
int VoEAudioProcessingImpl::SetEchoMetricsStatus(bool enable) {
int VoEAudioProcessingImpl::SetEcMetricsStatus(bool enable) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId, -1),
"SetEchoMetricsStatus(enable=%d)", enable);
"SetEcMetricsStatus(enable=%d)", enable);
ANDROID_NOT_SUPPORTED();
IPHONE_NOT_SUPPORTED();
@ -958,11 +958,13 @@ int VoEAudioProcessingImpl::SetEchoMetricsStatus(bool enable) {
return -1;
}
if (_audioProcessingModulePtr->echo_cancellation()->enable_metrics(enable) !=
0) {
if ((_audioProcessingModulePtr->echo_cancellation()->enable_metrics(enable)
!= 0) ||
(_audioProcessingModulePtr->echo_cancellation()->enable_delay_logging(
enable) != 0)) {
_engineStatistics.SetLastError(
VE_APM_ERROR, kTraceError,
"SetEchoMetricsStatus() unable to set echo metrics mode");
"SetEcMetricsStatus() unable to set EC metrics mode");
return -1;
}
return 0;
@ -973,9 +975,9 @@ int VoEAudioProcessingImpl::SetEchoMetricsStatus(bool enable) {
#endif
}
int VoEAudioProcessingImpl::GetEchoMetricsStatus(bool& enabled) {
int VoEAudioProcessingImpl::GetEcMetricsStatus(bool& enabled) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId, -1),
"GetEchoMetricsStatus(enabled=?)");
"GetEcMetricsStatus(enabled=?)");
ANDROID_NOT_SUPPORTED();
IPHONE_NOT_SUPPORTED();
@ -985,11 +987,22 @@ int VoEAudioProcessingImpl::GetEchoMetricsStatus(bool& enabled) {
return -1;
}
enabled =
_audioProcessingModulePtr->echo_cancellation()->are_metrics_enabled();
bool echo_mode =
_audioProcessingModulePtr->echo_cancellation()->are_metrics_enabled();
bool delay_mode =
_audioProcessingModulePtr->echo_cancellation()->is_delay_logging_enabled();
if (echo_mode != delay_mode) {
_engineStatistics.SetLastError(
VE_APM_ERROR, kTraceError,
"GetEcMetricsStatus() delay logging and echo mode are not the same");
return -1;
}
enabled = echo_mode;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
"GetEchoMetricsStatus() => enabled=%d", enabled);
"GetEcMetricsStatus() => enabled=%d", enabled);
return 0;
#else
_engineStatistics.SetLastError(
@ -1001,55 +1014,92 @@ int VoEAudioProcessingImpl::GetEchoMetricsStatus(bool& enabled) {
int VoEAudioProcessingImpl::GetEchoMetrics(int& ERL,
int& ERLE,
int& RERL,
int& A_NLP)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId, -1),
"GetEchoMetrics(ERL=?, ERLE=?, RERL=?, A_NLP=?)");
ANDROID_NOT_SUPPORTED();
IPHONE_NOT_SUPPORTED();
int& A_NLP) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId, -1),
"GetEchoMetrics(ERL=?, ERLE=?, RERL=?, A_NLP=?)");
ANDROID_NOT_SUPPORTED();
IPHONE_NOT_SUPPORTED();
#ifdef WEBRTC_VOICE_ENGINE_ECHO
if (!_engineStatistics.Initialized())
{
_engineStatistics.SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (!_engineStatistics.Initialized()) {
_engineStatistics.SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (!_audioProcessingModulePtr->echo_cancellation()->is_enabled()) {
_engineStatistics.SetLastError(
VE_APM_ERROR, kTraceWarning,
"GetEchoMetrics() AudioProcessingModule AEC is not enabled");
return -1;
}
bool echoMode =
_audioProcessingModulePtr->echo_cancellation()->is_enabled();
EchoCancellation::Metrics echoMetrics;
// Get Echo Metrics from Audio Processing Module.
EchoCancellation::Metrics echoMetrics;
if (_audioProcessingModulePtr->echo_cancellation()->GetMetrics(&echoMetrics))
{
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
"GetEchoMetrics(), AudioProcessingModule metrics error");
return -1;
}
if (echoMode == false)
{
_engineStatistics.SetLastError(
VE_APM_ERROR, kTraceWarning,
"GetEchoMetrics() AudioProcessingModule echo metrics is not"
"enabled");
return -1;
}
if (_audioProcessingModulePtr->echo_cancellation()->GetMetrics(
&echoMetrics))
{
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
"GetEchoMetrics(), AudioProcessingModule echo metrics"
"error");
return -1;
}
// Echo quality metrics.
ERL = echoMetrics.echo_return_loss.instant;
ERLE = echoMetrics.echo_return_loss_enhancement.instant;
RERL = echoMetrics.residual_echo_return_loss.instant;
A_NLP = echoMetrics.a_nlp.instant;
ERL = echoMetrics.echo_return_loss.instant;
ERLE = echoMetrics.echo_return_loss_enhancement.instant;
RERL = echoMetrics.residual_echo_return_loss.instant;
A_NLP = echoMetrics.a_nlp.instant;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
"GetEchoMetrics() => ERL=%d, ERLE=%d, RERL=%d, A_NLP=%d",
ERL, ERLE, RERL, A_NLP);
return 0;
return 0;
#else
_engineStatistics.SetLastError(
VE_FUNC_NOT_SUPPORTED, kTraceError,
"SetEcStatus() EC is not supported");
_engineStatistics.SetLastError(
VE_FUNC_NOT_SUPPORTED, kTraceError, "SetEcStatus() EC is not supported");
return -1;
#endif
}
int VoEAudioProcessingImpl::GetEcDelayMetrics(int& delay_median,
int& delay_std) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId, -1),
"GetEcDelayMetrics(median=?, std=?)");
ANDROID_NOT_SUPPORTED();
IPHONE_NOT_SUPPORTED();
#ifdef WEBRTC_VOICE_ENGINE_ECHO
if (!_engineStatistics.Initialized()) {
_engineStatistics.SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (!_audioProcessingModulePtr->echo_cancellation()->is_enabled()) {
_engineStatistics.SetLastError(
VE_APM_ERROR, kTraceWarning,
"GetEcDelayMetrics() AudioProcessingModule AEC is not enabled");
return -1;
}
int median = 0;
int std = 0;
// Get delay-logging values from Audio Processing Module.
if (_audioProcessingModulePtr->echo_cancellation()->GetDelayMetrics(
&median, &std)) {
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
"GetEcDelayMetrics(), AudioProcessingModule delay-logging "
"error");
return -1;
}
// EC delay-logging metrics
delay_median = median;
delay_std = std;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
"GetEcDelayMetrics() => delay_median=%d, delay_std=%d",
delay_median, delay_std);
return 0;
#else
_engineStatistics.SetLastError(
VE_FUNC_NOT_SUPPORTED, kTraceError, "SetEcStatus() EC is not supported");
return -1;
#endif
}

View File

@ -70,12 +70,14 @@ public:
virtual int VoiceActivityIndicator(int channel);
virtual int SetEchoMetricsStatus(bool enable);
virtual int SetEcMetricsStatus(bool enable);
virtual int GetEchoMetricsStatus(bool& enabled);
virtual int GetEcMetricsStatus(bool& enabled);
virtual int GetEchoMetrics(int& ERL, int& ERLE, int& RERL, int& A_NLP);
virtual int GetEcDelayMetrics(int& delay_median, int& delay_std);
virtual int StartDebugRecording(const char* fileNameUTF8);
virtual int StopDebugRecording();

View File

@ -89,7 +89,7 @@ int VoECallReportImpl::ResetCallReportStatistics(int channel)
_audioProcessingModulePtr->echo_cancellation()->are_metrics_enabled();
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
" current AudioProcessingModule echo metric currentState %d",
" current AudioProcessingModule echo metric state %d)",
echoMode);
// Reset the APM statistics
if (_audioProcessingModulePtr->echo_cancellation()->enable_metrics(true)

View File

@ -1699,13 +1699,14 @@ int VoEExtendedTest::TestCallReport()
EchoStatistics echo;
TEST(GetEchoMetricSummary);
ANL();
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled));
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
TEST_MUSTPASS(enabled != false);
TEST_MUSTPASS(apm->SetEchoMetricsStatus(true));
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
TEST_MUSTPASS(report->GetEchoMetricSummary(echo)); // all outputs will be
// -100 in loopback (skip further tests)
AOK();
ANL();
// TODO(xians): investigate the cause of test failure before enabling.
/*
StatVal delays;
@ -8117,26 +8118,26 @@ digitalCompressionGaindBDefault);
SLEEP(NSSleep);
//////////////////////////////////
// Echo Metrics
// Ec Metrics
#if (!defined(MAC_IPHONE) && !defined(WEBRTC_ANDROID))
TEST(GetEchoMetricsStatus);
TEST(GetEcMetricsStatus);
ANL();
TEST(SetEchoMetricsStatus);
TEST(SetEcMetricsStatus);
ANL();
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled));
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
MARK();
TEST_MUSTPASS(enabled != false);
MARK(); // should be OFF by default
TEST_MUSTPASS(apm->SetEchoMetricsStatus(true));
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
MARK();
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled));
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
MARK();
TEST_MUSTPASS(enabled != true);
MARK();
TEST_MUSTPASS(apm->SetEchoMetricsStatus(false));
TEST_MUSTPASS(apm->SetEcMetricsStatus(false));
MARK();
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled));
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
MARK();
TEST_MUSTPASS(enabled != false);
MARK();
@ -8148,21 +8149,43 @@ digitalCompressionGaindBDefault);
int ERL, ERLE, RERL, A_NLP;
TEST_MUSTPASS(-1 != apm->GetEchoMetrics(ERL, ERLE, RERL, A_NLP));
MARK(); // should fail since not activated
MARK(); // Should fail since not activated.
err = base->LastError();
TEST_MUSTPASS(err != VE_APM_ERROR);
TEST_MUSTPASS(apm->SetEchoMetricsStatus(true));
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
TEST_MUSTPASS(-1 != apm->GetEchoMetrics(ERL, ERLE, RERL, A_NLP));
MARK(); // should fail since AEC is off
MARK(); // Should fail since AEC is off.
err = base->LastError();
TEST_MUSTPASS(err != VE_APM_ERROR);
TEST_MUSTPASS(apm->SetEcStatus(true));
TEST_MUSTPASS(apm->GetEchoMetrics(ERL, ERLE, RERL, A_NLP));
MARK(); // should work now
TEST_LOG(
"\nEcho: ERL=%d, ERLE=%d, RERL=%d, A_NLP=%d [dB]\n",
ERL, ERLE, RERL, A_NLP);
TEST_MUSTPASS(apm->SetEchoMetricsStatus(false));
MARK(); // Should work now.
TEST_LOG("\nEcho: ERL=%d, ERLE=%d, RERL=%d, A_NLP=%d [dB]\n",
ERL, ERLE, RERL, A_NLP);
TEST_MUSTPASS(apm->SetEcMetricsStatus(false));
TEST_MUSTPASS(apm->SetEcStatus(false));
AOK();
ANL();
TEST(GetEcDelayMetrics);
ANL();
int delay_median = 0;
int delay_std = 0;
TEST_MUSTPASS(-1 != apm->GetEcDelayMetrics(delay_median, delay_std));
MARK(); // Should fail since not activated.
err = base->LastError();
TEST_MUSTPASS(err != VE_APM_ERROR);
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
TEST_MUSTPASS(-1 != apm->GetEcDelayMetrics(delay_median, delay_std));
MARK(); // Should fail since AEC is off.
err = base->LastError();
TEST_MUSTPASS(err != VE_APM_ERROR);
TEST_MUSTPASS(apm->SetEcStatus(true));
TEST_MUSTPASS(apm->GetEcDelayMetrics(delay_median, delay_std));
MARK(); // Should work now.
TEST_LOG("\nEC Delay: median=%d, std=%d [ms]\n", delay_median, delay_std);
TEST_MUSTPASS(apm->SetEcMetricsStatus(false));
TEST_MUSTPASS(apm->SetEcStatus(false));
AOK();
ANL();

View File

@ -2792,27 +2792,30 @@ int VoETestManager::DoStandardTest()
#if (!defined(MAC_IPHONE) && !defined(WEBRTC_ANDROID) && defined(WEBRTC_VOICE_ENGINE_NR))
#ifdef WEBRTC_VOICE_ENGINE_ECHO
bool enabled = false;
TEST_LOG("Echo Metric calls\n");
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled)); // check default
TEST_LOG("EC Metrics calls\n");
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled)); // check default
TEST_MUSTPASS(enabled != false);
TEST_MUSTPASS(apm->SetEchoMetricsStatus(true)); // enable echo metrics
TEST_MUSTPASS(apm->SetEcMetricsStatus(true)); // enable EC metrics
// must enable AEC to get valid echo metrics
TEST_MUSTPASS(apm->SetEcStatus(true, kEcAec));
TEST_MUSTPASS(apm->GetEchoMetricsStatus(enabled));
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
TEST_MUSTPASS(enabled != true);
TEST_LOG("Speak into microphone and check metrics for 10 seconds...\n");
int ERLE, ERL, RERL, A_NLP;
for (int t = 0; t < 5; t++)
{
SLEEP(2000);
TEST_MUSTPASS(apm->GetEchoMetrics(ERL, ERLE, RERL, A_NLP));
TEST_LOG(" Echo : ERL=%5d, ERLE=%5d, RERL=%5d, A_NLP=%5d [dB]\n",
ERL, ERLE, RERL, A_NLP);
int ERL, ERLE, RERL, A_NLP;
int delay_median = 0;
int delay_std = 0;
for (int t = 0; t < 5; t++) {
SLEEP(2000);
TEST_MUSTPASS(apm->GetEchoMetrics(ERL, ERLE, RERL, A_NLP));
TEST_MUSTPASS(apm->GetEcDelayMetrics(delay_median, delay_std));
TEST_LOG(" Echo : ERL=%5d, ERLE=%5d, RERL=%5d, A_NLP=%5d [dB], "
" delay median=%3d, delay std=%3d [ms]\n",
ERL, ERLE, RERL, A_NLP, delay_median, delay_std);
}
TEST_MUSTPASS(apm->SetEchoMetricsStatus(false)); // disable echo metrics
TEST_MUSTPASS(apm->SetEcMetricsStatus(false)); // disable echo metrics
#else
TEST_LOG("Skipping echo metrics tests -"
TEST_LOG("Skipping Echo Control metrics tests -"
" WEBRTC_VOICE_ENGINE_ECHO not defined \n");
#endif // #ifdef WEBRTC_VOICE_ENGINE_ECHO
#else
@ -3255,9 +3258,9 @@ int VoETestManager::DoStandardTest()
TEST_MUSTPASS(report->ResetCallReportStatistics(-1));
bool onOff;
TEST_MUSTPASS(apm->GetEchoMetricsStatus(onOff));
TEST_MUSTPASS(apm->GetEcMetricsStatus(onOff));
TEST_MUSTPASS(onOff != false);
TEST_MUSTPASS(apm->SetEchoMetricsStatus(true));
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
SLEEP(3000);
EchoStatistics echo;
TEST(GetEchoMetricSummary);ANL();