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