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 |