]> code.delx.au - pulseaudio/blob - src/tests/mix-test.c
Implement mix-test for s24le and s24be sample formats.
[pulseaudio] / 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 }