blob: 0144bf46c9ed58056f5d2e0f98c674776eb12c4d [file] [log] [blame]
/*
* 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/api/array_view.h"
#include "webrtc/modules/audio_processing/aec3/aec3_common.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 = 15;
} // 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