| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 // | 11 #include <cmath> |
| 12 // Unit tests for intelligibility utils. | |
| 13 // | |
| 14 | |
| 15 #include <math.h> | |
| 16 #include <complex> | 12 #include <complex> |
| 17 #include <iostream> | |
| 18 #include <vector> | 13 #include <vector> |
| 19 | 14 |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 21 #include "webrtc/base/arraysize.h" | 16 #include "webrtc/base/arraysize.h" |
| 22 #include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.
h" | 17 #include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.
h" |
| 23 | 18 |
| 24 using std::complex; | |
| 25 using std::vector; | |
| 26 | |
| 27 namespace webrtc { | 19 namespace webrtc { |
| 28 | 20 |
| 29 namespace intelligibility { | 21 namespace intelligibility { |
| 30 | 22 |
| 31 vector<vector<complex<float>>> GenerateTestData(int freqs, int samples) { | 23 std::vector<std::vector<std::complex<float>>> GenerateTestData(size_t freqs, |
| 32 vector<vector<complex<float>>> data(samples); | 24 size_t samples) { |
| 33 for (int i = 0; i < samples; i++) { | 25 std::vector<std::vector<std::complex<float>>> data(samples); |
| 34 for (int j = 0; j < freqs; j++) { | 26 for (size_t i = 0; i < samples; ++i) { |
| 27 for (size_t j = 0; j < freqs; ++j) { |
| 35 const float val = 0.99f / ((i + 1) * (j + 1)); | 28 const float val = 0.99f / ((i + 1) * (j + 1)); |
| 36 data[i].push_back(complex<float>(val, val)); | 29 data[i].push_back(std::complex<float>(val, val)); |
| 37 } | 30 } |
| 38 } | 31 } |
| 39 return data; | 32 return data; |
| 40 } | 33 } |
| 41 | 34 |
| 42 // Tests UpdateFactor. | 35 // Tests PowerEstimator, for all power step types. |
| 43 TEST(IntelligibilityUtilsTest, TestUpdateFactor) { | 36 TEST(IntelligibilityUtilsTest, TestPowerEstimator) { |
| 44 EXPECT_EQ(0, intelligibility::UpdateFactor(0, 0, 0)); | 37 const size_t kFreqs = 10; |
| 45 EXPECT_EQ(4, intelligibility::UpdateFactor(4, 2, 3)); | 38 const size_t kSamples = 100; |
| 46 EXPECT_EQ(3, intelligibility::UpdateFactor(4, 2, 1)); | 39 const float kDecay = 0.5f; |
| 47 EXPECT_EQ(2, intelligibility::UpdateFactor(2, 4, 3)); | 40 const std::vector<std::vector<std::complex<float>>> test_data( |
| 48 EXPECT_EQ(3, intelligibility::UpdateFactor(2, 4, 1)); | 41 GenerateTestData(kFreqs, kSamples)); |
| 49 } | 42 PowerEstimator power_estimator(kFreqs, kDecay); |
| 43 EXPECT_EQ(0, power_estimator.power()[0]); |
| 50 | 44 |
| 51 // Tests zerofudge. | 45 // Makes sure Step is doing something. |
| 52 TEST(IntelligibilityUtilsTest, TestCplx) { | 46 power_estimator.Step(&test_data[0][0]); |
| 53 complex<float> t0(1.f, 0.f); | 47 for (size_t i = 1; i < kSamples; ++i) { |
| 54 t0 = intelligibility::zerofudge(t0); | 48 power_estimator.Step(&test_data[i][0]); |
| 55 EXPECT_NE(t0.imag(), 0.f); | 49 for (size_t j = 0; j < kFreqs; ++j) { |
| 56 EXPECT_NE(t0.real(), 0.f); | 50 EXPECT_GE(power_estimator.power()[j], 0.f); |
| 57 } | 51 EXPECT_LE(power_estimator.power()[j], 1.f); |
| 58 | |
| 59 // Tests NewMean and AddToMean. | |
| 60 TEST(IntelligibilityUtilsTest, TestMeanUpdate) { | |
| 61 const complex<float> data[] = {{3, 8}, {7, 6}, {2, 1}, {8, 9}, {0, 6}}; | |
| 62 const complex<float> means[] = {{3, 8}, {5, 7}, {4, 5}, {5, 6}, {4, 6}}; | |
| 63 complex<float> mean(3, 8); | |
| 64 for (size_t i = 0; i < arraysize(data); i++) { | |
| 65 EXPECT_EQ(means[i], NewMean(mean, data[i], i + 1)); | |
| 66 AddToMean(data[i], i + 1, &mean); | |
| 67 EXPECT_EQ(means[i], mean); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 // Tests VarianceArray, for all variance step types. | |
| 72 TEST(IntelligibilityUtilsTest, TestVarianceArray) { | |
| 73 const int kFreqs = 10; | |
| 74 const int kSamples = 100; | |
| 75 const int kWindowSize = 10; // Should pass for all kWindowSize > 1. | |
| 76 const float kDecay = 0.5f; | |
| 77 vector<VarianceArray::StepType> step_types; | |
| 78 step_types.push_back(VarianceArray::kStepInfinite); | |
| 79 step_types.push_back(VarianceArray::kStepDecaying); | |
| 80 step_types.push_back(VarianceArray::kStepWindowed); | |
| 81 step_types.push_back(VarianceArray::kStepBlocked); | |
| 82 step_types.push_back(VarianceArray::kStepBlockBasedMovingAverage); | |
| 83 const vector<vector<complex<float>>> test_data( | |
| 84 GenerateTestData(kFreqs, kSamples)); | |
| 85 for (auto step_type : step_types) { | |
| 86 VarianceArray variance_array(kFreqs, step_type, kWindowSize, kDecay); | |
| 87 EXPECT_EQ(0, variance_array.variance()[0]); | |
| 88 EXPECT_EQ(0, variance_array.array_mean()); | |
| 89 variance_array.ApplyScale(2.0f); | |
| 90 EXPECT_EQ(0, variance_array.variance()[0]); | |
| 91 EXPECT_EQ(0, variance_array.array_mean()); | |
| 92 | |
| 93 // Makes sure Step is doing something. | |
| 94 variance_array.Step(&test_data[0][0]); | |
| 95 for (int i = 1; i < kSamples; i++) { | |
| 96 variance_array.Step(&test_data[i][0]); | |
| 97 EXPECT_GE(variance_array.array_mean(), 0.0f); | |
| 98 EXPECT_LE(variance_array.array_mean(), 1.0f); | |
| 99 for (int j = 0; j < kFreqs; j++) { | |
| 100 EXPECT_GE(variance_array.variance()[j], 0.0f); | |
| 101 EXPECT_LE(variance_array.variance()[j], 1.0f); | |
| 102 } | |
| 103 } | |
| 104 variance_array.Clear(); | |
| 105 EXPECT_EQ(0, variance_array.variance()[0]); | |
| 106 EXPECT_EQ(0, variance_array.array_mean()); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 // Tests exact computation on synthetic data. | |
| 111 TEST(IntelligibilityUtilsTest, TestMovingBlockAverage) { | |
| 112 // Exact, not unbiased estimates. | |
| 113 const float kTestVarianceBufferNotFull = 16.5f; | |
| 114 const float kTestVarianceBufferFull1 = 66.5f; | |
| 115 const float kTestVarianceBufferFull2 = 333.375f; | |
| 116 const int kFreqs = 2; | |
| 117 const int kSamples = 50; | |
| 118 const int kWindowSize = 2; | |
| 119 const float kDecay = 0.5f; | |
| 120 const float kMaxError = 0.0001f; | |
| 121 | |
| 122 VarianceArray variance_array( | |
| 123 kFreqs, VarianceArray::kStepBlockBasedMovingAverage, kWindowSize, kDecay); | |
| 124 | |
| 125 vector<vector<complex<float>>> test_data(kSamples); | |
| 126 for (int i = 0; i < kSamples; i++) { | |
| 127 for (int j = 0; j < kFreqs; j++) { | |
| 128 if (i < 30) { | |
| 129 test_data[i].push_back(complex<float>(static_cast<float>(kSamples - i), | |
| 130 static_cast<float>(i + 1))); | |
| 131 } else { | |
| 132 test_data[i].push_back(complex<float>(0.f, 0.f)); | |
| 133 } | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 for (int i = 0; i < kSamples; i++) { | |
| 138 variance_array.Step(&test_data[i][0]); | |
| 139 for (int j = 0; j < kFreqs; j++) { | |
| 140 if (i < 9) { // In utils, kWindowBlockSize = 10. | |
| 141 EXPECT_EQ(0, variance_array.variance()[j]); | |
| 142 } else if (i < 19) { | |
| 143 EXPECT_NEAR(kTestVarianceBufferNotFull, variance_array.variance()[j], | |
| 144 kMaxError); | |
| 145 } else if (i < 39) { | |
| 146 EXPECT_NEAR(kTestVarianceBufferFull1, variance_array.variance()[j], | |
| 147 kMaxError); | |
| 148 } else if (i < 49) { | |
| 149 EXPECT_NEAR(kTestVarianceBufferFull2, variance_array.variance()[j], | |
| 150 kMaxError); | |
| 151 } else { | |
| 152 EXPECT_EQ(0, variance_array.variance()[j]); | |
| 153 } | |
| 154 } | 52 } |
| 155 } | 53 } |
| 156 } | 54 } |
| 157 | 55 |
| 158 // Tests gain applier. | 56 // Tests gain applier. |
| 159 TEST(IntelligibilityUtilsTest, TestGainApplier) { | 57 TEST(IntelligibilityUtilsTest, TestGainApplier) { |
| 160 const int kFreqs = 10; | 58 const size_t kFreqs = 10; |
| 161 const int kSamples = 100; | 59 const size_t kSamples = 100; |
| 162 const float kChangeLimit = 0.1f; | 60 const float kChangeLimit = 0.1f; |
| 163 GainApplier gain_applier(kFreqs, kChangeLimit); | 61 GainApplier gain_applier(kFreqs, kChangeLimit); |
| 164 const vector<vector<complex<float>>> in_data( | 62 const std::vector<std::vector<std::complex<float>>> in_data( |
| 165 GenerateTestData(kFreqs, kSamples)); | 63 GenerateTestData(kFreqs, kSamples)); |
| 166 vector<vector<complex<float>>> out_data(GenerateTestData(kFreqs, kSamples)); | 64 std::vector<std::vector<std::complex<float>>> out_data( |
| 167 for (int i = 0; i < kSamples; i++) { | 65 GenerateTestData(kFreqs, kSamples)); |
| 66 for (size_t i = 0; i < kSamples; ++i) { |
| 168 gain_applier.Apply(&in_data[i][0], &out_data[i][0]); | 67 gain_applier.Apply(&in_data[i][0], &out_data[i][0]); |
| 169 for (int j = 0; j < kFreqs; j++) { | 68 for (size_t j = 0; j < kFreqs; ++j) { |
| 170 EXPECT_GT(out_data[i][j].real(), 0.0f); | 69 EXPECT_GT(out_data[i][j].real(), 0.f); |
| 171 EXPECT_LT(out_data[i][j].real(), 1.0f); | 70 EXPECT_LT(out_data[i][j].real(), 1.f); |
| 172 EXPECT_GT(out_data[i][j].imag(), 0.0f); | 71 EXPECT_GT(out_data[i][j].imag(), 0.f); |
| 173 EXPECT_LT(out_data[i][j].imag(), 1.0f); | 72 EXPECT_LT(out_data[i][j].imag(), 1.f); |
| 174 } | 73 } |
| 175 } | 74 } |
| 176 } | 75 } |
| 177 | 76 |
| 178 } // namespace intelligibility | 77 } // namespace intelligibility |
| 179 | 78 |
| 180 } // namespace webrtc | 79 } // namespace webrtc |
| OLD | NEW |