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, size_t input_length,
30                                  const float* expected_mean,
31                                  const float* expected_mean_squares);
32 
33   std::unique_ptr<MovingMoments> moving_moments_;
34   float output_mean_[kMaxOutputLength];
35   float output_mean_squares_[kMaxOutputLength];
36 };
37 
38 const size_t MovingMomentsTest::kMaxOutputLength;
39 
SetUp()40 void MovingMomentsTest::SetUp() {
41   moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
42 }
43 
CalculateMomentsAndVerify(const float * input,size_t input_length,const float * expected_mean,const float * expected_mean_squares)44 void MovingMomentsTest::CalculateMomentsAndVerify(
45     const float* input, size_t input_length,
46     const float* expected_mean,
47     const float* expected_mean_squares) {
48   ASSERT_LE(input_length, kMaxOutputLength);
49 
50   moving_moments_->CalculateMoments(input,
51                                     input_length,
52                                     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] =
77       {1.f, 2.f, 3.f, 4.f, 5.f, 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] =
90       {0.2f, 0.6f, 1.2f, 2.f, 3.f, 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[] =
100       {-1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f};
101   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
102 
103   const float expected_mean[kInputLength] =
104       {-0.2f, -0.6f, -1.2f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f};
105   const float expected_mean_squares[kInputLength] =
106       {0.2f, 1.f, 2.8f, 6.f, 11.f, 18.f, 27.f, 38.f, 51.f};
107 
108   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
109                             expected_mean_squares);
110 }
111 
TEST_F(MovingMomentsTest,CorrectMomentsOfAZeroMeanSequence)112 TEST_F(MovingMomentsTest, CorrectMomentsOfAZeroMeanSequence) {
113   const size_t kMovingMomentsBufferLength = 4;
114   moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
115   const float kInput[] =
116       {1.f, -1.f, 1.f, -1.f, 1.f, -1.f, 1.f, -1.f, 1.f, -1.f};
117   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
118 
119   const float expected_mean[kInputLength] =
120       {0.25f, 0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
121   const float expected_mean_squares[kInputLength] =
122       {0.25f, 0.5f, 0.75f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
123 
124   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
125                             expected_mean_squares);
126 }
127 
TEST_F(MovingMomentsTest,CorrectMomentsOfAnArbitraryBuffer)128 TEST_F(MovingMomentsTest, CorrectMomentsOfAnArbitraryBuffer) {
129   const float kInput[] =
130       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 0.13f, 0.17f, 0.19f, 0.23f};
131   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
132 
133   const float expected_mean[kInputLength] =
134       {0.04f, 0.1f, 0.2f, 0.34f, 0.362f, 0.348f, 0.322f, 0.26f, 0.166f};
135   const float expected_mean_squares[kInputLength] =
136       {0.008f, 0.026f, 0.076f, 0.174f, 0.1764f, 0.1718f, 0.1596f, 0.1168f,
137       0.0294f};
138 
139   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
140                             expected_mean_squares);
141 }
142 
TEST_F(MovingMomentsTest,MutipleCalculateMomentsCalls)143 TEST_F(MovingMomentsTest, MutipleCalculateMomentsCalls) {
144   const float kInputFirstCall[] =
145       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 0.13f, 0.17f, 0.19f, 0.23f};
146   const size_t kInputFirstCallLength = sizeof(kInputFirstCall) /
147                                     sizeof(kInputFirstCall[0]);
148   const float kInputSecondCall[] = {0.29f, 0.31f};
149   const size_t kInputSecondCallLength = sizeof(kInputSecondCall) /
150                                      sizeof(kInputSecondCall[0]);
151   const float kInputThirdCall[] = {0.37f, 0.41f, 0.43f, 0.47f};
152   const size_t kInputThirdCallLength = sizeof(kInputThirdCall) /
153                                     sizeof(kInputThirdCall[0]);
154 
155   const float expected_mean_first_call[kInputFirstCallLength] =
156       {0.04f, 0.1f, 0.2f, 0.34f, 0.362f, 0.348f, 0.322f, 0.26f, 0.166f};
157   const float expected_mean_squares_first_call[kInputFirstCallLength] =
158       {0.008f, 0.026f, 0.076f, 0.174f, 0.1764f, 0.1718f, 0.1596f, 0.1168f,
159       0.0294f};
160 
161   const float expected_mean_second_call[kInputSecondCallLength] =
162       {0.202f, 0.238f};
163   const float expected_mean_squares_second_call[kInputSecondCallLength] =
164       {0.0438f, 0.0596f};
165 
166   const float expected_mean_third_call[kInputThirdCallLength] =
167       {0.278f, 0.322f, 0.362f, 0.398f};
168   const float expected_mean_squares_third_call[kInputThirdCallLength] =
169       {0.0812f, 0.1076f, 0.134f, 0.1614f};
170 
171   CalculateMomentsAndVerify(kInputFirstCall, kInputFirstCallLength,
172       expected_mean_first_call, expected_mean_squares_first_call);
173 
174   CalculateMomentsAndVerify(kInputSecondCall, kInputSecondCallLength,
175       expected_mean_second_call, expected_mean_squares_second_call);
176 
177   CalculateMomentsAndVerify(kInputThirdCall, kInputThirdCallLength,
178       expected_mean_third_call, expected_mean_squares_third_call);
179 }
180 
TEST_F(MovingMomentsTest,VerifySampleBasedVsBlockBasedCalculation)181 TEST_F(MovingMomentsTest,
182        VerifySampleBasedVsBlockBasedCalculation) {
183   const float kInput[] =
184       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 0.13f, 0.17f, 0.19f, 0.23f};
185   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
186 
187   float output_mean_block_based[kInputLength];
188   float output_mean_squares_block_based[kInputLength];
189 
190   float output_mean_sample_based;
191   float output_mean_squares_sample_based;
192 
193   moving_moments_->CalculateMoments(
194       kInput, kInputLength, output_mean_block_based,
195       output_mean_squares_block_based);
196   moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
197   for (size_t i = 0; i < kInputLength; ++i) {
198     moving_moments_->CalculateMoments(
199         &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