Updating APM unittests on the echo metrics.
There were a series of changes in the calculation of echo metrics. There changes made the existing unittests lose, e.g., EXPECT_EQ become EXPECT_NEAR. It is good time to protect the echo calculation more strictly.
The change is not simply generating a new reference file and change EXPECT_NEAR to EXPECT_EQ. It strengthens the test as well. Main changes are
1. the old test only sample a metric at the end of processing, while the new test takes metrics during the call with a certain time interval. This gives a much stronger protection.
2. added protection of a newly added metric, called divergent_filter_fraction.
3. as said, use EXPECT_EQ (actually ASSERT_EQ) instead of EXPECT_NEAR as much as possible, even for float point values. This may be too restrictive. But it can be good to be restrictive at the beginning.
BUG=
Review-Url: https://codereview.webrtc.org/1969403003
Cr-Commit-Position: refs/heads/master@{#12871}
diff --git a/data/audio_processing/output_data_float.pb b/data/audio_processing/output_data_float.pb
index aff94fa..bc19aa3 100644
--- a/data/audio_processing/output_data_float.pb
+++ b/data/audio_processing/output_data_float.pb
Binary files differ
diff --git a/data/audio_processing/output_data_mac.pb b/data/audio_processing/output_data_mac.pb
index 78d0e10..44f6d27 100644
--- a/data/audio_processing/output_data_mac.pb
+++ b/data/audio_processing/output_data_mac.pb
Binary files differ
diff --git a/webrtc/modules/audio_processing/audio_processing_unittest.cc b/webrtc/modules/audio_processing/audio_processing_unittest.cc
index ded75c8..e5ab3da 100644
--- a/webrtc/modules/audio_processing/audio_processing_unittest.cc
+++ b/webrtc/modules/audio_processing/audio_processing_unittest.cc
@@ -204,10 +204,10 @@
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
void TestStats(const AudioProcessing::Statistic& test,
const audioproc::Test::Statistic& reference) {
- EXPECT_NEAR(reference.instant(), test.instant, 2);
- EXPECT_NEAR(reference.average(), test.average, 2);
- EXPECT_NEAR(reference.maximum(), test.maximum, 3);
- EXPECT_NEAR(reference.minimum(), test.minimum, 2);
+ EXPECT_EQ(reference.instant(), test.instant);
+ EXPECT_EQ(reference.average(), test.average);
+ EXPECT_EQ(reference.maximum(), test.maximum);
+ EXPECT_EQ(reference.minimum(), test.minimum);
}
void WriteStatsMessage(const AudioProcessing::Statistic& output,
@@ -221,7 +221,6 @@
void OpenFileAndWriteMessage(const std::string filename,
const ::google::protobuf::MessageLite& msg) {
-#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
FILE* file = fopen(filename.c_str(), "wb");
ASSERT_TRUE(file != NULL);
@@ -234,10 +233,6 @@
ASSERT_EQ(static_cast<size_t>(size),
fwrite(array.get(), sizeof(array[0]), size, file));
fclose(file);
-#else
- std::cout << "Warning: Writing new reference is only allowed on Linux!"
- << std::endl;
-#endif
}
std::string ResourceFilePath(std::string name, int sample_rate_hz) {
@@ -2101,6 +2096,9 @@
int analog_level_average = 0;
int max_output_average = 0;
float ns_speech_prob_average = 0.0f;
+#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
+ int stats_index = 0;
+#endif
while (ReadFrame(far_file_, revframe_) && ReadFrame(near_file_, frame_)) {
EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(revframe_));
@@ -2148,27 +2146,81 @@
// Reset in case of downmixing.
frame_->num_channels_ = static_cast<size_t>(test->num_input_channels());
frame_count++;
+
+#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
+ const int kStatsAggregationFrameNum = 100; // 1 second.
+ if (frame_count % kStatsAggregationFrameNum == 0) {
+ // Get echo metrics.
+ EchoCancellation::Metrics echo_metrics;
+ EXPECT_EQ(apm_->kNoError,
+ apm_->echo_cancellation()->GetMetrics(&echo_metrics));
+
+ // Get delay metrics.
+ int median = 0;
+ int std = 0;
+ float fraction_poor_delays = 0;
+ EXPECT_EQ(apm_->kNoError,
+ apm_->echo_cancellation()->GetDelayMetrics(
+ &median, &std, &fraction_poor_delays));
+
+ // Get RMS.
+ int rms_level = apm_->level_estimator()->RMS();
+ EXPECT_LE(0, rms_level);
+ EXPECT_GE(127, rms_level);
+
+ if (!write_ref_data) {
+ const audioproc::Test::EchoMetrics& reference =
+ test->echo_metrics(stats_index);
+ TestStats(echo_metrics.residual_echo_return_loss,
+ reference.residual_echo_return_loss());
+ TestStats(echo_metrics.echo_return_loss,
+ reference.echo_return_loss());
+ TestStats(echo_metrics.echo_return_loss_enhancement,
+ reference.echo_return_loss_enhancement());
+ TestStats(echo_metrics.a_nlp,
+ reference.a_nlp());
+ EXPECT_EQ(echo_metrics.divergent_filter_fraction,
+ reference.divergent_filter_fraction());
+
+ const audioproc::Test::DelayMetrics& reference_delay =
+ test->delay_metrics(stats_index);
+ EXPECT_EQ(reference_delay.median(), median);
+ EXPECT_EQ(reference_delay.std(), std);
+ EXPECT_EQ(reference_delay.fraction_poor_delays(),
+ fraction_poor_delays);
+
+ EXPECT_EQ(test->rms_level(stats_index), rms_level);
+
+ ++stats_index;
+ } else {
+ audioproc::Test::EchoMetrics* message =
+ test->add_echo_metrics();
+ WriteStatsMessage(echo_metrics.residual_echo_return_loss,
+ message->mutable_residual_echo_return_loss());
+ WriteStatsMessage(echo_metrics.echo_return_loss,
+ message->mutable_echo_return_loss());
+ WriteStatsMessage(echo_metrics.echo_return_loss_enhancement,
+ message->mutable_echo_return_loss_enhancement());
+ WriteStatsMessage(echo_metrics.a_nlp,
+ message->mutable_a_nlp());
+ message->set_divergent_filter_fraction(
+ echo_metrics.divergent_filter_fraction);
+
+ audioproc::Test::DelayMetrics* message_delay =
+ test->add_delay_metrics();
+ message_delay->set_median(median);
+ message_delay->set_std(std);
+ message_delay->set_fraction_poor_delays(fraction_poor_delays);
+
+ test->add_rms_level(rms_level);
+ }
+ }
+#endif // defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE).
}
max_output_average /= frame_count;
analog_level_average /= frame_count;
ns_speech_prob_average /= frame_count;
-#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
- EchoCancellation::Metrics echo_metrics;
- EXPECT_EQ(apm_->kNoError,
- apm_->echo_cancellation()->GetMetrics(&echo_metrics));
- int median = 0;
- int std = 0;
- float fraction_poor_delays = 0;
- EXPECT_EQ(apm_->kNoError,
- apm_->echo_cancellation()->GetDelayMetrics(
- &median, &std, &fraction_poor_delays));
-
- int rms_level = apm_->level_estimator()->RMS();
- EXPECT_LE(0, rms_level);
- EXPECT_GE(127, rms_level);
-#endif
-
if (!write_ref_data) {
const int kIntNear = 1;
// When running the test on a N7 we get a {2, 6} difference of
@@ -2198,27 +2250,8 @@
EXPECT_NEAR(test->max_output_average(),
max_output_average - kMaxOutputAverageOffset,
kMaxOutputAverageNear);
-
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
- audioproc::Test::EchoMetrics reference = test->echo_metrics();
- TestStats(echo_metrics.residual_echo_return_loss,
- reference.residual_echo_return_loss());
- TestStats(echo_metrics.echo_return_loss,
- reference.echo_return_loss());
- TestStats(echo_metrics.echo_return_loss_enhancement,
- reference.echo_return_loss_enhancement());
- TestStats(echo_metrics.a_nlp,
- reference.a_nlp());
-
const double kFloatNear = 0.0005;
- audioproc::Test::DelayMetrics reference_delay = test->delay_metrics();
- EXPECT_NEAR(reference_delay.median(), median, kIntNear);
- EXPECT_NEAR(reference_delay.std(), std, kIntNear);
- EXPECT_NEAR(reference_delay.fraction_poor_delays(), fraction_poor_delays,
- kFloatNear);
-
- EXPECT_NEAR(test->rms_level(), rms_level, kIntNear);
-
EXPECT_NEAR(test->ns_speech_probability_average(),
ns_speech_prob_average,
kFloatNear);
@@ -2232,24 +2265,6 @@
test->set_max_output_average(max_output_average);
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
- audioproc::Test::EchoMetrics* message = test->mutable_echo_metrics();
- WriteStatsMessage(echo_metrics.residual_echo_return_loss,
- message->mutable_residual_echo_return_loss());
- WriteStatsMessage(echo_metrics.echo_return_loss,
- message->mutable_echo_return_loss());
- WriteStatsMessage(echo_metrics.echo_return_loss_enhancement,
- message->mutable_echo_return_loss_enhancement());
- WriteStatsMessage(echo_metrics.a_nlp,
- message->mutable_a_nlp());
-
- audioproc::Test::DelayMetrics* message_delay =
- test->mutable_delay_metrics();
- message_delay->set_median(median);
- message_delay->set_std(std);
- message_delay->set_fraction_poor_delays(fraction_poor_delays);
-
- test->set_rms_level(rms_level);
-
EXPECT_LE(0.0f, ns_speech_prob_average);
EXPECT_GE(1.0f, ns_speech_prob_average);
test->set_ns_speech_probability_average(ns_speech_prob_average);
diff --git a/webrtc/modules/audio_processing/test/unittest.proto b/webrtc/modules/audio_processing/test/unittest.proto
index ddce46b..3c93bfd 100644
--- a/webrtc/modules/audio_processing/test/unittest.proto
+++ b/webrtc/modules/audio_processing/test/unittest.proto
@@ -32,9 +32,10 @@
optional Statistic echo_return_loss = 2;
optional Statistic echo_return_loss_enhancement = 3;
optional Statistic a_nlp = 4;
+ optional float divergent_filter_fraction = 5;
}
- optional EchoMetrics echo_metrics = 11;
+ repeated EchoMetrics echo_metrics = 11;
message DelayMetrics {
optional int32 median = 1;
@@ -42,9 +43,9 @@
optional float fraction_poor_delays = 3;
}
- optional DelayMetrics delay_metrics = 12;
+ repeated DelayMetrics delay_metrics = 12;
- optional int32 rms_level = 13;
+ repeated int32 rms_level = 13;
optional float ns_speech_probability_average = 14;