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