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