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 "webrtc/modules/audio_processing/transient/moving_moments.h"
12 
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/base/scoped_ptr.h"
15 
16 namespace webrtc {
17 
18 static const float kTolerance = 0.0001f;
19 
20 class MovingMomentsTest : public ::testing::Test {
21  protected:
22   static const size_t kMovingMomentsBufferLength = 5;
23   static const size_t kMaxOutputLength = 20;  // Valid for this tests only.
24 
25   virtual void SetUp();
26   // Calls CalculateMoments and verifies that it produces the expected
27   // outputs.
28   void CalculateMomentsAndVerify(const float* input, size_t input_length,
29                                  const float* expected_mean,
30                                  const float* expected_mean_squares);
31 
32   rtc::scoped_ptr<MovingMoments> moving_moments_;
33   float output_mean_[kMaxOutputLength];
34   float output_mean_squares_[kMaxOutputLength];
35 };
36 
37 const size_t MovingMomentsTest::kMaxOutputLength;
38 
SetUp()39 void MovingMomentsTest::SetUp() {
40   moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
41 }
42 
CalculateMomentsAndVerify(const float * input,size_t input_length,const float * expected_mean,const float * expected_mean_squares)43 void MovingMomentsTest::CalculateMomentsAndVerify(
44     const float* input, size_t input_length,
45     const float* expected_mean,
46     const float* expected_mean_squares) {
47   ASSERT_LE(input_length, kMaxOutputLength);
48 
49   moving_moments_->CalculateMoments(input,
50                                     input_length,
51                                     output_mean_,
52                                     output_mean_squares_);
53 
54   for (size_t i = 1; i < input_length; ++i) {
55     EXPECT_NEAR(expected_mean[i], output_mean_[i], kTolerance);
56     EXPECT_NEAR(expected_mean_squares[i], output_mean_squares_[i], kTolerance);
57   }
58 }
59 
TEST_F(MovingMomentsTest,CorrectMomentsOfAnAllZerosBuffer)60 TEST_F(MovingMomentsTest, CorrectMomentsOfAnAllZerosBuffer) {
61   const float kInput[] = {0.f, 0.f, 0.f, 0.f, 0.f};
62   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
63 
64   const float expected_mean[kInputLength] = {0.f, 0.f, 0.f, 0.f, 0.f};
65   const float expected_mean_squares[kInputLength] = {0.f, 0.f, 0.f, 0.f, 0.f};
66 
67   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
68                             expected_mean_squares);
69 }
70 
TEST_F(MovingMomentsTest,CorrectMomentsOfAConstantBuffer)71 TEST_F(MovingMomentsTest, CorrectMomentsOfAConstantBuffer) {
72   const float kInput[] = {5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f};
73   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
74 
75   const float expected_mean[kInputLength] =
76       {1.f, 2.f, 3.f, 4.f, 5.f, 5.f, 5.f, 5.f, 5.f, 5.f};
77   const float expected_mean_squares[kInputLength] =
78       {5.f, 10.f, 15.f, 20.f, 25.f, 25.f, 25.f, 25.f, 25.f, 25.f};
79 
80   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
81                             expected_mean_squares);
82 }
83 
TEST_F(MovingMomentsTest,CorrectMomentsOfAnIncreasingBuffer)84 TEST_F(MovingMomentsTest, CorrectMomentsOfAnIncreasingBuffer) {
85   const float kInput[] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f};
86   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
87 
88   const float expected_mean[kInputLength] =
89       {0.2f, 0.6f, 1.2f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f};
90   const float expected_mean_squares[kInputLength] =
91       {0.2f, 1.f, 2.8f, 6.f, 11.f, 18.f, 27.f, 38.f, 51.f};
92 
93   CalculateMomentsAndVerify(kInput, kInputLength, expected_mean,
94                             expected_mean_squares);
95 }
96 
TEST_F(MovingMomentsTest,CorrectMomentsOfADecreasingBuffer)97 TEST_F(MovingMomentsTest, CorrectMomentsOfADecreasingBuffer) {
98   const float kInput[] =
99       {-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] =
103       {-0.2f, -0.6f, -1.2f, -2.f, -3.f, -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[] =
115       {1.f, -1.f, 1.f, -1.f, 1.f, -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] =
119       {0.25f, 0.f, 0.25f, 0.f, 0.f, 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[] =
129       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 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] =
135       {0.008f, 0.026f, 0.076f, 0.174f, 0.1764f, 0.1718f, 0.1596f, 0.1168f,
136       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[] =
144       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 0.13f, 0.17f, 0.19f, 0.23f};
145   const size_t kInputFirstCallLength = sizeof(kInputFirstCall) /
146                                     sizeof(kInputFirstCall[0]);
147   const float kInputSecondCall[] = {0.29f, 0.31f};
148   const size_t kInputSecondCallLength = sizeof(kInputSecondCall) /
149                                      sizeof(kInputSecondCall[0]);
150   const float kInputThirdCall[] = {0.37f, 0.41f, 0.43f, 0.47f};
151   const size_t kInputThirdCallLength = sizeof(kInputThirdCall) /
152                                     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, 0.1718f, 0.1596f, 0.1168f,
158       0.0294f};
159 
160   const float expected_mean_second_call[kInputSecondCallLength] =
161       {0.202f, 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, expected_mean_squares_first_call);
172 
173   CalculateMomentsAndVerify(kInputSecondCall, kInputSecondCallLength,
174       expected_mean_second_call, expected_mean_squares_second_call);
175 
176   CalculateMomentsAndVerify(kInputThirdCall, kInputThirdCallLength,
177       expected_mean_third_call, expected_mean_squares_third_call);
178 }
179 
TEST_F(MovingMomentsTest,VerifySampleBasedVsBlockBasedCalculation)180 TEST_F(MovingMomentsTest,
181        VerifySampleBasedVsBlockBasedCalculation) {
182   const float kInput[] =
183       {0.2f, 0.3f, 0.5f, 0.7f, 0.11f, 0.13f, 0.17f, 0.19f, 0.23f};
184   const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
185 
186   float output_mean_block_based[kInputLength];
187   float output_mean_squares_block_based[kInputLength];
188 
189   float output_mean_sample_based;
190   float output_mean_squares_sample_based;
191 
192   moving_moments_->CalculateMoments(
193       kInput, kInputLength, output_mean_block_based,
194       output_mean_squares_block_based);
195   moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength));
196   for (size_t i = 0; i < kInputLength; ++i) {
197     moving_moments_->CalculateMoments(
198         &kInput[i], 1, &output_mean_sample_based,
199         &output_mean_squares_sample_based);
200     EXPECT_FLOAT_EQ(output_mean_block_based[i], output_mean_sample_based);
201     EXPECT_FLOAT_EQ(output_mean_squares_block_based[i],
202                      output_mean_squares_sample_based);
203   }
204 }
205 
206 }  // namespace webrtc
207