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 |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 template <size_t N> | 25 template <size_t N> |
26 void VerifyOutput(const float (&expected_output)[N], const float (&output)[N]) { | 26 void VerifyOutput(const float (&expected_output)[N], const float (&output)[N]) { |
27 EXPECT_EQ(0, memcmp(expected_output, output, sizeof(output))); | 27 EXPECT_EQ(0, memcmp(expected_output, output, sizeof(output))); |
28 } | 28 } |
29 | 29 |
30 } // namespace | 30 } // namespace |
31 | 31 |
32 TEST(SparseFIRFilterTest, FilterAsIdentity) { | 32 TEST(SparseFIRFilterTest, FilterAsIdentity) { |
33 const float kCoeff = 1.f; | 33 const float kCoeff = 1.f; |
34 const int kNumCoeff = 1; | 34 const size_t kNumCoeff = 1; |
35 const int kSparsity = 3; | 35 const size_t kSparsity = 3; |
36 const int kOffset = 0; | 36 const size_t kOffset = 0; |
37 float output[arraysize(kInput)]; | 37 float output[arraysize(kInput)]; |
38 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); | 38 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); |
39 filter.Filter(kInput, arraysize(kInput), output); | 39 filter.Filter(kInput, arraysize(kInput), output); |
40 VerifyOutput(kInput, output); | 40 VerifyOutput(kInput, output); |
41 } | 41 } |
42 | 42 |
43 TEST(SparseFIRFilterTest, SameOutputForScalarCoefficientAndDifferentSparsity) { | 43 TEST(SparseFIRFilterTest, SameOutputForScalarCoefficientAndDifferentSparsity) { |
44 const float kCoeff = 2.f; | 44 const float kCoeff = 2.f; |
45 const int kNumCoeff = 1; | 45 const size_t kNumCoeff = 1; |
46 const int kLowSparsity = 1; | 46 const size_t kLowSparsity = 1; |
47 const int kHighSparsity = 7; | 47 const size_t kHighSparsity = 7; |
48 const int kOffset = 0; | 48 const size_t kOffset = 0; |
49 float low_sparsity_output[arraysize(kInput)]; | 49 float low_sparsity_output[arraysize(kInput)]; |
50 float high_sparsity_output[arraysize(kInput)]; | 50 float high_sparsity_output[arraysize(kInput)]; |
51 SparseFIRFilter low_sparsity_filter(&kCoeff, | 51 SparseFIRFilter low_sparsity_filter(&kCoeff, |
52 kNumCoeff, | 52 kNumCoeff, |
53 kLowSparsity, | 53 kLowSparsity, |
54 kOffset); | 54 kOffset); |
55 SparseFIRFilter high_sparsity_filter(&kCoeff, | 55 SparseFIRFilter high_sparsity_filter(&kCoeff, |
56 kNumCoeff, | 56 kNumCoeff, |
57 kHighSparsity, | 57 kHighSparsity, |
58 kOffset); | 58 kOffset); |
59 low_sparsity_filter.Filter(kInput, arraysize(kInput), low_sparsity_output); | 59 low_sparsity_filter.Filter(kInput, arraysize(kInput), low_sparsity_output); |
60 high_sparsity_filter.Filter(kInput, arraysize(kInput), high_sparsity_output); | 60 high_sparsity_filter.Filter(kInput, arraysize(kInput), high_sparsity_output); |
61 VerifyOutput(low_sparsity_output, high_sparsity_output); | 61 VerifyOutput(low_sparsity_output, high_sparsity_output); |
62 } | 62 } |
63 | 63 |
64 TEST(SparseFIRFilterTest, FilterUsedAsScalarMultiplication) { | 64 TEST(SparseFIRFilterTest, FilterUsedAsScalarMultiplication) { |
65 const float kCoeff = 5.f; | 65 const float kCoeff = 5.f; |
66 const int kNumCoeff = 1; | 66 const size_t kNumCoeff = 1; |
67 const int kSparsity = 5; | 67 const size_t kSparsity = 5; |
68 const int kOffset = 0; | 68 const size_t kOffset = 0; |
69 float output[arraysize(kInput)]; | 69 float output[arraysize(kInput)]; |
70 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); | 70 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); |
71 filter.Filter(kInput, arraysize(kInput), output); | 71 filter.Filter(kInput, arraysize(kInput), output); |
72 EXPECT_FLOAT_EQ(5.f, output[0]); | 72 EXPECT_FLOAT_EQ(5.f, output[0]); |
73 EXPECT_FLOAT_EQ(20.f, output[3]); | 73 EXPECT_FLOAT_EQ(20.f, output[3]); |
74 EXPECT_FLOAT_EQ(25.f, output[4]); | 74 EXPECT_FLOAT_EQ(25.f, output[4]); |
75 EXPECT_FLOAT_EQ(50.f, output[arraysize(kInput) - 1]); | 75 EXPECT_FLOAT_EQ(50.f, output[arraysize(kInput) - 1]); |
76 } | 76 } |
77 | 77 |
78 TEST(SparseFIRFilterTest, FilterUsedAsInputShifting) { | 78 TEST(SparseFIRFilterTest, FilterUsedAsInputShifting) { |
79 const float kCoeff = 1.f; | 79 const float kCoeff = 1.f; |
80 const int kNumCoeff = 1; | 80 const size_t kNumCoeff = 1; |
81 const int kSparsity = 1; | 81 const size_t kSparsity = 1; |
82 const int kOffset = 4; | 82 const size_t kOffset = 4; |
83 float output[arraysize(kInput)]; | 83 float output[arraysize(kInput)]; |
84 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); | 84 SparseFIRFilter filter(&kCoeff, kNumCoeff, kSparsity, kOffset); |
85 filter.Filter(kInput, arraysize(kInput), output); | 85 filter.Filter(kInput, arraysize(kInput), output); |
86 EXPECT_FLOAT_EQ(0.f, output[0]); | 86 EXPECT_FLOAT_EQ(0.f, output[0]); |
87 EXPECT_FLOAT_EQ(0.f, output[3]); | 87 EXPECT_FLOAT_EQ(0.f, output[3]); |
88 EXPECT_FLOAT_EQ(1.f, output[4]); | 88 EXPECT_FLOAT_EQ(1.f, output[4]); |
89 EXPECT_FLOAT_EQ(2.f, output[5]); | 89 EXPECT_FLOAT_EQ(2.f, output[5]); |
90 EXPECT_FLOAT_EQ(6.f, output[arraysize(kInput) - 1]); | 90 EXPECT_FLOAT_EQ(6.f, output[arraysize(kInput) - 1]); |
91 } | 91 } |
92 | 92 |
93 TEST(SparseFIRFilterTest, FilterUsedAsArbitraryWeighting) { | 93 TEST(SparseFIRFilterTest, FilterUsedAsArbitraryWeighting) { |
94 const int kSparsity = 2; | 94 const size_t kSparsity = 2; |
95 const int kOffset = 1; | 95 const size_t kOffset = 1; |
96 float output[arraysize(kInput)]; | 96 float output[arraysize(kInput)]; |
97 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); | 97 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); |
98 filter.Filter(kInput, arraysize(kInput), output); | 98 filter.Filter(kInput, arraysize(kInput), output); |
99 EXPECT_FLOAT_EQ(0.f, output[0]); | 99 EXPECT_FLOAT_EQ(0.f, output[0]); |
100 EXPECT_FLOAT_EQ(0.9f, output[3]); | 100 EXPECT_FLOAT_EQ(0.9f, output[3]); |
101 EXPECT_FLOAT_EQ(1.4f, output[4]); | 101 EXPECT_FLOAT_EQ(1.4f, output[4]); |
102 EXPECT_FLOAT_EQ(2.4f, output[5]); | 102 EXPECT_FLOAT_EQ(2.4f, output[5]); |
103 EXPECT_FLOAT_EQ(8.61f, output[arraysize(kInput) - 1]); | 103 EXPECT_FLOAT_EQ(8.61f, output[arraysize(kInput) - 1]); |
104 } | 104 } |
105 | 105 |
106 TEST(SparseFIRFilterTest, FilterInLengthLesserOrEqualToCoefficientsLength) { | 106 TEST(SparseFIRFilterTest, FilterInLengthLesserOrEqualToCoefficientsLength) { |
107 const int kSparsity = 1; | 107 const size_t kSparsity = 1; |
108 const int kOffset = 0; | 108 const size_t kOffset = 0; |
109 float output[arraysize(kInput)]; | 109 float output[arraysize(kInput)]; |
110 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); | 110 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); |
111 filter.Filter(kInput, 2, output); | 111 filter.Filter(kInput, 2, output); |
112 EXPECT_FLOAT_EQ(0.2f, output[0]); | 112 EXPECT_FLOAT_EQ(0.2f, output[0]); |
113 EXPECT_FLOAT_EQ(0.7f, output[1]); | 113 EXPECT_FLOAT_EQ(0.7f, output[1]); |
114 } | 114 } |
115 | 115 |
116 TEST(SparseFIRFilterTest, MultipleFilterCalls) { | 116 TEST(SparseFIRFilterTest, MultipleFilterCalls) { |
117 const int kSparsity = 1; | 117 const size_t kSparsity = 1; |
118 const int kOffset = 0; | 118 const size_t kOffset = 0; |
119 float output[arraysize(kInput)]; | 119 float output[arraysize(kInput)]; |
120 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); | 120 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); |
121 filter.Filter(kInput, 2, output); | 121 filter.Filter(kInput, 2, output); |
122 EXPECT_FLOAT_EQ(0.2f, output[0]); | 122 EXPECT_FLOAT_EQ(0.2f, output[0]); |
123 EXPECT_FLOAT_EQ(0.7f, output[1]); | 123 EXPECT_FLOAT_EQ(0.7f, output[1]); |
124 filter.Filter(kInput, 2, output); | 124 filter.Filter(kInput, 2, output); |
125 EXPECT_FLOAT_EQ(1.3f, output[0]); | 125 EXPECT_FLOAT_EQ(1.3f, output[0]); |
126 EXPECT_FLOAT_EQ(2.4f, output[1]); | 126 EXPECT_FLOAT_EQ(2.4f, output[1]); |
127 filter.Filter(kInput, 2, output); | 127 filter.Filter(kInput, 2, output); |
128 EXPECT_FLOAT_EQ(2.81f, output[0]); | 128 EXPECT_FLOAT_EQ(2.81f, output[0]); |
129 EXPECT_FLOAT_EQ(2.62f, output[1]); | 129 EXPECT_FLOAT_EQ(2.62f, output[1]); |
130 filter.Filter(kInput, 2, output); | 130 filter.Filter(kInput, 2, output); |
131 EXPECT_FLOAT_EQ(2.81f, output[0]); | 131 EXPECT_FLOAT_EQ(2.81f, output[0]); |
132 EXPECT_FLOAT_EQ(2.62f, output[1]); | 132 EXPECT_FLOAT_EQ(2.62f, output[1]); |
133 filter.Filter(&kInput[3], 3, output); | 133 filter.Filter(&kInput[3], 3, output); |
134 EXPECT_FLOAT_EQ(3.41f, output[0]); | 134 EXPECT_FLOAT_EQ(3.41f, output[0]); |
135 EXPECT_FLOAT_EQ(4.12f, output[1]); | 135 EXPECT_FLOAT_EQ(4.12f, output[1]); |
136 EXPECT_FLOAT_EQ(6.21f, output[2]); | 136 EXPECT_FLOAT_EQ(6.21f, output[2]); |
137 filter.Filter(&kInput[3], 3, output); | 137 filter.Filter(&kInput[3], 3, output); |
138 EXPECT_FLOAT_EQ(8.12f, output[0]); | 138 EXPECT_FLOAT_EQ(8.12f, output[0]); |
139 EXPECT_FLOAT_EQ(9.14f, output[1]); | 139 EXPECT_FLOAT_EQ(9.14f, output[1]); |
140 EXPECT_FLOAT_EQ(9.45f, output[2]); | 140 EXPECT_FLOAT_EQ(9.45f, output[2]); |
141 } | 141 } |
142 | 142 |
143 TEST(SparseFIRFilterTest, VerifySampleBasedVsBlockBasedFiltering) { | 143 TEST(SparseFIRFilterTest, VerifySampleBasedVsBlockBasedFiltering) { |
144 const int kSparsity = 3; | 144 const size_t kSparsity = 3; |
145 const int kOffset = 1; | 145 const size_t kOffset = 1; |
146 float output_block_based[arraysize(kInput)]; | 146 float output_block_based[arraysize(kInput)]; |
147 SparseFIRFilter filter_block(kCoeffs, | 147 SparseFIRFilter filter_block(kCoeffs, |
148 arraysize(kCoeffs), | 148 arraysize(kCoeffs), |
149 kSparsity, | 149 kSparsity, |
150 kOffset); | 150 kOffset); |
151 filter_block.Filter(kInput, arraysize(kInput), output_block_based); | 151 filter_block.Filter(kInput, arraysize(kInput), output_block_based); |
152 float output_sample_based[arraysize(kInput)]; | 152 float output_sample_based[arraysize(kInput)]; |
153 SparseFIRFilter filter_sample(kCoeffs, | 153 SparseFIRFilter filter_sample(kCoeffs, |
154 arraysize(kCoeffs), | 154 arraysize(kCoeffs), |
155 kSparsity, | 155 kSparsity, |
156 kOffset); | 156 kOffset); |
157 for (size_t i = 0; i < arraysize(kInput); ++i) | 157 for (size_t i = 0; i < arraysize(kInput); ++i) |
158 filter_sample.Filter(&kInput[i], 1, &output_sample_based[i]); | 158 filter_sample.Filter(&kInput[i], 1, &output_sample_based[i]); |
159 VerifyOutput(output_block_based, output_sample_based); | 159 VerifyOutput(output_block_based, output_sample_based); |
160 } | 160 } |
161 | 161 |
162 TEST(SparseFIRFilterTest, SimpleHighPassFilter) { | 162 TEST(SparseFIRFilterTest, SimpleHighPassFilter) { |
163 const int kSparsity = 2; | 163 const size_t kSparsity = 2; |
164 const int kOffset = 2; | 164 const size_t kOffset = 2; |
165 const float kHPCoeffs[] = {1.f, -1.f}; | 165 const float kHPCoeffs[] = {1.f, -1.f}; |
166 const float kConstantInput[] = | 166 const float kConstantInput[] = |
167 {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; | 167 {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; |
168 float output[arraysize(kConstantInput)]; | 168 float output[arraysize(kConstantInput)]; |
169 SparseFIRFilter filter(kHPCoeffs, arraysize(kHPCoeffs), kSparsity, kOffset); | 169 SparseFIRFilter filter(kHPCoeffs, arraysize(kHPCoeffs), kSparsity, kOffset); |
170 filter.Filter(kConstantInput, arraysize(kConstantInput), output); | 170 filter.Filter(kConstantInput, arraysize(kConstantInput), output); |
171 EXPECT_FLOAT_EQ(0.f, output[0]); | 171 EXPECT_FLOAT_EQ(0.f, output[0]); |
172 EXPECT_FLOAT_EQ(0.f, output[1]); | 172 EXPECT_FLOAT_EQ(0.f, output[1]); |
173 EXPECT_FLOAT_EQ(1.f, output[2]); | 173 EXPECT_FLOAT_EQ(1.f, output[2]); |
174 EXPECT_FLOAT_EQ(1.f, output[3]); | 174 EXPECT_FLOAT_EQ(1.f, output[3]); |
175 for (size_t i = kSparsity + kOffset; i < arraysize(kConstantInput); ++i) | 175 for (size_t i = kSparsity + kOffset; i < arraysize(kConstantInput); ++i) |
176 EXPECT_FLOAT_EQ(0.f, output[i]); | 176 EXPECT_FLOAT_EQ(0.f, output[i]); |
177 } | 177 } |
178 | 178 |
179 TEST(SparseFIRFilterTest, SimpleLowPassFilter) { | 179 TEST(SparseFIRFilterTest, SimpleLowPassFilter) { |
180 const int kSparsity = 2; | 180 const size_t kSparsity = 2; |
181 const int kOffset = 2; | 181 const size_t kOffset = 2; |
182 const float kLPCoeffs[] = {1.f, 1.f}; | 182 const float kLPCoeffs[] = {1.f, 1.f}; |
183 const float kHighFrequencyInput[] = | 183 const float kHighFrequencyInput[] = |
184 {1.f, 1.f, -1.f, -1.f, 1.f, 1.f, -1.f, -1.f, 1.f, 1.f}; | 184 {1.f, 1.f, -1.f, -1.f, 1.f, 1.f, -1.f, -1.f, 1.f, 1.f}; |
185 float output[arraysize(kHighFrequencyInput)]; | 185 float output[arraysize(kHighFrequencyInput)]; |
186 SparseFIRFilter filter(kLPCoeffs, arraysize(kLPCoeffs), kSparsity, kOffset); | 186 SparseFIRFilter filter(kLPCoeffs, arraysize(kLPCoeffs), kSparsity, kOffset); |
187 filter.Filter(kHighFrequencyInput, arraysize(kHighFrequencyInput), output); | 187 filter.Filter(kHighFrequencyInput, arraysize(kHighFrequencyInput), output); |
188 EXPECT_FLOAT_EQ(0.f, output[0]); | 188 EXPECT_FLOAT_EQ(0.f, output[0]); |
189 EXPECT_FLOAT_EQ(0.f, output[1]); | 189 EXPECT_FLOAT_EQ(0.f, output[1]); |
190 EXPECT_FLOAT_EQ(1.f, output[2]); | 190 EXPECT_FLOAT_EQ(1.f, output[2]); |
191 EXPECT_FLOAT_EQ(1.f, output[3]); | 191 EXPECT_FLOAT_EQ(1.f, output[3]); |
192 for (size_t i = kSparsity + kOffset; i < arraysize(kHighFrequencyInput); ++i) | 192 for (size_t i = kSparsity + kOffset; i < arraysize(kHighFrequencyInput); ++i) |
193 EXPECT_FLOAT_EQ(0.f, output[i]); | 193 EXPECT_FLOAT_EQ(0.f, output[i]); |
194 } | 194 } |
195 | 195 |
196 TEST(SparseFIRFilterTest, SameOutputWhenSwappedCoefficientsAndInput) { | 196 TEST(SparseFIRFilterTest, SameOutputWhenSwappedCoefficientsAndInput) { |
197 const int kSparsity = 1; | 197 const size_t kSparsity = 1; |
198 const int kOffset = 0; | 198 const size_t kOffset = 0; |
199 float output[arraysize(kCoeffs)]; | 199 float output[arraysize(kCoeffs)]; |
200 float output_swapped[arraysize(kCoeffs)]; | 200 float output_swapped[arraysize(kCoeffs)]; |
201 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); | 201 SparseFIRFilter filter(kCoeffs, arraysize(kCoeffs), kSparsity, kOffset); |
202 // Use arraysize(kCoeffs) for in_length to get same-length outputs. | 202 // Use arraysize(kCoeffs) for in_length to get same-length outputs. |
203 filter.Filter(kInput, arraysize(kCoeffs), output); | 203 filter.Filter(kInput, arraysize(kCoeffs), output); |
204 SparseFIRFilter filter_swapped(kInput, | 204 SparseFIRFilter filter_swapped(kInput, |
205 arraysize(kCoeffs), | 205 arraysize(kCoeffs), |
206 kSparsity, | 206 kSparsity, |
207 kOffset); | 207 kOffset); |
208 filter_swapped.Filter(kCoeffs, arraysize(kCoeffs), output_swapped); | 208 filter_swapped.Filter(kCoeffs, arraysize(kCoeffs), output_swapped); |
209 VerifyOutput(output, output_swapped); | 209 VerifyOutput(output, output_swapped); |
210 } | 210 } |
211 | 211 |
212 TEST(SparseFIRFilterTest, SameOutputAsFIRFilterWhenSparsityOneAndOffsetZero) { | 212 TEST(SparseFIRFilterTest, SameOutputAsFIRFilterWhenSparsityOneAndOffsetZero) { |
213 const int kSparsity = 1; | 213 const size_t kSparsity = 1; |
214 const int kOffset = 0; | 214 const size_t kOffset = 0; |
215 float output[arraysize(kInput)]; | 215 float output[arraysize(kInput)]; |
216 float sparse_output[arraysize(kInput)]; | 216 float sparse_output[arraysize(kInput)]; |
217 rtc::scoped_ptr<FIRFilter> filter(FIRFilter::Create(kCoeffs, | 217 rtc::scoped_ptr<FIRFilter> filter(FIRFilter::Create(kCoeffs, |
218 arraysize(kCoeffs), | 218 arraysize(kCoeffs), |
219 arraysize(kInput))); | 219 arraysize(kInput))); |
220 SparseFIRFilter sparse_filter(kCoeffs, | 220 SparseFIRFilter sparse_filter(kCoeffs, |
221 arraysize(kCoeffs), | 221 arraysize(kCoeffs), |
222 kSparsity, | 222 kSparsity, |
223 kOffset); | 223 kOffset); |
224 filter->Filter(kInput, arraysize(kInput), output); | 224 filter->Filter(kInput, arraysize(kInput), output); |
225 sparse_filter.Filter(kInput, arraysize(kInput), sparse_output); | 225 sparse_filter.Filter(kInput, arraysize(kInput), sparse_output); |
226 for (size_t i = 0; i < arraysize(kInput); ++i) { | 226 for (size_t i = 0; i < arraysize(kInput); ++i) { |
227 EXPECT_FLOAT_EQ(output[i], sparse_output[i]); | 227 EXPECT_FLOAT_EQ(output[i], sparse_output[i]); |
228 } | 228 } |
229 } | 229 } |
230 | 230 |
231 } // namespace webrtc | 231 } // namespace webrtc |
OLD | NEW |