4980dd0bbe08b8cfac7dce9c432b049d4a51b9e6
[platform/upstream/pulseaudio.git] / 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 }