]> code.delx.au - pulseaudio/blob - src/tests/mix-test.c
core: Move pa_mix() into new file mix.c
[pulseaudio] / src / tests / mix-test.c
1 /***
2 This file is part of PulseAudio.
3
4 PulseAudio is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published
6 by the Free Software Foundation; either version 2.1 of the License,
7 or (at your option) any later version.
8
9 PulseAudio is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with PulseAudio; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <math.h>
26
27 #include <check.h>
28
29 #include <pulse/sample.h>
30 #include <pulse/volume.h>
31
32 #include <pulsecore/macro.h>
33 #include <pulsecore/endianmacros.h>
34 #include <pulsecore/memblock.h>
35 #include <pulsecore/sample-util.h>
36 #include <pulsecore/mix.h>
37
38
39 /* PA_SAMPLE_U8 */
40 static const uint8_t u8_result[3][10] = {
41 { 0x00, 0xff, 0x7f, 0x80, 0x9f, 0x3f, 0x01, 0xf0, 0x20, 0x21 },
42 { 0x0c, 0xf2, 0x7f, 0x80, 0x9b, 0x45, 0x0d, 0xe4, 0x29, 0x2a },
43 { 0x00, 0xff, 0x7e, 0x80, 0xba, 0x04, 0x00, 0xff, 0x00, 0x00 },
44 };
45
46 /* PA_SAMPLE_ALAW */
47 static const uint8_t alaw_result[3][10] = {
48 { 0x00, 0xff, 0x7f, 0x80, 0x9f, 0x3f, 0x01, 0xf0, 0x20, 0x21 },
49 { 0x06, 0xf2, 0x72, 0x86, 0x92, 0x32, 0x07, 0xf6, 0x26, 0x27 },
50 { 0x31, 0xec, 0x6d, 0xb1, 0x8c, 0x2d, 0x36, 0xe1, 0x2a, 0x2a },
51 };
52
53 /* PA_SAMPLE_ULAW */
54 static const uint8_t ulaw_result[3][10] = {
55 { 0x00, 0xff, 0x7f, 0x80, 0x9f, 0x3f, 0x01, 0xf0, 0x20, 0x21 },
56 { 0x03, 0xff, 0xff, 0x83, 0xa2, 0x42, 0x04, 0xf2, 0x23, 0x24 },
57 { 0x00, 0xff, 0xff, 0x80, 0x91, 0x31, 0x00, 0xe9, 0x12, 0x13 },
58 };
59
60 /* PA_SAMPLE_S16LE */
61 static const uint16_t s16le_result[3][10] = {
62 { 0x0000, 0xffff, 0x7fff, 0x8000, 0x9fff, 0x3fff, 0x0001, 0xf000, 0x0020, 0x0021 },
63 { 0x0000, 0xffff, 0x7332, 0x8ccd, 0xa998, 0x3998, 0x0000, 0xf199, 0x001c, 0x001d },
64 { 0x0000, 0xfffe, 0x7fff, 0x8000, 0x8000, 0x7997, 0x0001, 0xe199, 0x003c, 0x003e },
65 };
66
67 /* PA_SAMPLE_S16BE */
68 static const uint16_t s16be_result[3][10] = {
69 { 0x0000, 0xffff, 0x7fff, 0x8000, 0x9fff, 0x3fff, 0x0001, 0xf000, 0x0020, 0x0021 },
70 { 0x0000, 0xffff, 0x8bff, 0x7300, 0xa8ff, 0x52ff, 0xe600, 0xd700, 0xcc1c, 0xb31d },
71 { 0x0000, 0xfeff, 0x0aff, 0xf300, 0x47ff, 0x91fe, 0xe601, 0xc701, 0xcc3c, 0xb33e },
72 };
73
74 /* PA_SAMPLE_FLOAT32LE */
75 static const float float32le_result[3][10] = {
76 { 0.000000, -1.000000, 1.000000, 4711.000000, 0.222000, 0.330000, -0.300000, 99.000000, -0.555000, -0.123000 },
77 { 0.000000, -0.899987, 0.899987, 4239.837402, 0.199797, 0.296996, -0.269996, 89.098679, -0.499493, -0.110698 },
78 { 0.000000, -1.899987, 1.899987, 8950.837891, 0.421797, 0.626996, -0.569996, 188.098679, -1.054493, -0.233698 },
79 };
80
81 /* PA_SAMPLE_FLOAT32BE */
82 static const float float32be_result[3][10] = {
83 { 0.000000, -1.000000, 1.000000, 4711.000000, 0.222000, 0.330000, -0.300000, 99.000000, -0.555000, -0.123000 },
84 { 0.000000, -0.899987, 0.899987, 4239.837402, 0.199797, 0.296996, -0.269996, 89.098679, -0.499493, -0.110698 },
85 { 0.000000, -1.899987, 1.899987, 8950.837891, 0.421797, 0.626996, -0.569996, 188.098679, -1.054493, -0.233698 },
86 };
87
88 /* PA_SAMPLE_S32LE */
89 static const uint32_t s32le_result[3][10] = {
90 { 0x00000001, 0xffff0002, 0x7fff0003, 0x80000004, 0x9fff0005, 0x3fff0006, 0x00010007, 0xf0000008, 0x00200009, 0x0021000a },
91 { 0x00000000, 0xffff199b, 0x7332199c, 0x8ccd0003, 0xa998d99e, 0x3998999f, 0x0000e66c, 0xf199a007, 0x001cccc8, 0x001db32e },
92 { 0x00000001, 0xfffe199d, 0x7fffffff, 0x80000000, 0x80000000, 0x799799a5, 0x0001e673, 0xe199a00f, 0x003cccd1, 0x003eb338 },
93 };
94
95 /* PA_SAMPLE_S32BE */
96 static const uint32_t s32be_result[3][10] = {
97 { 0x00000001, 0xffff0002, 0x7fff0003, 0x80000004, 0x9fff0005, 0x3fff0006, 0x00010007, 0xf0000008, 0x00200009, 0x0021000a },
98 { 0x0066e600, 0x65b2cd01, 0xf117b402, 0x73989903, 0x0ee48004, 0xb8496705, 0xe6ca4c06, 0xd7303307, 0xccb21908, 0xb3190009 },
99 { 0x0066e601, 0x64b2ce03, 0x7017b505, 0xf3989907, 0xade38109, 0xf748680b, 0xe6cb4c0d, 0xc731330f, 0xccd21911, 0xb33a0013 },
100 };
101
102 /* PA_SAMPLE_S24LE */
103 static const uint8_t s24le_result[3][30] = {
104 { 0x00, 0x00, 0x01, 0xff, 0xff, 0x02, 0x7f, 0xff, 0x03, 0x80, 0x00, 0x04, 0x9f, 0xff, 0x05, 0x3f, 0xff, 0x06, 0x01, 0x00, 0x07, 0xf0, 0x00, 0x08, 0x20, 0x00, 0x09, 0x21, 0x00, 0x0a },
105 { 0x66, 0xe6, 0x00, 0x31, 0xb3, 0x02, 0x23, 0x99, 0x03, 0x0b, 0x9a, 0x03, 0x0c, 0x66, 0x05, 0x1c, 0x4c, 0x06, 0xca, 0x4c, 0x06, 0x07, 0x34, 0x07, 0xb2, 0x19, 0x08, 0x19, 0x00, 0x09 },
106 { 0x66, 0xe6, 0x01, 0x30, 0xb3, 0x05, 0xa2, 0x98, 0x07, 0x8b, 0x9a, 0x07, 0xab, 0x65, 0x0b, 0x5b, 0x4b, 0x0d, 0xcb, 0x4c, 0x0d, 0xf7, 0x34, 0x0f, 0xd2, 0x19, 0x11, 0x3a, 0x00, 0x13 },
107 };
108
109 /* PA_SAMPLE_S24BE */
110 static const uint8_t s24be_result[3][30] = {
111 { 0x00, 0x00, 0x01, 0xff, 0xff, 0x02, 0x7f, 0xff, 0x03, 0x80, 0x00, 0x04, 0x9f, 0xff, 0x05, 0x3f, 0xff, 0x06, 0x01, 0x00, 0x07,
112 0xf0, 0x00, 0x08, 0x20, 0x00, 0x09, 0x21, 0x00, 0x0a },
113 { 0x00, 0x00, 0x00, 0xff, 0xff, 0x1b, 0x73, 0x32, 0x1c, 0x8c, 0xcd, 0x03, 0xa9, 0x98, 0xde, 0x39, 0x98, 0x9f, 0x00, 0xe6, 0x6c,
114 0xf1, 0x99, 0xa7, 0x1c, 0xcc, 0xc8, 0x1d, 0xb3, 0x2e },
115 { 0x00, 0x00, 0x01, 0xff, 0xfe, 0x1d, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x79, 0x97, 0xa5, 0x01, 0xe6, 0x73,
116 0xe1, 0x99, 0xaf, 0x3c, 0xcc, 0xd1, 0x3e, 0xb3, 0x38 },
117 };
118
119 /* PA_SAMPLE_S24_32LE */
120 static const uint32_t s24_32le_result[3][10] = {
121 { 0x00000001, 0xffff0002, 0x7fff0003, 0x80000004, 0x9fff0005, 0x3fff0006, 0x00010007, 0xf0000008, 0x00200009, 0x0021000a },
122 { 0x00000000, 0x00ff199b, 0x00ff199c, 0x00000003, 0x00ff199e, 0x00ff199f, 0x0000e66c, 0x00000007, 0x001cccc8, 0x001db32e },
123 { 0x00000001, 0x00fe199d, 0x00fe199f, 0x00000007, 0x00fe19a3, 0x00fe19a5, 0x0001e673, 0x0000000f, 0x003cccd1, 0x003eb338 },
124 };
125
126 /* PA_SAMPLE_S24_32BE */
127 static const uint32_t s24_32be_result[3][10] = {
128 { 0x00000001, 0xffff0002, 0x7fff0003, 0x80000004, 0x9fff0005, 0x3fff0006, 0x00010007, 0xf0000008, 0x00200009, 0x0021000a },
129 { 0x00000000, 0x65e60000, 0xf1e50000, 0x73000000, 0x0ee60000, 0xb8e50000, 0xe6000000, 0xd7000000, 0xcc1c0000, 0xb31d0000 },
130 { 0x00000000, 0xe5010200, 0x00036400, 0x0470e500, 0xf3000000, 0xe5010500, 0x0006ad00, 0x07f7e400, 0xe6010000, 0x00000800 },
131 };
132
133 static void compare_block(const pa_sample_spec *ss, const pa_memchunk *chunk, int iter) {
134 void *d;
135 unsigned i;
136
137 d = pa_memblock_acquire(chunk->memblock);
138
139 switch (ss->format) {
140 case PA_SAMPLE_U8: {
141 const uint8_t *v = u8_result[iter];
142 uint8_t *u = d;
143
144 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
145 fail_unless(*u == *v, NULL);
146 ++u;
147 ++v;
148 }
149 break;
150 }
151
152 case PA_SAMPLE_ALAW: {
153 const uint8_t *v = alaw_result[iter];
154 uint8_t *u = d;
155
156 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
157 fail_unless(*u == *v, NULL);
158 ++u;
159 ++v;
160 }
161 break;
162 }
163
164 case PA_SAMPLE_ULAW: {
165 const uint8_t *v = ulaw_result[iter];
166 uint8_t *u = d;
167
168 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
169 fail_unless(*u == *v, NULL);
170 ++u;
171 ++v;
172 }
173 break;
174 }
175
176 case PA_SAMPLE_S16LE: {
177 const uint16_t *v = s16le_result[iter];
178 uint16_t *u = d;
179
180 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
181 fail_unless(*u == *v, NULL);
182 ++u;
183 ++v;
184 }
185 break;
186 }
187
188 case PA_SAMPLE_S16BE: {
189 const uint16_t *v = s16be_result[iter];
190 uint16_t *u = d;
191
192 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
193 fail_unless(*u == *v, NULL);
194 ++u;
195 ++v;
196 }
197 break;
198 }
199
200 case PA_SAMPLE_FLOAT32LE: {
201 const float *v = float32le_result[iter];
202 float *u = d;
203
204 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
205 float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u);
206 fail_unless(fabs(uu - *v) <= 1e-6, NULL);
207 ++u;
208 ++v;
209 }
210 break;
211 }
212
213 case PA_SAMPLE_FLOAT32BE: {
214 const float *v = float32be_result[iter];
215 float *u = d;
216
217 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
218 float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u);
219 fail_unless(fabs(uu - *v) <= 1e-6, NULL);
220 ++u;
221 ++v;
222 }
223 break;
224 }
225
226 case PA_SAMPLE_S32LE: {
227 const uint32_t *v = s32le_result[iter];
228 uint32_t *u = d;
229
230 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
231 fail_unless(*u == *v, NULL);
232 ++u;
233 ++v;
234 }
235 break;
236 }
237
238 case PA_SAMPLE_S32BE: {
239 const uint32_t *v = s32be_result[iter];
240 uint32_t *u = d;
241
242 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
243 fail_unless(*u == *v, NULL);
244 ++u;
245 ++v;
246 }
247 break;
248 }
249
250 case PA_SAMPLE_S24_32LE: {
251 const uint32_t *v = s24_32le_result[iter];
252 uint32_t *u = d;
253
254 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
255 fail_unless(*u == *v, NULL);
256 ++u;
257 ++v;
258 }
259 break;
260 }
261
262 case PA_SAMPLE_S24_32BE: {
263 const uint32_t *v = s24_32be_result[iter];
264 uint32_t *u = d;
265
266 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
267 fail_unless(*u == *v, NULL);
268 ++u;
269 ++v;
270 }
271 break;
272 }
273
274 case PA_SAMPLE_S24LE: {
275 const uint8_t *v = s24le_result[iter];
276 uint8_t *u = d;
277
278 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
279 fail_unless(*u == *v, NULL);
280 fail_unless(*(u+1) == *(v+1), NULL);
281 fail_unless(*(u+2) == *(v+2), NULL);
282
283 u += 3;
284 v += 3;
285 }
286 break;
287 }
288
289 case PA_SAMPLE_S24BE: {
290 const uint8_t *v = s24be_result[iter];
291 uint8_t *u = d;
292
293 for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
294 fail_unless(*u == *v, NULL);
295 fail_unless(*(u+1) == *(v+1), NULL);
296 fail_unless(*(u+2) == *(v+2), NULL);
297
298 u += 3;
299 v += 3;
300 }
301 break;
302 }
303
304 default:
305 pa_assert_not_reached();
306 }
307
308 pa_memblock_release(chunk->memblock);
309 }
310
311 static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
312 pa_memblock *r;
313 void *d;
314 unsigned i;
315
316 pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
317 d = pa_memblock_acquire(r);
318
319 switch (ss->format) {
320
321 case PA_SAMPLE_U8:
322 case PA_SAMPLE_ULAW:
323 case PA_SAMPLE_ALAW: {
324 static const uint8_t u8_samples[] = {
325 0x00, 0xFF, 0x7F, 0x80, 0x9f,
326 0x3f, 0x01, 0xF0, 0x20, 0x21
327 };
328
329 memcpy(d, u8_samples, sizeof(u8_samples));
330 break;
331 }
332
333 case PA_SAMPLE_S16NE:
334 case PA_SAMPLE_S16RE: {
335 static const uint16_t u16_samples[] = {
336 0x0000, 0xFFFF, 0x7FFF, 0x8000, 0x9fff,
337 0x3fff, 0x0001, 0xF000, 0x0020, 0x0021
338 };
339
340 memcpy(d, u16_samples, sizeof(u16_samples));
341 break;
342 }
343
344 case PA_SAMPLE_S24_32NE:
345 case PA_SAMPLE_S24_32RE:
346 case PA_SAMPLE_S32NE:
347 case PA_SAMPLE_S32RE: {
348 static const uint32_t u32_samples[] = {
349 0x00000001, 0xFFFF0002, 0x7FFF0003, 0x80000004, 0x9fff0005,
350 0x3fff0006, 0x00010007, 0xF0000008, 0x00200009, 0x0021000A
351 };
352
353 memcpy(d, u32_samples, sizeof(u32_samples));
354 break;
355 }
356
357 case PA_SAMPLE_S24NE:
358 case PA_SAMPLE_S24RE: {
359 /* Need to be on a byte array because they are not aligned */
360 static const uint8_t u24_samples[] = {
361 0x00, 0x00, 0x01,
362 0xFF, 0xFF, 0x02,
363 0x7F, 0xFF, 0x03,
364 0x80, 0x00, 0x04,
365 0x9f, 0xff, 0x05,
366 0x3f, 0xff, 0x06,
367 0x01, 0x00, 0x07,
368 0xF0, 0x00, 0x08,
369 0x20, 0x00, 0x09,
370 0x21, 0x00, 0x0A
371 };
372
373 memcpy(d, u24_samples, sizeof(u24_samples));
374 break;
375 }
376
377 case PA_SAMPLE_FLOAT32NE:
378 case PA_SAMPLE_FLOAT32RE: {
379 float *u = d;
380 static const float float_samples[] = {
381 0.0f, -1.0f, 1.0f, 4711.0f, 0.222f,
382 0.33f, -.3f, 99.0f, -0.555f, -.123f
383 };
384
385 if (ss->format == PA_SAMPLE_FLOAT32RE) {
386 for (i = 0; i < 10; i++)
387 u[i] = PA_FLOAT32_SWAP(float_samples[i]);
388 } else
389 memcpy(d, float_samples, sizeof(float_samples));
390
391 break;
392 }
393
394 default:
395 pa_assert_not_reached();
396 }
397
398 pa_memblock_release(r);
399
400 return r;
401 }
402
403 START_TEST (mix_test) {
404 pa_mempool *pool;
405 pa_sample_spec a;
406 pa_cvolume v;
407
408 if (!getenv("MAKE_CHECK"))
409 pa_log_set_level(PA_LOG_DEBUG);
410
411 fail_unless((pool = pa_mempool_new(FALSE, 0)) != NULL, NULL);
412
413 a.channels = 1;
414 a.rate = 44100;
415
416 v.channels = a.channels;
417 v.values[0] = pa_sw_volume_from_linear(0.9);
418
419 for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
420 pa_memchunk i, j, k;
421 pa_mix_info m[2];
422 void *ptr;
423
424 pa_log_debug("=== mixing: %s\n", pa_sample_format_to_string(a.format));
425
426 /* Generate block */
427 i.memblock = generate_block(pool, &a);
428 i.length = pa_memblock_get_length(i.memblock);
429 i.index = 0;
430
431 compare_block(&a, &i, 0);
432
433 /* Make a copy */
434 j = i;
435 pa_memblock_ref(j.memblock);
436 pa_memchunk_make_writable(&j, 0);
437
438 /* Adjust volume of the copy */
439 pa_volume_memchunk(&j, &a, &v);
440
441 compare_block(&a, &j, 1);
442
443 m[0].chunk = i;
444 m[0].volume.values[0] = PA_VOLUME_NORM;
445 m[0].volume.channels = a.channels;
446 m[1].chunk = j;
447 m[1].volume.values[0] = PA_VOLUME_NORM;
448 m[1].volume.channels = a.channels;
449
450 k.memblock = pa_memblock_new(pool, i.length);
451 k.length = i.length;
452 k.index = 0;
453
454 ptr = pa_memblock_acquire_chunk(&k);
455 pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE);
456 pa_memblock_release(k.memblock);
457
458 compare_block(&a, &k, 2);
459
460 pa_memblock_unref(i.memblock);
461 pa_memblock_unref(j.memblock);
462 pa_memblock_unref(k.memblock);
463 }
464
465 pa_mempool_free(pool);
466 }
467 END_TEST
468
469 int main(int argc, char *argv[]) {
470 int failed = 0;
471 Suite *s;
472 TCase *tc;
473 SRunner *sr;
474
475 s = suite_create("Mix");
476 tc = tcase_create("mix");
477 tcase_add_test(tc, mix_test);
478 suite_add_tcase(s, tc);
479
480 sr = srunner_create(s);
481 srunner_run_all(sr, CK_NORMAL);
482 failed = srunner_ntests_failed(sr);
483 srunner_free(sr);
484
485 return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
486 }