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. */ 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. */ 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 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 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 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 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 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 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 410 int main(int argc, char **argv) { 411 ::testing::InitGoogleTest(&argc, argv); 412 return RUN_ALL_TESTS(); 413 } 414