1 /*-
2 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
3 * Copyright (c) 2005 Ariff Abdullah <ariff@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * *New* and rewritten soft format converter, supporting 24/32bit pcm data,
28 * simplified and optimized.
29 *
30 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
31 * *
32 * This new implementation is fully dedicated in memory of Cameron Grant, *
33 * the creator of the magnificent, highly addictive feeder infrastructure. *
34 * *
35 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
36 *
37 */
38
39 #include <dev/sound/pcm/sound.h>
40 #include "feeder_if.h"
41
42 SND_DECLARE_FILE("$FreeBSD: releng/6.4/sys/dev/sound/pcm/feeder_fmt.c 154970 2006-01-29 02:27:28Z ariff $");
43
44 MALLOC_DEFINE(M_FMTFEEDER, "fmtfeed", "pcm format feeder");
45
46 #define FEEDBUFSZ 8192
47 #define FEEDBUF24SZ 8190
48
49 #define FMT_TRACE(x...) /* printf(x) */
50 #define FMT_TEST(x, y...) /* if (x) FMT_TRACE(y) */
51 #define FMT_ALIGNBYTE(x) /* x */
52
53 /*
54 * Sign inverted ulaw/alaw -> 8 table
55 */
56 static uint8_t ulaw_to_s8_tbl[] = {
57 131, 135, 139, 143, 147, 151, 155, 159,
58 163, 167, 171, 175, 179, 183, 187, 191,
59 194, 196, 198, 200, 202, 204, 206, 208,
60 210, 212, 214, 216, 218, 220, 222, 224,
61 226, 227, 228, 229, 230, 231, 232, 233,
62 234, 235, 236, 237, 238, 239, 240, 241,
63 241, 242, 242, 243, 243, 244, 244, 245,
64 245, 246, 246, 247, 247, 248, 248, 249,
65 249, 249, 250, 250, 250, 250, 251, 251,
66 251, 251, 252, 252, 252, 252, 253, 253,
67 253, 253, 253, 253, 254, 254, 254, 254,
68 254, 254, 254, 254, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0,
73 125, 121, 117, 113, 109, 105, 101, 97,
74 93, 89, 85, 81, 77, 73, 69, 65,
75 62, 60, 58, 56, 54, 52, 50, 48,
76 46, 44, 42, 40, 38, 36, 34, 32,
77 30, 29, 28, 27, 26, 25, 24, 23,
78 22, 21, 20, 19, 18, 17, 16, 15,
79 15, 14, 14, 13, 13, 12, 12, 11,
80 11, 10, 10, 9, 9, 8, 8, 7,
81 7, 7, 6, 6, 6, 6, 5, 5,
82 5, 5, 4, 4, 4, 4, 3, 3,
83 3, 3, 3, 3, 2, 2, 2, 2,
84 2, 2, 2, 2, 1, 1, 1, 1,
85 1, 1, 1, 1, 1, 1, 1, 1,
86 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0,
89 };
90
91 static uint8_t alaw_to_s8_tbl[] = {
92 236, 237, 234, 235, 240, 241, 238, 239,
93 228, 229, 226, 227, 232, 233, 230, 231,
94 246, 246, 245, 245, 248, 248, 247, 247,
95 242, 242, 241, 241, 244, 244, 243, 243,
96 171, 175, 163, 167, 187, 191, 179, 183,
97 139, 143, 131, 135, 155, 159, 147, 151,
98 214, 216, 210, 212, 222, 224, 218, 220,
99 198, 200, 194, 196, 206, 208, 202, 204,
100 255, 255, 255, 255, 255, 255, 255, 255,
101 255, 255, 255, 255, 255, 255, 255, 255,
102 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0,
104 251, 251, 251, 251, 252, 252, 252, 252,
105 249, 249, 249, 249, 250, 250, 250, 250,
106 254, 254, 254, 254, 254, 254, 254, 254,
107 253, 253, 253, 253, 253, 253, 253, 253,
108 20, 19, 22, 21, 16, 15, 18, 17,
109 28, 27, 30, 29, 24, 23, 26, 25,
110 10, 10, 11, 11, 8, 8, 9, 9,
111 14, 14, 15, 15, 12, 12, 13, 13,
112 85, 81, 93, 89, 69, 65, 77, 73,
113 117, 113, 125, 121, 101, 97, 109, 105,
114 42, 40, 46, 44, 34, 32, 38, 36,
115 58, 56, 62, 60, 50, 48, 54, 52,
116 1, 1, 1, 1, 1, 1, 1, 1,
117 1, 1, 1, 1, 1, 1, 1, 1,
118 0, 0, 0, 0, 0, 0, 0, 0,
119 0, 0, 0, 0, 0, 0, 0, 0,
120 5, 5, 5, 5, 4, 4, 4, 4,
121 7, 7, 7, 7, 6, 6, 6, 6,
122 2, 2, 2, 2, 2, 2, 2, 2,
123 3, 3, 3, 3, 3, 3, 3, 3,
124 };
125
126 static uint8_t u8_to_ulaw_tbl[] = {
127 0, 0, 0, 0, 0, 1, 1, 1,
128 1, 2, 2, 2, 2, 3, 3, 3,
129 3, 4, 4, 4, 4, 5, 5, 5,
130 5, 6, 6, 6, 6, 7, 7, 7,
131 7, 8, 8, 8, 8, 9, 9, 9,
132 9, 10, 10, 10, 10, 11, 11, 11,
133 11, 12, 12, 12, 12, 13, 13, 13,
134 13, 14, 14, 14, 14, 15, 15, 15,
135 15, 16, 16, 17, 17, 18, 18, 19,
136 19, 20, 20, 21, 21, 22, 22, 23,
137 23, 24, 24, 25, 25, 26, 26, 27,
138 27, 28, 28, 29, 29, 30, 30, 31,
139 31, 32, 33, 34, 35, 36, 37, 38,
140 39, 40, 41, 42, 43, 44, 45, 46,
141 47, 49, 51, 53, 55, 57, 59, 61,
142 63, 66, 70, 74, 78, 84, 92, 104,
143 254, 231, 219, 211, 205, 201, 197, 193,
144 190, 188, 186, 184, 182, 180, 178, 176,
145 175, 174, 173, 172, 171, 170, 169, 168,
146 167, 166, 165, 164, 163, 162, 161, 160,
147 159, 159, 158, 158, 157, 157, 156, 156,
148 155, 155, 154, 154, 153, 153, 152, 152,
149 151, 151, 150, 150, 149, 149, 148, 148,
150 147, 147, 146, 146, 145, 145, 144, 144,
151 143, 143, 143, 143, 142, 142, 142, 142,
152 141, 141, 141, 141, 140, 140, 140, 140,
153 139, 139, 139, 139, 138, 138, 138, 138,
154 137, 137, 137, 137, 136, 136, 136, 136,
155 135, 135, 135, 135, 134, 134, 134, 134,
156 133, 133, 133, 133, 132, 132, 132, 132,
157 131, 131, 131, 131, 130, 130, 130, 130,
158 129, 129, 129, 129, 128, 128, 128, 128,
159 };
160
161 static uint8_t u8_to_alaw_tbl[] = {
162 42, 42, 42, 42, 42, 43, 43, 43,
163 43, 40, 40, 40, 40, 41, 41, 41,
164 41, 46, 46, 46, 46, 47, 47, 47,
165 47, 44, 44, 44, 44, 45, 45, 45,
166 45, 34, 34, 34, 34, 35, 35, 35,
167 35, 32, 32, 32, 32, 33, 33, 33,
168 33, 38, 38, 38, 38, 39, 39, 39,
169 39, 36, 36, 36, 36, 37, 37, 37,
170 37, 58, 58, 59, 59, 56, 56, 57,
171 57, 62, 62, 63, 63, 60, 60, 61,
172 61, 50, 50, 51, 51, 48, 48, 49,
173 49, 54, 54, 55, 55, 52, 52, 53,
174 53, 10, 11, 8, 9, 14, 15, 12,
175 13, 2, 3, 0, 1, 6, 7, 4,
176 5, 24, 30, 28, 18, 16, 22, 20,
177 106, 110, 98, 102, 122, 114, 75, 90,
178 213, 197, 245, 253, 229, 225, 237, 233,
179 149, 151, 145, 147, 157, 159, 153, 155,
180 133, 132, 135, 134, 129, 128, 131, 130,
181 141, 140, 143, 142, 137, 136, 139, 138,
182 181, 181, 180, 180, 183, 183, 182, 182,
183 177, 177, 176, 176, 179, 179, 178, 178,
184 189, 189, 188, 188, 191, 191, 190, 190,
185 185, 185, 184, 184, 187, 187, 186, 186,
186 165, 165, 165, 165, 164, 164, 164, 164,
187 167, 167, 167, 167, 166, 166, 166, 166,
188 161, 161, 161, 161, 160, 160, 160, 160,
189 163, 163, 163, 163, 162, 162, 162, 162,
190 173, 173, 173, 173, 172, 172, 172, 172,
191 175, 175, 175, 175, 174, 174, 174, 174,
192 169, 169, 169, 169, 168, 168, 168, 168,
193 171, 171, 171, 171, 170, 170, 170, 170,
194 };
195
196 static int
197 feed_table_u8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
198 uint32_t count, void *source)
199 {
200 int j, k = FEEDER_FEED(f->source, c, b, count, source);
201 uint8_t *tbl = (uint8_t *)f->data;
202
203 j = k;
204 while (j > 0) {
205 j--;
206 b[j] = tbl[b[j]] ^ 0x80;
207 }
208 return k;
209 }
210
211 static int
212 feed_table_s16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
213 uint32_t count, void *source)
214 {
215 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
216 uint8_t *tbl = (uint8_t *)f->data;
217
218 i = k;
219 k <<= 1;
220 j = k;
221 while (i > 0) {
222 b[--j] = tbl[b[--i]];
223 b[--j] = 0;
224 }
225 return k;
226 }
227
228 static int
229 feed_table_xlaw(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
230 uint32_t count, void *source)
231 {
232 int j, k = FEEDER_FEED(f->source, c, b, count, source);
233 uint8_t *tbl = (uint8_t *)f->data;
234
235 j = k;
236 while (j > 0) {
237 j--;
238 b[j] = tbl[b[j]];
239 }
240 return k;
241 }
242
243 static struct pcm_feederdesc feeder_ulawtou8_desc[] = {
244 {FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
245 {FEEDER_FMT, AFMT_MU_LAW|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
246 {0, 0, 0, 0},
247 };
248 static kobj_method_t feeder_ulawtou8_methods[] = {
249 KOBJMETHOD(feeder_feed, feed_table_u8),
250 {0, 0}
251 };
252 FEEDER_DECLARE(feeder_ulawtou8, 0, ulaw_to_s8_tbl);
253
254 static struct pcm_feederdesc feeder_alawtou8_desc[] = {
255 {FEEDER_FMT, AFMT_A_LAW, AFMT_U8, 0},
256 {FEEDER_FMT, AFMT_A_LAW|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
257 {0, 0, 0, 0},
258 };
259 static kobj_method_t feeder_alawtou8_methods[] = {
260 KOBJMETHOD(feeder_feed, feed_table_u8),
261 {0, 0}
262 };
263 FEEDER_DECLARE(feeder_alawtou8, 0, alaw_to_s8_tbl);
264
265 static struct pcm_feederdesc feeder_ulawtos16le_desc[] = {
266 {FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_LE, 0},
267 {FEEDER_FMT, AFMT_MU_LAW|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
268 {0, 0, 0, 0},
269 };
270 static kobj_method_t feeder_ulawtos16le_methods[] = {
271 KOBJMETHOD(feeder_feed, feed_table_s16le),
272 {0, 0}
273 };
274 FEEDER_DECLARE(feeder_ulawtos16le, 0, ulaw_to_s8_tbl);
275
276 static struct pcm_feederdesc feeder_alawtos16le_desc[] = {
277 {FEEDER_FMT, AFMT_A_LAW, AFMT_S16_LE, 0},
278 {FEEDER_FMT, AFMT_A_LAW|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
279 {0, 0, 0, 0},
280 };
281 static kobj_method_t feeder_alawtos16le_methods[] = {
282 KOBJMETHOD(feeder_feed, feed_table_s16le),
283 {0, 0}
284 };
285 FEEDER_DECLARE(feeder_alawtos16le, 0, alaw_to_s8_tbl);
286
287 static struct pcm_feederdesc feeder_u8toulaw_desc[] = {
288 {FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
289 {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_MU_LAW|AFMT_STEREO, 0},
290 {0, 0, 0, 0},
291 };
292 static kobj_method_t feeder_u8toulaw_methods[] = {
293 KOBJMETHOD(feeder_feed, feed_table_xlaw),
294 {0, 0}
295 };
296 FEEDER_DECLARE(feeder_u8toulaw, 0, u8_to_ulaw_tbl);
297
298 static struct pcm_feederdesc feeder_u8toalaw_desc[] = {
299 {FEEDER_FMT, AFMT_U8, AFMT_A_LAW, 0},
300 {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_A_LAW|AFMT_STEREO, 0},
301 {0, 0, 0, 0},
302 };
303 static kobj_method_t feeder_u8toalaw_methods[] = {
304 KOBJMETHOD(feeder_feed, feed_table_xlaw),
305 {0, 0}
306 };
307 FEEDER_DECLARE(feeder_u8toalaw, 0, u8_to_alaw_tbl);
308
309 /*
310 * Conversion rules:-
311 * 1. BE -> LE
312 * 2. if fmt == u8 , u8 -> s8 (economical)
313 * 3. Xle -> 16le
314 * 4. if fmt != u8 && fmt == u16le , u16le -> s16le
315 * 4. s16le mono -> s16le stereo
316 *
317 * All conversion done in byte level to preserve endianess.
318 */
319
320 static int
321 feed_common_init(struct pcm_feeder *f)
322 {
323 f->data = malloc(FEEDBUFSZ, M_FMTFEEDER, M_NOWAIT|M_ZERO);
324 if (f->data == NULL)
325 return ENOMEM;
326 return 0;
327 }
328
329 static int
330 feed_common_free(struct pcm_feeder *f)
331 {
332 if (f->data)
333 free(f->data, M_FMTFEEDER);
334 f->data = NULL;
335 return 0;
336 }
337
338 /*
339 * Bit conversion
340 */
341 static int
342 feed_8to16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
343 uint32_t count, void *source)
344 {
345 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
346
347 i = k;
348 k <<= 1;
349 j = k;
350 while (i > 0) {
351 b[--j] = b[--i];
352 b[--j] = 0;
353 }
354 return k;
355 }
356 static struct pcm_feederdesc feeder_8to16le_desc[] = {
357 {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
358 {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
359 {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
360 {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
361 {0, 0, 0, 0},
362 };
363 static kobj_method_t feeder_8to16le_methods[] = {
364 KOBJMETHOD(feeder_feed, feed_8to16le),
365 {0, 0}
366 };
367 FEEDER_DECLARE(feeder_8to16le, 0, NULL);
368
369 static int
370 feed_16leto8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
371 uint32_t count, void *source)
372 {
373 int i, j, k;
374 uint8_t *src = (uint8_t *)f->data;
375
376 k = count << 1;
377 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
378 if (k < 2) {
379 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
380 __func__, k);
381 return 0;
382 }
383 FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
384 FMT_ALIGNBYTE(k &= ~1);
385 i = k;
386 j = k >> 1;
387 while (i > 0) {
388 b[--j] = src[--i];
389 i--;
390 }
391 return k >> 1;
392 }
393 static struct pcm_feederdesc feeder_16leto8_desc[] = {
394 {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
395 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
396 {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
397 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
398 {0, 0, 0, 0},
399 };
400 static kobj_method_t feeder_16leto8_methods[] = {
401 KOBJMETHOD(feeder_init, feed_common_init),
402 KOBJMETHOD(feeder_free, feed_common_free),
403 KOBJMETHOD(feeder_feed, feed_16leto8),
404 {0, 0}
405 };
406 FEEDER_DECLARE(feeder_16leto8, 0, NULL);
407
408 static int
409 feed_16leto24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
410 uint32_t count, void *source)
411 {
412 int i, j, k;
413
414 k = (count / 3) << 1;
415 k = FEEDER_FEED(f->source, c, b, k, source);
416 if (k < 2) {
417 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
418 __func__, k);
419 return 0;
420 }
421 FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
422 FMT_ALIGNBYTE(k &= ~1);
423 i = k;
424 j = (k >> 1) * 3;
425 k = j;
426 while (i > 0) {
427 b[--j] = b[--i];
428 b[--j] = b[--i];
429 b[--j] = 0;
430 }
431 return k;
432 }
433 static struct pcm_feederdesc feeder_16leto24le_desc[] = {
434 {FEEDER_FMT, AFMT_U16_LE, AFMT_U24_LE, 0},
435 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
436 {FEEDER_FMT, AFMT_S16_LE, AFMT_S24_LE, 0},
437 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
438 {0, 0, 0, 0},
439 };
440 static kobj_method_t feeder_16leto24le_methods[] = {
441 KOBJMETHOD(feeder_feed, feed_16leto24le),
442 {0, 0}
443 };
444 FEEDER_DECLARE(feeder_16leto24le, 0, NULL);
445
446 static int
447 feed_24leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
448 uint32_t count, void *source)
449 {
450 int i, j, k;
451 uint8_t *src = (uint8_t *)f->data;
452
453 k = (count * 3) >> 1;
454 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
455 if (k < 3) {
456 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
457 __func__, k);
458 return 0;
459 }
460 FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.\n", __func__);
461 FMT_ALIGNBYTE(k -= k % 3);
462 i = (k / 3) << 1;
463 j = i;
464 while (i > 0) {
465 b[--i] = src[--k];
466 b[--i] = src[--k];
467 k--;
468 }
469 return j;
470 }
471 static struct pcm_feederdesc feeder_24leto16le_desc[] = {
472 {FEEDER_FMT, AFMT_U24_LE, AFMT_U16_LE, 0},
473 {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
474 {FEEDER_FMT, AFMT_S24_LE, AFMT_S16_LE, 0},
475 {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
476 {0, 0, 0, 0},
477 };
478 static kobj_method_t feeder_24leto16le_methods[] = {
479 KOBJMETHOD(feeder_init, feed_common_init),
480 KOBJMETHOD(feeder_free, feed_common_free),
481 KOBJMETHOD(feeder_feed, feed_24leto16le),
482 {0, 0}
483 };
484 FEEDER_DECLARE(feeder_24leto16le, 1, NULL);
485
486 static int
487 feed_16leto32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
488 uint32_t count, void *source)
489 {
490 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
491 if (k < 2) {
492 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
493 __func__, k);
494 return 0;
495 }
496 FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
497 FMT_ALIGNBYTE(k &= ~1);
498 i = k;
499 j = k << 1;
500 k = j;
501 while (i > 0) {
502 b[--j] = b[--i];
503 b[--j] = b[--i];
504 b[--j] = 0;
505 b[--j] = 0;
506 }
507 return k;
508 }
509 static struct pcm_feederdesc feeder_16leto32le_desc[] = {
510 {FEEDER_FMT, AFMT_U16_LE, AFMT_U32_LE, 0},
511 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
512 {FEEDER_FMT, AFMT_S16_LE, AFMT_S32_LE, 0},
513 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
514 {0, 0, 0, 0},
515 };
516 static kobj_method_t feeder_16leto32le_methods[] = {
517 KOBJMETHOD(feeder_feed, feed_16leto32le),
518 {0, 0}
519 };
520 FEEDER_DECLARE(feeder_16leto32le, 0, NULL);
521
522 static int
523 feed_32leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
524 uint32_t count, void *source)
525 {
526 int i, j, k;
527 uint8_t *src = (uint8_t *)f->data;
528
529 k = count << 1;
530 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
531 if (k < 4) {
532 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
533 __func__, k);
534 return 0;
535 }
536 FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.\n", __func__);
537 FMT_ALIGNBYTE(k &= ~3);
538 i = k;
539 k >>= 1;
540 j = k;
541 while (i > 0) {
542 b[--j] = src[--i];
543 b[--j] = src[--i];
544 i -= 2;
545 }
546 return k;
547 }
548 static struct pcm_feederdesc feeder_32leto16le_desc[] = {
549 {FEEDER_FMT, AFMT_U32_LE, AFMT_U16_LE, 0},
550 {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
551 {FEEDER_FMT, AFMT_S32_LE, AFMT_S16_LE, 0},
552 {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
553 {0, 0, 0, 0},
554 };
555 static kobj_method_t feeder_32leto16le_methods[] = {
556 KOBJMETHOD(feeder_init, feed_common_init),
557 KOBJMETHOD(feeder_free, feed_common_free),
558 KOBJMETHOD(feeder_feed, feed_32leto16le),
559 {0, 0}
560 };
561 FEEDER_DECLARE(feeder_32leto16le, 1, NULL);
562 /*
563 * Bit conversion end
564 */
565
566 /*
567 * Channel conversion (mono -> stereo)
568 */
569 static int
570 feed_monotostereo8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
571 uint32_t count, void *source)
572 {
573 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
574
575 i = k;
576 j = k << 1;
577 while (i > 0) {
578 b[--j] = b[--i];
579 b[--j] = b[i];
580 }
581 return k << 1;
582 }
583 static struct pcm_feederdesc feeder_monotostereo8_desc[] = {
584 {FEEDER_FMT, AFMT_U8, AFMT_U8|AFMT_STEREO, 0},
585 {FEEDER_FMT, AFMT_S8, AFMT_S8|AFMT_STEREO, 0},
586 {0, 0, 0, 0},
587 };
588 static kobj_method_t feeder_monotostereo8_methods[] = {
589 KOBJMETHOD(feeder_feed, feed_monotostereo8),
590 {0, 0}
591 };
592 FEEDER_DECLARE(feeder_monotostereo8, 0, NULL);
593
594 static int
595 feed_monotostereo16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
596 uint32_t count, void *source)
597 {
598 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
599 uint8_t l, m;
600
601 if (k < 2) {
602 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
603 __func__, k);
604 return 0;
605 }
606 FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
607 FMT_ALIGNBYTE(k &= ~1);
608 i = k;
609 j = k << 1;
610 while (i > 0) {
611 l = b[--i];
612 m = b[--i];
613 b[--j] = l;
614 b[--j] = m;
615 b[--j] = l;
616 b[--j] = m;
617 }
618 return k << 1;
619 }
620 static struct pcm_feederdesc feeder_monotostereo16_desc[] = {
621 {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE|AFMT_STEREO, 0},
622 {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE|AFMT_STEREO, 0},
623 {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE|AFMT_STEREO, 0},
624 {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE|AFMT_STEREO, 0},
625 {0, 0, 0, 0},
626 };
627 static kobj_method_t feeder_monotostereo16_methods[] = {
628 KOBJMETHOD(feeder_feed, feed_monotostereo16),
629 {0, 0}
630 };
631 FEEDER_DECLARE(feeder_monotostereo16, 0, NULL);
632
633 static int
634 feed_monotostereo24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
635 uint32_t count, void *source)
636 {
637 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
638 uint8_t l, m, n;
639
640 if (k < 3) {
641 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
642 __func__, k);
643 return 0;
644 }
645 FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.\n", __func__);
646 FMT_ALIGNBYTE(k -= k % 3);
647 i = k;
648 j = k << 1;
649 while (i > 0) {
650 l = b[--i];
651 m = b[--i];
652 n = b[--i];
653 b[--j] = l;
654 b[--j] = m;
655 b[--j] = n;
656 b[--j] = l;
657 b[--j] = m;
658 b[--j] = n;
659 }
660 return k << 1;
661 }
662 static struct pcm_feederdesc feeder_monotostereo24_desc[] = {
663 {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_LE|AFMT_STEREO, 0},
664 {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_LE|AFMT_STEREO, 0},
665 {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_BE|AFMT_STEREO, 0},
666 {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_BE|AFMT_STEREO, 0},
667 {0, 0, 0, 0},
668 };
669 static kobj_method_t feeder_monotostereo24_methods[] = {
670 KOBJMETHOD(feeder_feed, feed_monotostereo24),
671 {0, 0}
672 };
673 FEEDER_DECLARE(feeder_monotostereo24, 0, NULL);
674
675 static int
676 feed_monotostereo32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
677 uint32_t count, void *source)
678 {
679 int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
680 uint8_t l, m, n, o;
681
682 if (k < 4) {
683 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
684 __func__, k);
685 return 0;
686 }
687 FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.\n", __func__);
688 FMT_ALIGNBYTE(k &= ~3);
689 i = k;
690 j = k << 1;
691 while (i > 0) {
692 l = b[--i];
693 m = b[--i];
694 n = b[--i];
695 o = b[--i];
696 b[--j] = l;
697 b[--j] = m;
698 b[--j] = n;
699 b[--j] = o;
700 b[--j] = l;
701 b[--j] = m;
702 b[--j] = n;
703 b[--j] = o;
704 }
705 return k << 1;
706 }
707 static struct pcm_feederdesc feeder_monotostereo32_desc[] = {
708 {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_LE|AFMT_STEREO, 0},
709 {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_LE|AFMT_STEREO, 0},
710 {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_BE|AFMT_STEREO, 0},
711 {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_BE|AFMT_STEREO, 0},
712 {0, 0, 0, 0},
713 };
714 static kobj_method_t feeder_monotostereo32_methods[] = {
715 KOBJMETHOD(feeder_feed, feed_monotostereo32),
716 {0, 0}
717 };
718 FEEDER_DECLARE(feeder_monotostereo32, 0, NULL);
719 /*
720 * Channel conversion (mono -> stereo) end
721 */
722
723 /*
724 * Channel conversion (stereo -> mono)
725 */
726 static int
727 feed_stereotomono8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
728 uint32_t count, void *source)
729 {
730 int i, j, k;
731 uint8_t *src = (uint8_t *)f->data;
732
733 k = count << 1;
734 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
735 if (k < 2) {
736 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
737 __func__, k);
738 return 0;
739 }
740 FMT_TEST(k & 1, "%s: Bytes not 8bit (stereo) aligned.\n", __func__);
741 FMT_ALIGNBYTE(k &= ~1);
742 i = k >> 1;
743 j = i;
744 while (i > 0) {
745 k--;
746 b[--i] = src[--k];
747 }
748 return j;
749 }
750 static struct pcm_feederdesc feeder_stereotomono8_desc[] = {
751 {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U8, 0},
752 {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S8, 0},
753 {0, 0, 0, 0},
754 };
755 static kobj_method_t feeder_stereotomono8_methods[] = {
756 KOBJMETHOD(feeder_init, feed_common_init),
757 KOBJMETHOD(feeder_free, feed_common_free),
758 KOBJMETHOD(feeder_feed, feed_stereotomono8),
759 {0, 0}
760 };
761 FEEDER_DECLARE(feeder_stereotomono8, 0, NULL);
762
763 static int
764 feed_stereotomono16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
765 uint32_t count, void *source)
766 {
767 int i, j, k;
768 uint8_t *src = (uint8_t *)f->data;
769
770 k = count << 1;
771 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
772 if (k < 4) {
773 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
774 __func__, k);
775 return 0;
776 }
777 FMT_TEST(k & 3, "%s: Bytes not 16bit (stereo) aligned.\n", __func__);
778 FMT_ALIGNBYTE(k &= ~3);
779 i = k >> 1;
780 j = i;
781 while (i > 0) {
782 k -= 2;
783 b[--i] = src[--k];
784 b[--i] = src[--k];
785 }
786 return j;
787 }
788 static struct pcm_feederdesc feeder_stereotomono16_desc[] = {
789 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_LE, 0},
790 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_LE, 0},
791 {FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_BE, 0},
792 {FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_BE, 0},
793 {0, 0, 0, 0},
794 };
795 static kobj_method_t feeder_stereotomono16_methods[] = {
796 KOBJMETHOD(feeder_init, feed_common_init),
797 KOBJMETHOD(feeder_free, feed_common_free),
798 KOBJMETHOD(feeder_feed, feed_stereotomono16),
799 {0, 0}
800 };
801 FEEDER_DECLARE(feeder_stereotomono16, 0, NULL);
802
803 static int
804 feed_stereotomono24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
805 uint32_t count, void *source)
806 {
807 int i, j, k;
808 uint8_t *src = (uint8_t *)f->data;
809
810 k = count << 1;
811 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
812 if (k < 6) {
813 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
814 __func__, k);
815 return 0;
816 }
817 FMT_TEST(k % 6, "%s: Bytes not 24bit (stereo) aligned.\n", __func__);
818 FMT_ALIGNBYTE(k -= k % 6);
819 i = k >> 1;
820 j = i;
821 while (i > 0) {
822 k -= 3;
823 b[--i] = src[--k];
824 b[--i] = src[--k];
825 b[--i] = src[--k];
826 }
827 return j;
828 }
829 static struct pcm_feederdesc feeder_stereotomono24_desc[] = {
830 {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_LE, 0},
831 {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_LE, 0},
832 {FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_BE, 0},
833 {FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_BE, 0},
834 {0, 0, 0, 0},
835 };
836 static kobj_method_t feeder_stereotomono24_methods[] = {
837 KOBJMETHOD(feeder_init, feed_common_init),
838 KOBJMETHOD(feeder_free, feed_common_free),
839 KOBJMETHOD(feeder_feed, feed_stereotomono24),
840 {0, 0}
841 };
842 FEEDER_DECLARE(feeder_stereotomono24, 0, NULL);
843
844 static int
845 feed_stereotomono32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
846 uint32_t count, void *source)
847 {
848 int i, j, k;
849 uint8_t *src = (uint8_t *)f->data;
850
851 k = count << 1;
852 k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
853 if (k < 8) {
854 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
855 __func__, k);
856 return 0;
857 }
858 FMT_TEST(k & 7, "%s: Bytes not 32bit (stereo) aligned.\n", __func__);
859 FMT_ALIGNBYTE(k &= ~7);
860 i = k >> 1;
861 j = i;
862 while (i > 0) {
863 k -= 4;
864 b[--i] = src[--k];
865 b[--i] = src[--k];
866 b[--i] = src[--k];
867 b[--i] = src[--k];
868 }
869 return j;
870 }
871 static struct pcm_feederdesc feeder_stereotomono32_desc[] = {
872 {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_LE, 0},
873 {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_LE, 0},
874 {FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_BE, 0},
875 {FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_BE, 0},
876 {0, 0, 0, 0},
877 };
878 static kobj_method_t feeder_stereotomono32_methods[] = {
879 KOBJMETHOD(feeder_init, feed_common_init),
880 KOBJMETHOD(feeder_free, feed_common_free),
881 KOBJMETHOD(feeder_feed, feed_stereotomono32),
882 {0, 0}
883 };
884 FEEDER_DECLARE(feeder_stereotomono32, 0, NULL);
885 /*
886 * Channel conversion (stereo -> mono) end
887 */
888
889 /*
890 * Sign conversion
891 */
892 static int
893 feed_sign8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
894 uint32_t count, void *source)
895 {
896 int i, j = FEEDER_FEED(f->source, c, b, count, source);
897
898 i = j;
899 while (i > 0)
900 b[--i] ^= 0x80;
901 return j;
902 }
903 static struct pcm_feederdesc feeder_sign8_desc[] = {
904 {FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
905 {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
906 {FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
907 {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
908 {0, 0, 0, 0},
909 };
910 static kobj_method_t feeder_sign8_methods[] = {
911 KOBJMETHOD(feeder_feed, feed_sign8),
912 {0, 0}
913 };
914 FEEDER_DECLARE(feeder_sign8, 0, NULL);
915
916 static int
917 feed_sign16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
918 uint32_t count, void *source)
919 {
920 int i, j = FEEDER_FEED(f->source, c, b, count, source);
921
922 if (j < 2) {
923 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
924 __func__, j);
925 return 0;
926 }
927 FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.\n", __func__);
928 FMT_ALIGNBYTE(j &= ~1);
929 i = j;
930 while (i > 0) {
931 b[--i] ^= 0x80;
932 i--;
933 }
934 return j;
935 }
936 static struct pcm_feederdesc feeder_sign16le_desc[] = {
937 {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
938 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
939 {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
940 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
941 {0, 0, 0, 0},
942 };
943 static kobj_method_t feeder_sign16le_methods[] = {
944 KOBJMETHOD(feeder_feed, feed_sign16le),
945 {0, 0}
946 };
947 FEEDER_DECLARE(feeder_sign16le, 0, NULL);
948
949 static int
950 feed_sign24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
951 uint32_t count, void *source)
952 {
953 int i, j = FEEDER_FEED(f->source, c, b, count, source);
954
955 if (j < 3) {
956 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
957 __func__, j);
958 return 0;
959 }
960 FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.\n", __func__);
961 FMT_ALIGNBYTE(j -= j % 3);
962 i = j;
963 while (i > 0) {
964 b[--i] ^= 0x80;
965 i -= 2;
966 }
967 return j;
968 }
969 static struct pcm_feederdesc feeder_sign24le_desc[] = {
970 {FEEDER_FMT, AFMT_U24_LE, AFMT_S24_LE, 0},
971 {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
972 {FEEDER_FMT, AFMT_S24_LE, AFMT_U24_LE, 0},
973 {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
974 {0, 0, 0, 0},
975 };
976 static kobj_method_t feeder_sign24le_methods[] = {
977 KOBJMETHOD(feeder_feed, feed_sign24le),
978 {0, 0}
979 };
980 FEEDER_DECLARE(feeder_sign24le, 0, NULL);
981
982 static int
983 feed_sign32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
984 uint32_t count, void *source)
985 {
986 int i, j = FEEDER_FEED(f->source, c, b, count, source);
987
988 if (j < 4) {
989 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
990 __func__, j);
991 return 0;
992 }
993 FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.\n", __func__);
994 FMT_ALIGNBYTE(j &= ~3);
995 i = j;
996 while (i > 0) {
997 b[--i] ^= 0x80;
998 i -= 3;
999 }
1000 return j;
1001 }
1002 static struct pcm_feederdesc feeder_sign32le_desc[] = {
1003 {FEEDER_FMT, AFMT_U32_LE, AFMT_S32_LE, 0},
1004 {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
1005 {FEEDER_FMT, AFMT_S32_LE, AFMT_U32_LE, 0},
1006 {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
1007 {0, 0, 0, 0},
1008 };
1009 static kobj_method_t feeder_sign32le_methods[] = {
1010 KOBJMETHOD(feeder_feed, feed_sign32le),
1011 {0, 0}
1012 };
1013 FEEDER_DECLARE(feeder_sign32le, 0, NULL);
1014 /*
1015 * Sign conversion end.
1016 */
1017
1018 /*
1019 * Endian conversion.
1020 */
1021 static int
1022 feed_endian16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1023 uint32_t count, void *source)
1024 {
1025 int i, j = FEEDER_FEED(f->source, c, b, count, source);
1026 uint8_t v;
1027
1028 if (j < 2) {
1029 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1030 __func__, j);
1031 return 0;
1032 }
1033 FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.\n", __func__);
1034 FMT_ALIGNBYTE(j &= ~1);
1035 i = j;
1036 while (i > 0) {
1037 v = b[--i];
1038 b[i] = b[i - 1];
1039 b[--i] = v;
1040 }
1041 return j;
1042 }
1043 static struct pcm_feederdesc feeder_endian16_desc[] = {
1044 {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
1045 {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_BE|AFMT_STEREO, 0},
1046 {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
1047 {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_BE|AFMT_STEREO, 0},
1048 {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
1049 {FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
1050 {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
1051 {FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
1052 {0, 0, 0, 0},
1053 };
1054 static kobj_method_t feeder_endian16_methods[] = {
1055 KOBJMETHOD(feeder_feed, feed_endian16),
1056 {0, 0}
1057 };
1058 FEEDER_DECLARE(feeder_endian16, 0, NULL);
1059
1060 static int
1061 feed_endian24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1062 uint32_t count, void *source)
1063 {
1064 int i, j = FEEDER_FEED(f->source, c, b, count, source);
1065 uint8_t v;
1066
1067 if (j < 3) {
1068 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1069 __func__, j);
1070 return 0;
1071 }
1072 FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.\n", __func__);
1073 FMT_ALIGNBYTE(j -= j % 3);
1074 i = j;
1075 while (i > 0) {
1076 v = b[--i];
1077 b[i] = b[i - 2];
1078 b[i -= 2] = v;
1079 }
1080 return j;
1081 }
1082 static struct pcm_feederdesc feeder_endian24_desc[] = {
1083 {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_BE, 0},
1084 {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_BE|AFMT_STEREO, 0},
1085 {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_BE, 0},
1086 {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_BE|AFMT_STEREO, 0},
1087 {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_LE, 0},
1088 {FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
1089 {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_LE, 0},
1090 {FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
1091 {0, 0, 0, 0},
1092 };
1093 static kobj_method_t feeder_endian24_methods[] = {
1094 KOBJMETHOD(feeder_feed, feed_endian24),
1095 {0, 0}
1096 };
1097 FEEDER_DECLARE(feeder_endian24, 0, NULL);
1098
1099 static int
1100 feed_endian32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1101 uint32_t count, void *source)
1102 {
1103 int i, j = FEEDER_FEED(f->source, c, b, count, source);
1104 uint8_t l, m;
1105
1106 if (j < 4) {
1107 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1108 __func__, j);
1109 return 0;
1110 }
1111 FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.\n", __func__);
1112 FMT_ALIGNBYTE(j &= ~3);
1113 i = j;
1114 while (i > 0) {
1115 l = b[--i];
1116 m = b[--i];
1117 b[i] = b[i - 1];
1118 b[i + 1] = b[i - 2];
1119 b[--i] = m;
1120 b[--i] = l;
1121 }
1122 return j;
1123 }
1124 static struct pcm_feederdesc feeder_endian32_desc[] = {
1125 {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_BE, 0},
1126 {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_BE|AFMT_STEREO, 0},
1127 {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_BE, 0},
1128 {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_BE|AFMT_STEREO, 0},
1129 {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_LE, 0},
1130 {FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
1131 {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_LE, 0},
1132 {FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
1133 {0, 0, 0, 0},
1134 };
1135 static kobj_method_t feeder_endian32_methods[] = {
1136 KOBJMETHOD(feeder_feed, feed_endian32),
1137 {0, 0}
1138 };
1139 FEEDER_DECLARE(feeder_endian32, 0, NULL);
1140 /*
1141 * Endian conversion end
1142 */
Cache object: ee2f9b49533ca1ef8d599061f83ec4c6
|