1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/audio_processing/agc2/input_volume_stats_reporter.h"
12
13 #include "absl/strings/string_view.h"
14 #include "rtc_base/strings/string_builder.h"
15 #include "system_wrappers/include/metrics.h"
16 #include "test/gmock.h"
17
18 namespace webrtc {
19 namespace {
20
21 using InputVolumeType = InputVolumeStatsReporter::InputVolumeType;
22
23 constexpr int kFramesIn60Seconds = 6000;
24
25 constexpr absl::string_view kLabelPrefix = "WebRTC.Audio.Apm.";
26
27 class InputVolumeStatsReporterTest
28 : public ::testing::TestWithParam<InputVolumeType> {
29 public:
InputVolumeStatsReporterTest()30 InputVolumeStatsReporterTest() { metrics::Reset(); }
31
32 protected:
InputVolumeType() const33 InputVolumeType InputVolumeType() const { return GetParam(); }
DecreaseRateLabel() const34 std::string DecreaseRateLabel() const {
35 return (rtc::StringBuilder(kLabelPrefix)
36 << VolumeTypeLabel() << "DecreaseRate")
37 .str();
38 }
DecreaseAverageLabel() const39 std::string DecreaseAverageLabel() const {
40 return (rtc::StringBuilder(kLabelPrefix)
41 << VolumeTypeLabel() << "DecreaseAverage")
42 .str();
43 }
IncreaseRateLabel() const44 std::string IncreaseRateLabel() const {
45 return (rtc::StringBuilder(kLabelPrefix)
46 << VolumeTypeLabel() << "IncreaseRate")
47 .str();
48 }
IncreaseAverageLabel() const49 std::string IncreaseAverageLabel() const {
50 return (rtc::StringBuilder(kLabelPrefix)
51 << VolumeTypeLabel() << "IncreaseAverage")
52 .str();
53 }
UpdateRateLabel() const54 std::string UpdateRateLabel() const {
55 return (rtc::StringBuilder(kLabelPrefix)
56 << VolumeTypeLabel() << "UpdateRate")
57 .str();
58 }
UpdateAverageLabel() const59 std::string UpdateAverageLabel() const {
60 return (rtc::StringBuilder(kLabelPrefix)
61 << VolumeTypeLabel() << "UpdateAverage")
62 .str();
63 }
64
65 private:
VolumeTypeLabel() const66 absl::string_view VolumeTypeLabel() const {
67 switch (InputVolumeType()) {
68 case InputVolumeType::kApplied:
69 return "AppliedInputVolume.";
70 case InputVolumeType::kRecommended:
71 return "RecommendedInputVolume.";
72 }
73 }
74 };
75
TEST_P(InputVolumeStatsReporterTest,CheckLogVolumeUpdateStatsEmpty)76 TEST_P(InputVolumeStatsReporterTest, CheckLogVolumeUpdateStatsEmpty) {
77 InputVolumeStatsReporter stats_reporter(InputVolumeType());
78 constexpr int kInputVolume = 10;
79 stats_reporter.UpdateStatistics(kInputVolume);
80 // Update almost until the periodic logging and reset.
81 for (int i = 0; i < kFramesIn60Seconds - 2; i += 2) {
82 stats_reporter.UpdateStatistics(kInputVolume + 2);
83 stats_reporter.UpdateStatistics(kInputVolume);
84 }
85 EXPECT_METRIC_THAT(metrics::Samples(UpdateRateLabel()),
86 ::testing::ElementsAre());
87 EXPECT_METRIC_THAT(metrics::Samples(DecreaseRateLabel()),
88 ::testing::ElementsAre());
89 EXPECT_METRIC_THAT(metrics::Samples(IncreaseRateLabel()),
90 ::testing::ElementsAre());
91 EXPECT_METRIC_THAT(metrics::Samples(UpdateAverageLabel()),
92 ::testing::ElementsAre());
93 EXPECT_METRIC_THAT(metrics::Samples(DecreaseAverageLabel()),
94 ::testing::ElementsAre());
95 EXPECT_METRIC_THAT(metrics::Samples(IncreaseAverageLabel()),
96 ::testing::ElementsAre());
97 }
98
TEST_P(InputVolumeStatsReporterTest,CheckLogVolumeUpdateStatsNotEmpty)99 TEST_P(InputVolumeStatsReporterTest, CheckLogVolumeUpdateStatsNotEmpty) {
100 InputVolumeStatsReporter stats_reporter(InputVolumeType());
101 constexpr int kInputVolume = 10;
102 stats_reporter.UpdateStatistics(kInputVolume);
103 // Update until periodic logging.
104 for (int i = 0; i < kFramesIn60Seconds; i += 2) {
105 stats_reporter.UpdateStatistics(kInputVolume + 2);
106 stats_reporter.UpdateStatistics(kInputVolume);
107 }
108 // Update until periodic logging.
109 for (int i = 0; i < kFramesIn60Seconds; i += 2) {
110 stats_reporter.UpdateStatistics(kInputVolume + 3);
111 stats_reporter.UpdateStatistics(kInputVolume);
112 }
113 EXPECT_METRIC_THAT(
114 metrics::Samples(UpdateRateLabel()),
115 ::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds - 1, 1),
116 ::testing::Pair(kFramesIn60Seconds, 1)));
117 EXPECT_METRIC_THAT(
118 metrics::Samples(DecreaseRateLabel()),
119 ::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds / 2 - 1, 1),
120 ::testing::Pair(kFramesIn60Seconds / 2, 1)));
121 EXPECT_METRIC_THAT(
122 metrics::Samples(IncreaseRateLabel()),
123 ::testing::ElementsAre(::testing::Pair(kFramesIn60Seconds / 2, 2)));
124 EXPECT_METRIC_THAT(
125 metrics::Samples(UpdateAverageLabel()),
126 ::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
127 EXPECT_METRIC_THAT(
128 metrics::Samples(DecreaseAverageLabel()),
129 ::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
130 EXPECT_METRIC_THAT(
131 metrics::Samples(IncreaseAverageLabel()),
132 ::testing::ElementsAre(::testing::Pair(2, 1), ::testing::Pair(3, 1)));
133 }
134 } // namespace
135
TEST_P(InputVolumeStatsReporterTest,CheckVolumeUpdateStatsForEmptyStats)136 TEST_P(InputVolumeStatsReporterTest, CheckVolumeUpdateStatsForEmptyStats) {
137 InputVolumeStatsReporter stats_reporter(InputVolumeType());
138 const auto& update_stats = stats_reporter.volume_update_stats();
139 EXPECT_EQ(update_stats.num_decreases, 0);
140 EXPECT_EQ(update_stats.sum_decreases, 0);
141 EXPECT_EQ(update_stats.num_increases, 0);
142 EXPECT_EQ(update_stats.sum_increases, 0);
143 }
144
TEST_P(InputVolumeStatsReporterTest,CheckVolumeUpdateStatsAfterNoVolumeChange)145 TEST_P(InputVolumeStatsReporterTest,
146 CheckVolumeUpdateStatsAfterNoVolumeChange) {
147 constexpr int kInputVolume = 10;
148 InputVolumeStatsReporter stats_reporter(InputVolumeType());
149 stats_reporter.UpdateStatistics(kInputVolume);
150 stats_reporter.UpdateStatistics(kInputVolume);
151 stats_reporter.UpdateStatistics(kInputVolume);
152 const auto& update_stats = stats_reporter.volume_update_stats();
153 EXPECT_EQ(update_stats.num_decreases, 0);
154 EXPECT_EQ(update_stats.sum_decreases, 0);
155 EXPECT_EQ(update_stats.num_increases, 0);
156 EXPECT_EQ(update_stats.sum_increases, 0);
157 }
158
TEST_P(InputVolumeStatsReporterTest,CheckVolumeUpdateStatsAfterVolumeIncrease)159 TEST_P(InputVolumeStatsReporterTest,
160 CheckVolumeUpdateStatsAfterVolumeIncrease) {
161 constexpr int kInputVolume = 10;
162 InputVolumeStatsReporter stats_reporter(InputVolumeType());
163 stats_reporter.UpdateStatistics(kInputVolume);
164 stats_reporter.UpdateStatistics(kInputVolume + 4);
165 stats_reporter.UpdateStatistics(kInputVolume + 5);
166 const auto& update_stats = stats_reporter.volume_update_stats();
167 EXPECT_EQ(update_stats.num_decreases, 0);
168 EXPECT_EQ(update_stats.sum_decreases, 0);
169 EXPECT_EQ(update_stats.num_increases, 2);
170 EXPECT_EQ(update_stats.sum_increases, 5);
171 }
172
TEST_P(InputVolumeStatsReporterTest,CheckVolumeUpdateStatsAfterVolumeDecrease)173 TEST_P(InputVolumeStatsReporterTest,
174 CheckVolumeUpdateStatsAfterVolumeDecrease) {
175 constexpr int kInputVolume = 10;
176 InputVolumeStatsReporter stats_reporter(InputVolumeType());
177 stats_reporter.UpdateStatistics(kInputVolume);
178 stats_reporter.UpdateStatistics(kInputVolume - 4);
179 stats_reporter.UpdateStatistics(kInputVolume - 5);
180 const auto& stats_update = stats_reporter.volume_update_stats();
181 EXPECT_EQ(stats_update.num_decreases, 2);
182 EXPECT_EQ(stats_update.sum_decreases, 5);
183 EXPECT_EQ(stats_update.num_increases, 0);
184 EXPECT_EQ(stats_update.sum_increases, 0);
185 }
186
TEST_P(InputVolumeStatsReporterTest,CheckVolumeUpdateStatsAfterReset)187 TEST_P(InputVolumeStatsReporterTest, CheckVolumeUpdateStatsAfterReset) {
188 InputVolumeStatsReporter stats_reporter(InputVolumeType());
189 constexpr int kInputVolume = 10;
190 stats_reporter.UpdateStatistics(kInputVolume);
191 // Update until the periodic reset.
192 for (int i = 0; i < kFramesIn60Seconds - 2; i += 2) {
193 stats_reporter.UpdateStatistics(kInputVolume + 2);
194 stats_reporter.UpdateStatistics(kInputVolume);
195 }
196 const auto& stats_before_reset = stats_reporter.volume_update_stats();
197 EXPECT_EQ(stats_before_reset.num_decreases, kFramesIn60Seconds / 2 - 1);
198 EXPECT_EQ(stats_before_reset.sum_decreases, kFramesIn60Seconds - 2);
199 EXPECT_EQ(stats_before_reset.num_increases, kFramesIn60Seconds / 2 - 1);
200 EXPECT_EQ(stats_before_reset.sum_increases, kFramesIn60Seconds - 2);
201 stats_reporter.UpdateStatistics(kInputVolume + 2);
202 const auto& stats_during_reset = stats_reporter.volume_update_stats();
203 EXPECT_EQ(stats_during_reset.num_decreases, 0);
204 EXPECT_EQ(stats_during_reset.sum_decreases, 0);
205 EXPECT_EQ(stats_during_reset.num_increases, 0);
206 EXPECT_EQ(stats_during_reset.sum_increases, 0);
207 stats_reporter.UpdateStatistics(kInputVolume);
208 stats_reporter.UpdateStatistics(kInputVolume + 3);
209 const auto& stats_after_reset = stats_reporter.volume_update_stats();
210 EXPECT_EQ(stats_after_reset.num_decreases, 1);
211 EXPECT_EQ(stats_after_reset.sum_decreases, 2);
212 EXPECT_EQ(stats_after_reset.num_increases, 1);
213 EXPECT_EQ(stats_after_reset.sum_increases, 3);
214 }
215
216 INSTANTIATE_TEST_SUITE_P(,
217 InputVolumeStatsReporterTest,
218 ::testing::Values(InputVolumeType::kApplied,
219 InputVolumeType::kRecommended));
220
221 } // namespace webrtc
222