1 /*
2 * Copyright (c) 2013 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/transient/moving_moments.h"
12
13 #include <memory>
14
15 #include "test/gtest.h"
16
17 namespace webrtc {
18
19 static const float kTolerance = 0.0001f;
20
21 class MovingMomentsTest : public ::testing::Test {
22 protected:
23 static const size_t kMovingMomentsBufferLength = 5;
24 static const size_t kMaxOutputLength = 20; // Valid for this tests only.
25
26 virtual void SetUp();
27 // Calls CalculateMoments and verifies that it produces the expected
28 // outputs.
29 void CalculateMomentsAndVerify(const float* input,
30 size_t input_length,
31 const float* expected_mean,
32 const float* expected_mean_squares);
33
34 std::unique_ptr<MovingMoments> moving_moments_;
35 float output_mean_[kMaxOutputLength];
36 float output_mean_squares_[kMaxOutputLength];
37 };
38
39 const size_t MovingMomentsTest::kMaxOutputLength;
40
SetUp()41 void MovingMomentsTest::SetUp() {
42 moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
43 }
44
CalculateMomentsAndVerify(const float * input,size_t input_length,const float * expected_mean,const float * expected_mean_squares)45 void MovingMomentsTest::CalculateMomentsAndVerify(
46 const float* input,
47 size_t input_length,
48 const float* expected_mean,
49 const float* expected_mean_squares) {
50 ASSERT_LE(input_length, kMaxOutputLength);
51
52 moving_moments_->CalculateMoments(input, input_length, output_mean_,
53 output_mean_squares_);
54
55 for (size_t i = 1; i < input_length; ++i) {
56 EXPECT_NEAR(expected_mean[i], output_mean_[i], kTolerance);
57 EXPECT_NEAR(expected_mean_squares[i], output_mean_squares_[i], kTolerance);
58 }
59 }
60
TEST_F(MovingMomentsTest,CorrectMomentsOfAnAllZerosBuffer)61 TEST_F(MovingMomentsTest, CorrectMomentsOfAnAllZerosBuffer) {
62 const float kInput[] = {0.f, 0.f, 0.f, 0.f, 0.f};
63 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
64
65 const float expected_mean[kInputLength] = {0.f, 0.f, 0.f, 0.f, 0.f};
66 const float expected_mean_squares[kInputLength] = {0.f, 0.f, 0.f, 0.f, 0.f};
67
68 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
69 expected_mean_squares);
70 }
71
TEST_F(MovingMomentsTest,CorrectMomentsOfAConstantBuffer)72 TEST_F(MovingMomentsTest, CorrectMomentsOfAConstantBuffer) {
73 const float kInput[] = {5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f};
74 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
75
76 const float expected_mean[kInputLength] = {1.f, 2.f, 3.f, 4.f, 5.f,
77 5.f, 5.f, 5.f, 5.f, 5.f};
78 const float expected_mean_squares[kInputLength] = {
79 5.f, 10.f, 15.f, 20.f, 25.f, 25.f, 25.f, 25.f, 25.f, 25.f};
80
81 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
82 expected_mean_squares);
83 }
84
TEST_F(MovingMomentsTest,CorrectMomentsOfAnIncreasingBuffer)85 TEST_F(MovingMomentsTest, CorrectMomentsOfAnIncreasingBuffer) {
86 const float kInput[] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f};
87 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
88
89 const float expected_mean[kInputLength] = {0.2f, 0.6f, 1.2f, 2.f, 3.f,
90 4.f, 5.f, 6.f, 7.f};
91 const float expected_mean_squares[kInputLength] = {
92 0.2f, 1.f, 2.8f, 6.f, 11.f, 18.f, 27.f, 38.f, 51.f};
93
94 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
95 expected_mean_squares);
96 }
97
TEST_F(MovingMomentsTest,CorrectMomentsOfADecreasingBuffer)98 TEST_F(MovingMomentsTest, CorrectMomentsOfADecreasingBuffer) {
99 const float kInput[] = {-1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f};
100 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
101
102 const float expected_mean[kInputLength] = {-0.2f, -0.6f, -1.2f, -2.f, -3.f,
103 -4.f, -5.f, -6.f, -7.f};
104 const float expected_mean_squares[kInputLength] = {
105 0.2f, 1.f, 2.8f, 6.f, 11.f, 18.f, 27.f, 38.f, 51.f};
106
107 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
108 expected_mean_squares);
109 }
110
TEST_F(MovingMomentsTest,CorrectMomentsOfAZeroMeanSequence)111 TEST_F(MovingMomentsTest, CorrectMomentsOfAZeroMeanSequence) {
112 const size_t kMovingMomentsBufferLength = 4;
113 moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
114 const float kInput[] = {1.f, -1.f, 1.f, -1.f, 1.f,
115 -1.f, 1.f, -1.f, 1.f, -1.f};
116 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
117
118 const float expected_mean[kInputLength] = {0.25f, 0.f, 0.25f, 0.f, 0.f,
119 0.f, 0.f, 0.f, 0.f, 0.f};
120 const float expected_mean_squares[kInputLength] = {
121 0.25f, 0.5f, 0.75f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
122
123 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
124 expected_mean_squares);
125 }
126
TEST_F(MovingMomentsTest,CorrectMomentsOfAnArbitraryBuffer)127 TEST_F(MovingMomentsTest, CorrectMomentsOfAnArbitraryBuffer) {
128 const float kInput[] = {0.2f, 0.3f, 0.5f, 0.7f, 0.11f,
129 0.13f, 0.17f, 0.19f, 0.23f};
130 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
131
132 const float expected_mean[kInputLength] = {
133 0.04f, 0.1f, 0.2f, 0.34f, 0.362f, 0.348f, 0.322f, 0.26f, 0.166f};
134 const float expected_mean_squares[kInputLength] = {0.008f, 0.026f, 0.076f,
135 0.174f, 0.1764f, 0.1718f,
136 0.1596f, 0.1168f, 0.0294f};
137
138 CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
139 expected_mean_squares);
140 }
141
TEST_F(MovingMomentsTest,MutipleCalculateMomentsCalls)142 TEST_F(MovingMomentsTest, MutipleCalculateMomentsCalls) {
143 const float kInputFirstCall[] = {0.2f, 0.3f, 0.5f, 0.7f, 0.11f,
144 0.13f, 0.17f, 0.19f, 0.23f};
145 const size_t kInputFirstCallLength =
146 sizeof(kInputFirstCall) / sizeof(kInputFirstCall[0]);
147 const float kInputSecondCall[] = {0.29f, 0.31f};
148 const size_t kInputSecondCallLength =
149 sizeof(kInputSecondCall) / sizeof(kInputSecondCall[0]);
150 const float kInputThirdCall[] = {0.37f, 0.41f, 0.43f, 0.47f};
151 const size_t kInputThirdCallLength =
152 sizeof(kInputThirdCall) / sizeof(kInputThirdCall[0]);
153
154 const float expected_mean_first_call[kInputFirstCallLength] = {
155 0.04f, 0.1f, 0.2f, 0.34f, 0.362f, 0.348f, 0.322f, 0.26f, 0.166f};
156 const float expected_mean_squares_first_call[kInputFirstCallLength] = {
157 0.008f, 0.026f, 0.076f, 0.174f, 0.1764f,
158 0.1718f, 0.1596f, 0.1168f, 0.0294f};
159
160 const float expected_mean_second_call[kInputSecondCallLength] = {0.202f,
161 0.238f};
162 const float expected_mean_squares_second_call[kInputSecondCallLength] = {
163 0.0438f, 0.0596f};
164
165 const float expected_mean_third_call[kInputThirdCallLength] = {
166 0.278f, 0.322f, 0.362f, 0.398f};
167 const float expected_mean_squares_third_call[kInputThirdCallLength] = {
168 0.0812f, 0.1076f, 0.134f, 0.1614f};
169
170 CalculateMomentsAndVerify(kInputFirstCall, kInputFirstCallLength,
171 expected_mean_first_call,
172 expected_mean_squares_first_call);
173
174 CalculateMomentsAndVerify(kInputSecondCall, kInputSecondCallLength,
175 expected_mean_second_call,
176 expected_mean_squares_second_call);
177
178 CalculateMomentsAndVerify(kInputThirdCall, kInputThirdCallLength,
179 expected_mean_third_call,
180 expected_mean_squares_third_call);
181 }
182
TEST_F(MovingMomentsTest,VerifySampleBasedVsBlockBasedCalculation)183 TEST_F(MovingMomentsTest, VerifySampleBasedVsBlockBasedCalculation) {
184 const float kInput[] = {0.2f, 0.3f, 0.5f, 0.7f, 0.11f,
185 0.13f, 0.17f, 0.19f, 0.23f};
186 const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
187
188 float output_mean_block_based[kInputLength];
189 float output_mean_squares_block_based[kInputLength];
190
191 float output_mean_sample_based;
192 float output_mean_squares_sample_based;
193
194 moving_moments_->CalculateMoments(kInput, kInputLength,
195 output_mean_block_based,
196 output_mean_squares_block_based);
197 moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
198 for (size_t i = 0; i < kInputLength; ++i) {
199 moving_moments_->CalculateMoments(&kInput[i], 1, &output_mean_sample_based,
200 &output_mean_squares_sample_based);
201 EXPECT_FLOAT_EQ(output_mean_block_based[i], output_mean_sample_based);
202 EXPECT_FLOAT_EQ(output_mean_squares_block_based[i],
203 output_mean_squares_sample_based);
204 }
205 }
206
207 } // namespace webrtc
208