Merge commit 'flameeyes/master'
[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
26 #include <pulse/sample.h>
27 #include <pulse/volume.h>
28
29 #include <pulsecore/resampler.h>
30 #include <pulsecore/macro.h>
31 #include <pulsecore/endianmacros.h>
32 #include <pulsecore/memblock.h>
33 #include <pulsecore/sample-util.h>
34
35 #include <liboil/liboil.h>
36
37 static float swap_float(float a) {
38     uint32_t *b = (uint32_t*) &a;
39     *b = PA_UINT32_SWAP(*b);
40     return a;
41 }
42
43 static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
44     void *d;
45     unsigned i;
46
47     d = pa_memblock_acquire(chunk->memblock);
48
49     switch (ss->format) {
50
51         case PA_SAMPLE_U8:
52         case PA_SAMPLE_ULAW:
53         case PA_SAMPLE_ALAW: {
54             uint8_t *u = d;
55
56             for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
57                 printf("0x%02x ", *(u++));
58
59             break;
60         }
61
62         case PA_SAMPLE_S16NE:
63         case PA_SAMPLE_S16RE: {
64             uint16_t *u = d;
65
66             for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
67                 printf("0x%04x ", *(u++));
68
69             break;
70         }
71
72         case PA_SAMPLE_S24_32NE:
73         case PA_SAMPLE_S24_32RE:
74         case PA_SAMPLE_S32NE:
75         case PA_SAMPLE_S32RE: {
76             uint32_t *u = d;
77
78             for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
79                 printf("0x%08x ", *(u++));
80
81             break;
82         }
83
84         case PA_SAMPLE_S24NE:
85         case PA_SAMPLE_S24RE: {
86             uint8_t *u = d;
87
88             for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
89                 printf("0x%02x%02x%02xx ", *u, *(u+1), *(u+2));
90                 u += 3;
91             }
92
93             break;
94         }
95
96         case PA_SAMPLE_FLOAT32NE:
97         case PA_SAMPLE_FLOAT32RE: {
98             float *u = d;
99
100             for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
101                 printf("%1.5f ",  ss->format == PA_SAMPLE_FLOAT32NE ? *u : swap_float(*u));
102                 u++;
103             }
104
105             break;
106         }
107
108         default:
109             pa_assert_not_reached();
110     }
111
112     printf("\n");
113
114     pa_memblock_release(chunk->memblock);
115 }
116
117 static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
118     pa_memblock *r;
119     void *d;
120     unsigned i;
121
122     pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
123     d = pa_memblock_acquire(r);
124
125     switch (ss->format) {
126
127         case PA_SAMPLE_U8:
128         case PA_SAMPLE_ULAW:
129         case PA_SAMPLE_ALAW: {
130             static const uint8_t u8_samples[] = {
131                 0x00, 0xFF, 0x7F, 0x80, 0x9f,
132                 0x3f, 0x01, 0xF0, 0x20, 0x21
133             };
134
135             memcpy(d, u8_samples, sizeof(u8_samples));
136             break;
137         }
138
139         case PA_SAMPLE_S16NE:
140         case PA_SAMPLE_S16RE: {
141             static const uint16_t u16_samples[] = {
142                 0x0000, 0xFFFF, 0x7FFF, 0x8000, 0x9fff,
143                 0x3fff, 0x0001, 0xF000, 0x0020, 0x0021
144             };
145
146             memcpy(d, u16_samples, sizeof(u16_samples));
147             break;
148         }
149
150         case PA_SAMPLE_S24_32NE:
151         case PA_SAMPLE_S24_32RE:
152         case PA_SAMPLE_S32NE:
153         case PA_SAMPLE_S32RE: {
154             static const uint32_t u32_samples[] = {
155                 0x00000001, 0xFFFF0002, 0x7FFF0003, 0x80000004, 0x9fff0005,
156                 0x3fff0006, 0x00010007, 0xF0000008, 0x00200009, 0x0021000A
157             };
158
159             memcpy(d, u32_samples, sizeof(u32_samples));
160             break;
161         }
162
163         case PA_SAMPLE_S24NE:
164         case PA_SAMPLE_S24RE: {
165             /* Need to be on a byte array because they are not aligned */
166             static const uint8_t u24_samples[] = {
167                 0x00, 0x00, 0x01,
168                 0xFF, 0xFF, 0x02,
169                 0x7F, 0xFF, 0x03,
170                 0x80, 0x00, 0x04,
171                 0x9f, 0xff, 0x05,
172                 0x3f, 0xff, 0x06,
173                 0x01, 0x00, 0x07,
174                 0xF0, 0x00, 0x08,
175                 0x20, 0x00, 0x09,
176                 0x21, 0x00, 0x0A
177             };
178
179             memcpy(d, u24_samples, sizeof(u24_samples));
180             break;
181         }
182
183         case PA_SAMPLE_FLOAT32NE:
184         case PA_SAMPLE_FLOAT32RE: {
185             float *u = d;
186             static const float float_samples[] = {
187                 0.0f, -1.0f, 1.0f, 4711.0f, 0.222f,
188                 0.33f, -.3f, 99.0f, -0.555f, -.123f
189             };
190
191             if (ss->format == PA_SAMPLE_FLOAT32RE) {
192                 for (i = 0; i < 10; i++)
193                     u[i] = swap_float(float_samples[i]);
194             } else
195               memcpy(d, float_samples, sizeof(float_samples));
196
197             break;
198         }
199
200         default:
201             pa_assert_not_reached();
202     }
203
204     pa_memblock_release(r);
205
206     return r;
207 }
208
209 int main(int argc, char *argv[]) {
210     pa_mempool *pool;
211     pa_sample_spec a;
212     pa_cvolume v;
213
214     oil_init();
215     pa_log_set_level(PA_LOG_DEBUG);
216
217     pa_assert_se(pool = pa_mempool_new(FALSE, 0));
218
219     a.channels = 1;
220     a.rate = 44100;
221
222     v.channels = a.channels;
223     v.values[0] = pa_sw_volume_from_linear(0.9);
224
225     for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
226         pa_memchunk i, j, k;
227         pa_mix_info m[2];
228         void *ptr;
229
230         printf("=== mixing: %s\n", pa_sample_format_to_string(a.format));
231
232         /* Generate block */
233         i.memblock = generate_block(pool, &a);
234         i.length = pa_memblock_get_length(i.memblock);
235         i.index = 0;
236
237         dump_block(&a, &i);
238
239         /* Make a copy */
240         j = i;
241         pa_memblock_ref(j.memblock);
242         pa_memchunk_make_writable(&j, 0);
243
244         /* Adjust volume of the copy */
245         pa_volume_memchunk(&j, &a, &v);
246
247         dump_block(&a, &j);
248
249         m[0].chunk = i;
250         m[0].volume.values[0] = PA_VOLUME_NORM;
251         m[0].volume.channels = a.channels;
252         m[1].chunk = j;
253         m[1].volume.values[0] = PA_VOLUME_NORM;
254         m[1].volume.channels = a.channels;
255
256         k.memblock = pa_memblock_new(pool, i.length);
257         k.length = i.length;
258         k.index = 0;
259
260         ptr = (uint8_t*) pa_memblock_acquire(k.memblock) + k.index;
261         pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE);
262         pa_memblock_release(k.memblock);
263
264         dump_block(&a, &k);
265
266         pa_memblock_unref(i.memblock);
267         pa_memblock_unref(j.memblock);
268         pa_memblock_unref(k.memblock);
269     }
270
271     pa_mempool_free(pool);
272
273     return 0;
274 }