1 // Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <gtest/gtest.h>
6 #include <math.h>
7 #include "crossover.h"
8 #include "crossover2.h"
9 #include "drc.h"
10 #include "dsp_util.h"
11 #include "eq.h"
12 #include "eq2.h"
13
14 namespace {
15
16 /* Adds amplitude * sin(pi*freq*i + offset) to the data array. */
add_sine(float * data,size_t len,float freq,float offset,float amplitude)17 static void add_sine(float *data, size_t len, float freq, float offset,
18 float amplitude)
19 {
20 for (size_t i = 0; i < len; i++)
21 data[i] += amplitude * sinf((float)M_PI*freq*i + offset);
22 }
23
24 /* Calculates the magnitude at normalized frequency f. The output is
25 * the result of DFT, multiplied by 2/len. */
magnitude_at(float * data,size_t len,float f)26 static float magnitude_at(float *data, size_t len, float f)
27 {
28 double re = 0, im = 0;
29 f *= (float)M_PI;
30 for (size_t i = 0; i < len; i++) {
31 re += data[i] * cos(i * f);
32 im += data[i] * sin(i * f);
33 }
34 return sqrt(re * re + im * im) * (2.0 / len);
35 }
36
TEST(InterleaveTest,All)37 TEST(InterleaveTest, All) {
38 const int FRAMES = 12;
39 const int SAMPLES = FRAMES * 2;
40
41 /* Repeat the same data twice, so it will exercise neon/sse
42 * optimized functions. */
43 int16_t input[SAMPLES] = {
44 -32768, -32767, -32766, -2, -1, 0, 1, 2, 3, 32765, 32766, 32767,
45 -32768, -32767, -32766, -2, -1, 0, 1, 2, 3, 32765, 32766, 32767
46 };
47
48 float answer[SAMPLES] = {
49 -1, -32766/32768.0f, -1/32768.0f, 1/32768.0f, 3/32768.0f, 32766/32768.0f,
50 -1, -32766/32768.0f, -1/32768.0f, 1/32768.0f, 3/32768.0f, 32766/32768.0f,
51 -32767/32768.0f, -2/32768.0f, 0, 2/32768.0f, 32765/32768.0f, 32767/32768.0f,
52 -32767/32768.0f, -2/32768.0f, 0, 2/32768.0f, 32765/32768.0f, 32767/32768.0f
53 };
54
55 float output[SAMPLES];
56 float *out_ptr[] = {output, output + FRAMES};
57
58 dsp_util_deinterleave((uint8_t *)input, out_ptr, 2,
59 SND_PCM_FORMAT_S16_LE, FRAMES);
60
61 for (int i = 0 ; i < SAMPLES; i++) {
62 EXPECT_EQ(answer[i], output[i]);
63 }
64
65 /* dsp_util_interleave() should round to nearest number. */
66 for (int i = 0 ; i < SAMPLES; i += 2) {
67 output[i] += 0.499 / 32768.0f;
68 output[i + 1] -= 0.499 / 32768.0f;
69 }
70
71 int16_t output2[SAMPLES];
72 dsp_util_interleave(out_ptr, (uint8_t *)output2, 2,
73 SND_PCM_FORMAT_S16_LE, FRAMES);
74 for (int i = 0 ; i < SAMPLES; i++) {
75 EXPECT_EQ(input[i], output2[i]);
76 }
77 }
78
TEST(EqTest,All)79 TEST(EqTest, All) {
80 struct eq *eq;
81 size_t len = 44100;
82 float NQ = len / 2;
83 float f_low = 10 / NQ;
84 float f_mid = 100 / NQ;
85 float f_high = 1000 / NQ;
86 float *data = (float *)malloc(sizeof(float) * len);
87
88 dsp_enable_flush_denormal_to_zero();
89 /* low pass */
90 memset(data, 0, sizeof(float) * len);
91 add_sine(data, len, f_low, 0, 1); // 10Hz sine, magnitude = 1
92 EXPECT_FLOAT_EQ(1, magnitude_at(data, len, f_low));
93 add_sine(data, len, f_high, 0, 1); // 1000Hz sine, magnitude = 1
94 EXPECT_FLOAT_EQ(1, magnitude_at(data, len, f_low));
95 EXPECT_FLOAT_EQ(1, magnitude_at(data, len, f_high));
96
97 eq = eq_new();
98 EXPECT_EQ(0, eq_append_biquad(eq, BQ_LOWPASS, f_mid, 0, 0));
99 eq_process(eq, data, len);
100 EXPECT_NEAR(1, magnitude_at(data, len, f_low), 0.01);
101 EXPECT_NEAR(0, magnitude_at(data, len, f_high), 0.01);
102
103 /* Test for empty input */
104 eq_process(eq, NULL, 0);
105
106 eq_free(eq);
107
108 /* high pass */
109 memset(data, 0, sizeof(float) * len);
110 add_sine(data, len, f_low, 0, 1);
111 add_sine(data, len, f_high, 0, 1);
112
113 eq = eq_new();
114 EXPECT_EQ(0, eq_append_biquad(eq, BQ_HIGHPASS, f_mid, 0, 0));
115 eq_process(eq, data, len);
116 EXPECT_NEAR(0, magnitude_at(data, len, f_low), 0.01);
117 EXPECT_NEAR(1, magnitude_at(data, len, f_high), 0.01);
118 eq_free(eq);
119
120 /* peaking */
121 memset(data, 0, sizeof(float) * len);
122 add_sine(data, len, f_low, 0, 1);
123 add_sine(data, len, f_high, 0, 1);
124
125 eq = eq_new();
126 EXPECT_EQ(0, eq_append_biquad(eq, BQ_PEAKING, f_high, 5, 6)); // Q=5, 6dB gain
127 eq_process(eq, data, len);
128 EXPECT_NEAR(1, magnitude_at(data, len, f_low), 0.01);
129 EXPECT_NEAR(2, magnitude_at(data, len, f_high), 0.01);
130 eq_free(eq);
131
132 free(data);
133
134 /* Too many biquads */
135 eq = eq_new();
136 for (int i = 0; i < MAX_BIQUADS_PER_EQ; i++) {
137 EXPECT_EQ(0, eq_append_biquad(eq, BQ_PEAKING, f_high, 5, 6));
138 }
139 EXPECT_EQ(-1, eq_append_biquad(eq, BQ_PEAKING, f_high, 5, 6));
140 eq_free(eq);
141 }
142
TEST(Eq2Test,All)143 TEST(Eq2Test, All) {
144 struct eq2 *eq2;
145 size_t len = 44100;
146 float NQ = len / 2;
147 float f_low = 10 / NQ;
148 float f_mid = 100 / NQ;
149 float f_high = 1000 / NQ;
150 float *data0 = (float *)malloc(sizeof(float) * len);
151 float *data1 = (float *)malloc(sizeof(float) * len);
152
153 dsp_enable_flush_denormal_to_zero();
154
155 /* a mixture of 10Hz an 1000Hz sine */
156 memset(data0, 0, sizeof(float) * len);
157 memset(data1, 0, sizeof(float) * len);
158 add_sine(data0, len, f_low, 0, 1); // 10Hz sine, magnitude = 1
159 add_sine(data0, len, f_high, 0, 1); // 1000Hz sine, magnitude = 1
160 add_sine(data1, len, f_low, 0, 1); // 10Hz sine, magnitude = 1
161 add_sine(data1, len, f_high, 0, 1); // 1000Hz sine, magnitude = 1
162
163 /* low pass at left and high pass at right */
164 eq2 = eq2_new();
165 EXPECT_EQ(0, eq2_append_biquad(eq2, 0, BQ_LOWPASS, f_mid, 0, 0));
166 EXPECT_EQ(0, eq2_append_biquad(eq2, 1, BQ_HIGHPASS, f_mid, 0, 0));
167 eq2_process(eq2, data0, data1, len);
168 EXPECT_NEAR(1, magnitude_at(data0, len, f_low), 0.01);
169 EXPECT_NEAR(0, magnitude_at(data0, len, f_high), 0.01);
170 EXPECT_NEAR(0, magnitude_at(data1, len, f_low), 0.01);
171 EXPECT_NEAR(1, magnitude_at(data1, len, f_high), 0.01);
172
173 /* Test for empty input */
174 eq2_process(eq2, NULL, NULL, 0);
175 eq2_free(eq2);
176
177 /* a mixture of 10Hz and 1000Hz sine */
178 memset(data0, 0, sizeof(float) * len);
179 memset(data1, 0, sizeof(float) * len);
180 add_sine(data0, len, f_low, 0, 1);
181 add_sine(data0, len, f_high, 0, 1);
182 add_sine(data1, len, f_low, 0, 1);
183 add_sine(data1, len, f_high, 0, 1);
184
185 /* one high-shelving biquad at left and two low-shelving biquads at right */
186 eq2 = eq2_new();
187 EXPECT_EQ(0, eq2_append_biquad(eq2, 0, BQ_HIGHSHELF, f_mid, 5, 6));
188 EXPECT_EQ(0, eq2_append_biquad(eq2, 1, BQ_LOWSHELF, f_mid, 0, -6));
189 EXPECT_EQ(0, eq2_append_biquad(eq2, 1, BQ_LOWSHELF, f_mid, 0, -6));
190
191 eq2_process(eq2, data0, data1, len);
192 EXPECT_NEAR(1, magnitude_at(data0, len, f_low), 0.01);
193 EXPECT_NEAR(2, magnitude_at(data0, len, f_high), 0.01);
194 EXPECT_NEAR(0.25, magnitude_at(data1, len, f_low), 0.01);
195 EXPECT_NEAR(1, magnitude_at(data1, len, f_high), 0.01);
196 eq2_free(eq2);
197
198 free(data0);
199 free(data1);
200
201 /* Too many biquads */
202 eq2 = eq2_new();
203 for (int i = 0; i < MAX_BIQUADS_PER_EQ2; i++) {
204 EXPECT_EQ(0, eq2_append_biquad(eq2, 0, BQ_PEAKING, f_high, 5, 6));
205 EXPECT_EQ(0, eq2_append_biquad(eq2, 1, BQ_PEAKING, f_high, 5, 6));
206 }
207 EXPECT_EQ(-1, eq2_append_biquad(eq2, 0, BQ_PEAKING, f_high, 5, 6));
208 EXPECT_EQ(-1, eq2_append_biquad(eq2, 1, BQ_PEAKING, f_high, 5, 6));
209 eq2_free(eq2);
210 }
211
TEST(CrossoverTest,All)212 TEST(CrossoverTest, All) {
213 struct crossover xo;
214 size_t len = 44100;
215 float NQ = len / 2;
216 float f0 = 62.5 / NQ;
217 float f1 = 250 / NQ;
218 float f2 = 1000 / NQ;
219 float f3 = 4000 / NQ;
220 float f4 = 16000 / NQ;
221 float *data = (float *)malloc(sizeof(float) * len);
222 float *data1 = (float *)malloc(sizeof(float) * len);
223 float *data2 = (float *)malloc(sizeof(float) * len);
224
225 dsp_enable_flush_denormal_to_zero();
226 crossover_init(&xo, f1, f3);
227 memset(data, 0, sizeof(float) * len);
228 add_sine(data, len, f0, 0, 1);
229 add_sine(data, len, f2, 0, 1);
230 add_sine(data, len, f4, 0, 1);
231
232 crossover_process(&xo, len, data, data1, data2);
233
234 // low band
235 EXPECT_NEAR(1, magnitude_at(data, len, f0), 0.01);
236 EXPECT_NEAR(0, magnitude_at(data, len, f2), 0.01);
237 EXPECT_NEAR(0, magnitude_at(data, len, f4), 0.01);
238
239 // mid band
240 EXPECT_NEAR(0, magnitude_at(data1, len, f0), 0.01);
241 EXPECT_NEAR(1, magnitude_at(data1, len, f2), 0.01);
242 EXPECT_NEAR(0, magnitude_at(data1, len, f4), 0.01);
243
244 // high band
245 EXPECT_NEAR(0, magnitude_at(data2, len, f0), 0.01);
246 EXPECT_NEAR(0, magnitude_at(data2, len, f2), 0.01);
247 EXPECT_NEAR(1, magnitude_at(data2, len, f4), 0.01);
248
249 /* Test for empty input */
250 crossover_process(&xo, 0, NULL, NULL, NULL);
251
252 free(data);
253 free(data1);
254 free(data2);
255 }
256
TEST(Crossover2Test,All)257 TEST(Crossover2Test, All) {
258 struct crossover2 xo2;
259 size_t len = 44100;
260 float NQ = len / 2;
261 float f0 = 62.5 / NQ;
262 float f1 = 250 / NQ;
263 float f2 = 1000 / NQ;
264 float f3 = 4000 / NQ;
265 float f4 = 16000 / NQ;
266 float *data0L = (float *)malloc(sizeof(float) * len);
267 float *data1L = (float *)malloc(sizeof(float) * len);
268 float *data2L = (float *)malloc(sizeof(float) * len);
269 float *data0R = (float *)malloc(sizeof(float) * len);
270 float *data1R = (float *)malloc(sizeof(float) * len);
271 float *data2R = (float *)malloc(sizeof(float) * len);
272
273 dsp_enable_flush_denormal_to_zero();
274 crossover2_init(&xo2, f1, f3);
275 memset(data0L, 0, sizeof(float) * len);
276 memset(data0R, 0, sizeof(float) * len);
277
278 add_sine(data0L, len, f0, 0, 1);
279 add_sine(data0L, len, f2, 0, 1);
280 add_sine(data0L, len, f4, 0, 1);
281
282 add_sine(data0R, len, f0, 0, 0.5);
283 add_sine(data0R, len, f2, 0, 0.5);
284 add_sine(data0R, len, f4, 0, 0.5);
285
286 crossover2_process(&xo2, len, data0L, data0R, data1L, data1R, data2L, data2R);
287
288 // left low band
289 EXPECT_NEAR(1, magnitude_at(data0L, len, f0), 0.01);
290 EXPECT_NEAR(0, magnitude_at(data0L, len, f2), 0.01);
291 EXPECT_NEAR(0, magnitude_at(data0L, len, f4), 0.01);
292
293 // left mid band
294 EXPECT_NEAR(0, magnitude_at(data1L, len, f0), 0.01);
295 EXPECT_NEAR(1, magnitude_at(data1L, len, f2), 0.01);
296 EXPECT_NEAR(0, magnitude_at(data1L, len, f4), 0.01);
297
298 // left high band
299 EXPECT_NEAR(0, magnitude_at(data2L, len, f0), 0.01);
300 EXPECT_NEAR(0, magnitude_at(data2L, len, f2), 0.01);
301 EXPECT_NEAR(1, magnitude_at(data2L, len, f4), 0.01);
302
303 // right low band
304 EXPECT_NEAR(0.5, magnitude_at(data0R, len, f0), 0.005);
305 EXPECT_NEAR(0, magnitude_at(data0R, len, f2), 0.005);
306 EXPECT_NEAR(0, magnitude_at(data0R, len, f4), 0.005);
307
308 // right mid band
309 EXPECT_NEAR(0, magnitude_at(data1R, len, f0), 0.005);
310 EXPECT_NEAR(0.5, magnitude_at(data1R, len, f2), 0.005);
311 EXPECT_NEAR(0, magnitude_at(data1R, len, f4), 0.005);
312
313 // right high band
314 EXPECT_NEAR(0, magnitude_at(data2R, len, f0), 0.005);
315 EXPECT_NEAR(0, magnitude_at(data2R, len, f2), 0.005);
316 EXPECT_NEAR(0.5, magnitude_at(data2R, len, f4), 0.005);
317
318 /* Test for empty input */
319 crossover2_process(&xo2, 0, NULL, NULL, NULL, NULL, NULL, NULL);
320
321 free(data0L);
322 free(data1L);
323 free(data2L);
324 free(data0R);
325 free(data1R);
326 free(data2R);
327 }
328
TEST(DrcTest,All)329 TEST(DrcTest, All) {
330 size_t len = 44100;
331 float NQ = len / 2;
332 float f0 = 62.5 / NQ;
333 float f1 = 250 / NQ;
334 float f2 = 1000 / NQ;
335 float f3 = 4000 / NQ;
336 float f4 = 16000 / NQ;
337 float *data_left = (float *)malloc(sizeof(float) * len);
338 float *data_right = (float *)malloc(sizeof(float) * len);
339 float *data[] = {data_left, data_right};
340 float *data_empty[] = {NULL, NULL};
341 struct drc *drc;
342
343 dsp_enable_flush_denormal_to_zero();
344 drc = drc_new(44100);
345
346 drc_set_param(drc, 0, PARAM_CROSSOVER_LOWER_FREQ, 0);
347 drc_set_param(drc, 0, PARAM_ENABLED, 1);
348 drc_set_param(drc, 0, PARAM_THRESHOLD, -30);
349 drc_set_param(drc, 0, PARAM_KNEE, 0);
350 drc_set_param(drc, 0, PARAM_RATIO, 3);
351 drc_set_param(drc, 0, PARAM_ATTACK, 0.02);
352 drc_set_param(drc, 0, PARAM_RELEASE, 0.2);
353 drc_set_param(drc, 0, PARAM_POST_GAIN, 0);
354
355 drc_set_param(drc, 1, PARAM_CROSSOVER_LOWER_FREQ, f1);
356 drc_set_param(drc, 1, PARAM_ENABLED, 0);
357 drc_set_param(drc, 1, PARAM_THRESHOLD, -30);
358 drc_set_param(drc, 1, PARAM_KNEE, 0);
359 drc_set_param(drc, 1, PARAM_RATIO, 3);
360 drc_set_param(drc, 1, PARAM_ATTACK, 0.02);
361 drc_set_param(drc, 1, PARAM_RELEASE, 0.2);
362 drc_set_param(drc, 1, PARAM_POST_GAIN, 0);
363
364 drc_set_param(drc, 2, PARAM_CROSSOVER_LOWER_FREQ, f3);
365 drc_set_param(drc, 2, PARAM_ENABLED, 1);
366 drc_set_param(drc, 2, PARAM_THRESHOLD, -30);
367 drc_set_param(drc, 2, PARAM_KNEE, 0);
368 drc_set_param(drc, 2, PARAM_RATIO, 1);
369 drc_set_param(drc, 2, PARAM_ATTACK, 0.02);
370 drc_set_param(drc, 2, PARAM_RELEASE, 0.2);
371 drc_set_param(drc, 2, PARAM_POST_GAIN, 20);
372
373 drc_init(drc);
374
375 memset(data_left, 0, sizeof(float) * len);
376 memset(data_right, 0, sizeof(float) * len);
377 add_sine(data_left, len, f0, 0, 1);
378 add_sine(data_left, len, f2, 0, 1);
379 add_sine(data_left, len, f4, 0, 1);
380 add_sine(data_right, len, f0, 0, 1);
381 add_sine(data_right, len, f2, 0, 1);
382 add_sine(data_right, len, f4, 0, 1);
383
384 for (size_t start = 0; start < len; start += DRC_PROCESS_MAX_FRAMES) {
385 int chunk = std::min(len - start, (size_t)DRC_PROCESS_MAX_FRAMES);
386 drc_process(drc, data, chunk);
387 data[0] += chunk;
388 data[1] += chunk;
389 }
390
391 /* This is -8dB because there is a 12dB makeup (20dB^0.6) inside the DRC */
392 EXPECT_NEAR(0.4, magnitude_at(data_right, len, f0), 0.1);
393
394 /* This is 0dB because the DRC is disabled */
395 EXPECT_NEAR(1, magnitude_at(data_right, len, f2), 0.1);
396
397 /* This is 20dB because of the post gain */
398 EXPECT_NEAR(10, magnitude_at(data_right, len, f4), 1);
399
400 /* Test for empty input */
401 drc_process(drc, data_empty, 0);
402
403 drc_free(drc);
404 free(data_left);
405 free(data_right);
406 }
407
408 } // namespace
409
main(int argc,char ** argv)410 int main(int argc, char **argv) {
411 ::testing::InitGoogleTest(&argc, argv);
412 return RUN_ALL_TESTS();
413 }
414