memblock: Add pa_memblock_acquire_chunk().
[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
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 }