blob: e762c1fb59f37803d548ddb56cf223e36f99935d [file] [log] [blame]
/*
* Copyright (c) 2021 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 "modules/audio_processing/agc2/input_volume_stats_reporter.h"
#include "absl/strings/string_view.h"
#include "rtc_base/strings/string_builder.h"
#include "system_wrappers/include/metrics.h"
#include "test/gmock.h"
namespace webrtc {
namespace {
using InputVolumeType = InputVolumeStatsReporter::InputVolumeType;
constexpr int kFramesIn60Seconds = 6000;
constexpr absl::string_view kLabelPrefix = "WebRTC.Audio.Apm.";
class InputVolumeStatsReporterTest
: public ::testing::TestWithParam<InputVolumeType> {
public:
InputVolumeStatsReporterTest() { metrics::Reset(); }
protected:
InputVolumeType InputVolumeType() const { return GetParam(); }
std::string VolumeLabel() const {
return (rtc::StringBuilder(kLabelPrefix) << VolumeTypeLabel() << "OnChange")
.str();
}
std::string DecreaseRateLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "DecreaseRate")
.str();
}
std::string DecreaseAverageLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "DecreaseAverage")
.str();
}
std::string IncreaseRateLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "IncreaseRate")
.str();
}
std::string IncreaseAverageLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "IncreaseAverage")
.str();
}
std::string UpdateRateLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "UpdateRate")
.str();
}
std::string UpdateAverageLabel() const {
return (rtc::StringBuilder(kLabelPrefix)
<< VolumeTypeLabel() << "UpdateAverage")
.str();
}
private:
absl::string_view VolumeTypeLabel() const {
switch (InputVolumeType()) {
case InputVolumeType::kApplied:
return "AppliedInputVolume.";
case InputVolumeType::kRecommended:
return "RecommendedInputVolume.";
}
}
};
TEST_P(InputVolumeStatsReporterTest, CheckVolumeOnChangeIsEmpty) {
InputVolumeStatsReporter stats_reporter(InputVolumeType());
stats_reporter.UpdateStatistics(10);
EXPECT_METRIC_THAT(metrics::Samples(VolumeLabel()), ::testing::ElementsAre());
}
TEST_P(InputVolumeStatsReporterTest, CheckRateAverageStatsEmpty) {
InputVolumeStatsReporter stats_reporter(InputVolumeType());
constexpr int kInputVolume = 10;
stats_reporter.UpdateStatistics(kInputVolume);
// Update almost until the periodic logging and reset.
for (int i = 0; i < kFramesIn60Seconds - 2; i += 2) {
stats_reporter.UpdateStatistics(kInputVolume + 2);
stats_reporter.UpdateStatistics(kInputVolume);
}
EXPECT_METRIC_THAT(metrics::Samples(UpdateRateLabel()),
::testing::ElementsAre());
EXPECT_METRIC_THAT(metrics::Samples(DecreaseRateLabel()),
::testing::ElementsAre());
EXPECT_METRIC_THAT(metrics::Samples(IncreaseRateLabel()),
::testing::ElementsAre());
EXPECT_METRIC_THAT(metrics::Samples(UpdateAverageLabel()),
::testing::ElementsAre());
EXPECT_METRIC_THAT(metrics::Samples(DecreaseAverageLabel()),
::testing::ElementsAre());
EXPECT_METRIC_THAT(metrics::Samples(IncreaseAverageLabel()),
::testing::ElementsAre());
}
TEST_P(InputVolumeStatsReporterTest, CheckSamples) {
InputVolumeStatsReporter stats_reporter(InputVolumeType());
constexpr int kInputVolume1 = 10;
stats_reporter.UpdateStatistics(kInputVolume1);
// Update until periodic logging.
constexpr int kInputVolume2 = 12;
for (int i = 0; i < kFramesIn60Seconds; i += 2) {
stats_reporter.UpdateStatistics(kInputVolume2);
stats_reporter.UpdateStatistics(kInputVolume1);
}
// Update until periodic logging.
constexpr int kInputVolume3 = 13;
for (int i = 0; i < kFramesIn60Seconds; i += 2) {
stats_reporter.UpdateStatistics(kInputVolume3);
stats_reporter.UpdateStatistics(kInputVolume1);
}
// Check volume changes stats.
EXPECT_METRIC_THAT(
metrics::Samples(VolumeLabel()),
::testing::ElementsAre(
::testing::Pair(kInputVolume1, kFramesIn60Seconds),
::testing::Pair(kInputVolume2, kFramesIn60Seconds / 2),
::testing::Pair(kInputVolume3, kFramesIn60Seconds / 2)));
// Check volume change rate stats.
EXPECT_METRIC_THAT(
metrics::Samples(UpdateRateLabel()),
::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds - 1, 1),
::testing::Pair(kFramesIn60Seconds, 1)));
EXPECT_METRIC_THAT(
metrics::Samples(DecreaseRateLabel()),
::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds / 2 - 1, 1),
::testing::Pair(kFramesIn60Seconds / 2, 1)));
EXPECT_METRIC_THAT(
metrics::Samples(IncreaseRateLabel()),
::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds / 2, 2)));
// Check volume change average stats.
EXPECT_METRIC_THAT(
metrics::Samples(UpdateAverageLabel()),
::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
EXPECT_METRIC_THAT(
metrics::Samples(DecreaseAverageLabel()),
::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
EXPECT_METRIC_THAT(
metrics::Samples(IncreaseAverageLabel()),
::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
}
} // namespace
TEST_P(InputVolumeStatsReporterTest, CheckVolumeUpdateStatsForEmptyStats) {
InputVolumeStatsReporter stats_reporter(InputVolumeType());
const auto& update_stats = stats_reporter.volume_update_stats();
EXPECT_EQ(update_stats.num_decreases, 0);
EXPECT_EQ(update_stats.sum_decreases, 0);
EXPECT_EQ(update_stats.num_increases, 0);
EXPECT_EQ(update_stats.sum_increases, 0);
}
TEST_P(InputVolumeStatsReporterTest,
CheckVolumeUpdateStatsAfterNoVolumeChange) {
constexpr int kInputVolume = 10;
InputVolumeStatsReporter stats_reporter(InputVolumeType());
stats_reporter.UpdateStatistics(kInputVolume);
stats_reporter.UpdateStatistics(kInputVolume);
stats_reporter.UpdateStatistics(kInputVolume);
const auto& update_stats = stats_reporter.volume_update_stats();
EXPECT_EQ(update_stats.num_decreases, 0);
EXPECT_EQ(update_stats.sum_decreases, 0);
EXPECT_EQ(update_stats.num_increases, 0);
EXPECT_EQ(update_stats.sum_increases, 0);
}
TEST_P(InputVolumeStatsReporterTest,
CheckVolumeUpdateStatsAfterVolumeIncrease) {
constexpr int kInputVolume = 10;
InputVolumeStatsReporter stats_reporter(InputVolumeType());
stats_reporter.UpdateStatistics(kInputVolume);
stats_reporter.UpdateStatistics(kInputVolume + 4);
stats_reporter.UpdateStatistics(kInputVolume + 5);
const auto& update_stats = stats_reporter.volume_update_stats();
EXPECT_EQ(update_stats.num_decreases, 0);
EXPECT_EQ(update_stats.sum_decreases, 0);
EXPECT_EQ(update_stats.num_increases, 2);
EXPECT_EQ(update_stats.sum_increases, 5);
}
TEST_P(InputVolumeStatsReporterTest,
CheckVolumeUpdateStatsAfterVolumeDecrease) {
constexpr int kInputVolume = 10;
InputVolumeStatsReporter stats_reporter(InputVolumeType());
stats_reporter.UpdateStatistics(kInputVolume);
stats_reporter.UpdateStatistics(kInputVolume - 4);
stats_reporter.UpdateStatistics(kInputVolume - 5);
const auto& stats_update = stats_reporter.volume_update_stats();
EXPECT_EQ(stats_update.num_decreases, 2);
EXPECT_EQ(stats_update.sum_decreases, 5);
EXPECT_EQ(stats_update.num_increases, 0);
EXPECT_EQ(stats_update.sum_increases, 0);
}
TEST_P(InputVolumeStatsReporterTest, CheckVolumeUpdateStatsAfterReset) {
InputVolumeStatsReporter stats_reporter(InputVolumeType());
constexpr int kInputVolume = 10;
stats_reporter.UpdateStatistics(kInputVolume);
// Update until the periodic reset.
for (int i = 0; i < kFramesIn60Seconds - 2; i += 2) {
stats_reporter.UpdateStatistics(kInputVolume + 2);
stats_reporter.UpdateStatistics(kInputVolume);
}
const auto& stats_before_reset = stats_reporter.volume_update_stats();
EXPECT_EQ(stats_before_reset.num_decreases, kFramesIn60Seconds / 2 - 1);
EXPECT_EQ(stats_before_reset.sum_decreases, kFramesIn60Seconds - 2);
EXPECT_EQ(stats_before_reset.num_increases, kFramesIn60Seconds / 2 - 1);
EXPECT_EQ(stats_before_reset.sum_increases, kFramesIn60Seconds - 2);
stats_reporter.UpdateStatistics(kInputVolume + 2);
const auto& stats_during_reset = stats_reporter.volume_update_stats();
EXPECT_EQ(stats_during_reset.num_decreases, 0);
EXPECT_EQ(stats_during_reset.sum_decreases, 0);
EXPECT_EQ(stats_during_reset.num_increases, 0);
EXPECT_EQ(stats_during_reset.sum_increases, 0);
stats_reporter.UpdateStatistics(kInputVolume);
stats_reporter.UpdateStatistics(kInputVolume + 3);
const auto& stats_after_reset = stats_reporter.volume_update_stats();
EXPECT_EQ(stats_after_reset.num_decreases, 1);
EXPECT_EQ(stats_after_reset.sum_decreases, 2);
EXPECT_EQ(stats_after_reset.num_increases, 1);
EXPECT_EQ(stats_after_reset.sum_increases, 3);
}
INSTANTIATE_TEST_SUITE_P(,
InputVolumeStatsReporterTest,
::testing::Values(InputVolumeType::kApplied,
InputVolumeType::kRecommended));
} // namespace webrtc