Index: webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator_unittest.cc |
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator_unittest.cc b/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b76116ba0bb314642a936859a4558c61bd8995d5 |
--- /dev/null |
+++ b/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator_unittest.cc |
@@ -0,0 +1,192 @@ |
+/* |
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include "webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator.h" |
+ |
+#include <sstream> |
+#include <string> |
+#include <vector> |
+ |
+#include "webrtc/base/array_view.h" |
+#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" |
+#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
+#include "webrtc/test/gtest.h" |
+ |
+namespace webrtc { |
+namespace { |
+ |
+void VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ size_t num_repetitions, |
+ rtc::ArrayView<const MatchedFilter::LagEstimate> lag_estimates, |
+ MatchedFilterLagAggregator* aggregator) { |
+ for (size_t k = 0; k < num_repetitions; ++k) { |
+ EXPECT_FALSE(aggregator->Aggregate(lag_estimates)); |
+ } |
+} |
+ |
+constexpr size_t kThresholdForRequiredLagUpdatesInARow = 10; |
+constexpr size_t kThresholdForRequiredIdenticalLagAggregates = 10; |
+ |
+} // namespace |
+ |
+// Verifies that the most accurate lag estimate is chosen. |
+TEST(MatchedFilterLagAggregator, MostAccurateLagChosen) { |
+ constexpr size_t kArtificialLag1 = 5; |
+ constexpr size_t kArtificialLag2 = 10; |
+ ApmDataDumper data_dumper(0); |
+ std::vector<MatchedFilter::LagEstimate> lag_estimates(2); |
+ MatchedFilterLagAggregator aggregator(&data_dumper, lag_estimates.size()); |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag1, true); |
+ lag_estimates[1] = |
+ MatchedFilter::LagEstimate(0.5f, true, kArtificialLag2, true); |
+ |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredLagUpdatesInARow + |
+ kThresholdForRequiredIdenticalLagAggregates, |
+ lag_estimates, &aggregator); |
+ rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag1, *aggregated_lag); |
+ |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(0.5f, true, kArtificialLag1, true); |
+ lag_estimates[1] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag2, true); |
+ |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredIdenticalLagAggregates, lag_estimates, &aggregator); |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag2, *aggregated_lag); |
+} |
+ |
+// Verifies that varying lag estimates causes lag estimates to not be deemed |
+// reliable. |
+TEST(MatchedFilterLagAggregator, |
+ LagEstimateInvarianceRequiredForAggregatedLag) { |
+ constexpr size_t kArtificialLag1 = 5; |
+ constexpr size_t kArtificialLag2 = 10; |
+ ApmDataDumper data_dumper(0); |
+ std::vector<MatchedFilter::LagEstimate> lag_estimates(1); |
+ MatchedFilterLagAggregator aggregator(&data_dumper, lag_estimates.size()); |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag1, true); |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredLagUpdatesInARow + |
+ kThresholdForRequiredIdenticalLagAggregates, |
+ lag_estimates, &aggregator); |
+ rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag1, *aggregated_lag); |
+ |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag2, true); |
+ |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredIdenticalLagAggregates, lag_estimates, &aggregator); |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag2, *aggregated_lag); |
+} |
+ |
+// Verifies that lag estimate updates are required to produce an updated lag |
+// aggregate. |
+TEST(MatchedFilterLagAggregator, LagEstimateUpdatesRequiredForAggregatedLag) { |
+ constexpr size_t kArtificialLag1 = 5; |
+ constexpr size_t kArtificialLag2 = 10; |
+ ApmDataDumper data_dumper(0); |
+ std::vector<MatchedFilter::LagEstimate> lag_estimates(1); |
+ MatchedFilterLagAggregator aggregator(&data_dumper, lag_estimates.size()); |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag1, true); |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredLagUpdatesInARow + |
+ kThresholdForRequiredIdenticalLagAggregates, |
+ lag_estimates, &aggregator); |
+ rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag1, *aggregated_lag); |
+ |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag2, false); |
+ |
+ for (size_t k = 0; k < kThresholdForRequiredLagUpdatesInARow + |
+ kThresholdForRequiredIdenticalLagAggregates + 1; |
+ ++k) { |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag1, *aggregated_lag); |
+ } |
+ |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag2, true); |
+ for (size_t k = 0; k < kThresholdForRequiredLagUpdatesInARow; ++k) { |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag1, *aggregated_lag); |
+ } |
+ |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredIdenticalLagAggregates, lag_estimates, &aggregator); |
+ |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag2, *aggregated_lag); |
+} |
+ |
+// Verifies that an aggregated lag is persistent if the lag estimates do not |
+// change and that an aggregated lag is not produced without gaining lag |
+// estimate confidence. |
+TEST(MatchedFilterLagAggregator, PersistentAggregatedLag) { |
+ constexpr size_t kArtificialLag = 5; |
+ ApmDataDumper data_dumper(0); |
+ std::vector<MatchedFilter::LagEstimate> lag_estimates(1); |
+ MatchedFilterLagAggregator aggregator(&data_dumper, lag_estimates.size()); |
+ lag_estimates[0] = |
+ MatchedFilter::LagEstimate(1.f, true, kArtificialLag, true); |
+ VerifyNoAggregateOutputForRepeatedLagAggregation( |
+ kThresholdForRequiredLagUpdatesInARow + |
+ kThresholdForRequiredIdenticalLagAggregates, |
+ lag_estimates, &aggregator); |
+ rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag, *aggregated_lag); |
+ |
+ aggregated_lag = aggregator.Aggregate(lag_estimates); |
+ EXPECT_TRUE(aggregated_lag); |
+ EXPECT_EQ(kArtificialLag, *aggregated_lag); |
+} |
+ |
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
+ |
+// Verifies the check for correct number of lag estimates. |
+TEST(MatchedFilterLagAggregator, IncorrectNumberOfLagEstimates) { |
+ ApmDataDumper data_dumper(0); |
+ MatchedFilterLagAggregator aggregator(&data_dumper, 1); |
+ std::vector<MatchedFilter::LagEstimate> lag_estimates(2); |
+ |
+ EXPECT_DEATH(aggregator.Aggregate(lag_estimates), ""); |
+} |
+ |
+// Verifies the check for non-zero number of lag estimates. |
+TEST(MatchedFilterLagAggregator, NonZeroLagEstimates) { |
+ ApmDataDumper data_dumper(0); |
+ EXPECT_DEATH(MatchedFilterLagAggregator(&data_dumper, 0), ""); |
+} |
+ |
+// Verifies the check for non-null data dumper. |
+TEST(MatchedFilterLagAggregator, NullDataDumper) { |
+ EXPECT_DEATH(MatchedFilterLagAggregator(nullptr, 1), ""); |
+} |
+ |
+#endif |
+ |
+} // namespace webrtc |