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 16namespace webrtc { 17 18static const float kTolerance = 0.0001f; 19 20class 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 37const size_t MovingMomentsTest::kMaxOutputLength; 38 39void MovingMomentsTest::SetUp() { 40 moving_moments_.reset(new MovingMoments(kMovingMomentsBufferLength)); 41} 42 43void 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 60TEST_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 71TEST_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 84TEST_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 97TEST_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 111TEST_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 127TEST_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 142TEST_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 180TEST_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