blob: 4df8b488b3a00d09ffff6afa4caefc56ddc2ead6 [file] [log] [blame]
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +01001/*
2 * Copyright (c) 2019 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/audio_coding/neteq/histogram.h"
12
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010013#include <cmath>
14
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010015#include "test/gtest.h"
16
17namespace webrtc {
18
19TEST(HistogramTest, Initialization) {
20 Histogram histogram(65, 32440);
21 histogram.Reset();
22 const auto& buckets = histogram.buckets();
23 double sum = 0.0;
24 for (size_t i = 0; i < buckets.size(); i++) {
25 EXPECT_NEAR(ldexp(std::pow(0.5, static_cast<int>(i + 1)), 30), buckets[i],
26 65537);
27 // Tolerance 65537 in Q30 corresponds to a delta of approximately 0.00006.
28 sum += buckets[i];
29 }
30 EXPECT_EQ(1 << 30, static_cast<int>(sum)); // Should be 1 in Q30.
31}
32
33TEST(HistogramTest, Add) {
34 Histogram histogram(10, 32440);
35 histogram.Reset();
36 const std::vector<int> before = histogram.buckets();
37 const int index = 5;
38 histogram.Add(index);
39 const std::vector<int> after = histogram.buckets();
40 EXPECT_GT(after[index], before[index]);
41 int sum = 0;
42 for (int bucket : after) {
43 sum += bucket;
44 }
45 EXPECT_EQ(1 << 30, sum);
46}
47
48TEST(HistogramTest, ForgetFactor) {
49 Histogram histogram(10, 32440);
50 histogram.Reset();
51 const std::vector<int> before = histogram.buckets();
52 const int index = 4;
53 histogram.Add(index);
54 const std::vector<int> after = histogram.buckets();
55 for (int i = 0; i < histogram.NumBuckets(); ++i) {
56 if (i != index) {
57 EXPECT_LT(after[i], before[i]);
58 }
59 }
60}
61
62// Test if the histogram is scaled correctly if the bucket width is decreased.
63TEST(HistogramTest, DownScale) {
64 // Test a straightforward 60 to 20 change.
65 std::vector<int> buckets = {12, 0, 0, 0, 0, 0};
66 std::vector<int> expected_result = {4, 4, 4, 0, 0, 0};
67 std::vector<int> stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
68 EXPECT_EQ(stretched_buckets, expected_result);
69
70 // Test an example where the last bin in the stretched histogram should
71 // contain the sum of the elements that don't fit into the new histogram.
72 buckets = {18, 15, 12, 9, 6, 3, 0};
73 expected_result = {6, 6, 6, 5, 5, 5, 30};
74 stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
75 EXPECT_EQ(stretched_buckets, expected_result);
76
77 // Test a 120 to 60 change.
78 buckets = {18, 16, 14, 4, 0};
79 expected_result = {9, 9, 8, 8, 18};
80 stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 60);
81 EXPECT_EQ(stretched_buckets, expected_result);
82
83 // Test a 120 to 20 change.
84 buckets = {19, 12, 0, 0, 0, 0, 0, 0};
85 expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
86 stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 20);
87 EXPECT_EQ(stretched_buckets, expected_result);
88
89 // Test a 70 to 40 change.
90 buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
91 expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
92 stretched_buckets = Histogram::ScaleBuckets(buckets, 70, 40);
93 EXPECT_EQ(stretched_buckets, expected_result);
94
95 // Test a 30 to 20 change.
96 buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
97 expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
98 stretched_buckets = Histogram::ScaleBuckets(buckets, 30, 20);
99 EXPECT_EQ(stretched_buckets, expected_result);
100}
101
102// Test if the histogram is scaled correctly if the bucket width is increased.
103TEST(HistogramTest, UpScale) {
104 // Test a 20 to 60 change.
105 std::vector<int> buckets = {12, 11, 10, 3, 2, 1};
106 std::vector<int> expected_result = {33, 6, 0, 0, 0, 0};
107 std::vector<int> compressed_buckets =
108 Histogram::ScaleBuckets(buckets, 20, 60);
109 EXPECT_EQ(compressed_buckets, expected_result);
110
111 // Test a 60 to 120 change.
112 buckets = {18, 16, 14, 4, 1};
113 expected_result = {34, 18, 1, 0, 0};
114 compressed_buckets = Histogram::ScaleBuckets(buckets, 60, 120);
115 EXPECT_EQ(compressed_buckets, expected_result);
116
117 // Test a 20 to 120 change.
118 buckets = {18, 12, 5, 4, 4, 3, 5, 1};
119 expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
120 compressed_buckets = Histogram::ScaleBuckets(buckets, 20, 120);
121 EXPECT_EQ(compressed_buckets, expected_result);
122
123 // Test a 70 to 80 change.
124 buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
125 expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
126 compressed_buckets = Histogram::ScaleBuckets(buckets, 70, 80);
127 EXPECT_EQ(compressed_buckets, expected_result);
128
129 // Test a 50 to 110 change.
130 buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
131 expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
132 compressed_buckets = Histogram::ScaleBuckets(buckets, 50, 110);
133 EXPECT_EQ(compressed_buckets, expected_result);
134}
135
136// Test if the histogram scaling function handles overflows correctly.
137TEST(HistogramTest, OverflowTest) {
138 // Test a upscale operation that can cause overflow.
139 std::vector<int> buckets = {733544448, 0, 0, 0, 0, 0, 0,
140 340197376, 0, 0, 0, 0, 0, 0};
141 std::vector<int> expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0};
143 std::vector<int> scaled_buckets = Histogram::ScaleBuckets(buckets, 10, 60);
144 EXPECT_EQ(scaled_buckets, expected_result);
145
146 buckets = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
147 114119, 2072996, 0, 2149354, 0};
148 expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
149 0, 0, 0, 0, 0};
150 scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
151 EXPECT_EQ(scaled_buckets, expected_result);
152
153 // In this test case we will not be able to add everything to the final bin in
154 // the scaled histogram. Check that the last bin doesn't overflow.
155 buckets = {2000000000, 2000000000, 2000000000,
156 2000000000, 2000000000, 2000000000};
157 expected_result = {666666666, 666666666, 666666666,
158 666666667, 666666667, 2147483647};
159 scaled_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
160 EXPECT_EQ(scaled_buckets, expected_result);
161
162 // In this test case we will not be able to add enough to each of the bins,
163 // so the values should be smeared out past the end of the normal range.
164 buckets = {2000000000, 2000000000, 2000000000,
165 2000000000, 2000000000, 2000000000};
166 expected_result = {2147483647, 2147483647, 2147483647,
167 2147483647, 2147483647, 1262581765};
168 scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
169 EXPECT_EQ(scaled_buckets, expected_result);
170}
171
Jakob Ivarssone9a2ee22019-05-22 16:54:09 +0200172TEST(HistogramTest, ReachSteadyStateForgetFactor) {
173 static constexpr int kSteadyStateForgetFactor = (1 << 15) * 0.9993;
174 Histogram histogram(100, kSteadyStateForgetFactor, 1.0);
175 histogram.Reset();
176 int n = (1 << 15) / ((1 << 15) - kSteadyStateForgetFactor);
177 for (int i = 0; i < n; ++i) {
178 histogram.Add(0);
179 }
180 EXPECT_EQ(histogram.forget_factor_for_testing(), kSteadyStateForgetFactor);
181}
182
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100183} // namespace webrtc