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
28 /*
29 * *New* and rewritten soft format converter, supporting 24/32bit pcm data,
30 * simplified and optimized.
31 *
32 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
33 * *
34 * This new implementation is fully dedicated in memory of Cameron Grant, *
35 * the creator of the magnificent, highly addictive feeder infrastructure. *
36 * *
37 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
38 *
39 */
40
41 #include <dev/sound/pcm/sound.h>
42 #include "feeder_if.h"
43
44 SND_DECLARE_FILE("$FreeBSD$");
45
46 static int feeder_fmt_stereodownmix = 0;
47 TUNABLE_INT("hw.snd.feeder_fmt_stereodownmix", &feeder_fmt_stereodownmix);
48 #ifdef SND_DEBUG
49 SYSCTL_INT(_hw_snd, OID_AUTO, feeder_fmt_stereodownmix, CTLFLAG_RW,
50 &feeder_fmt_stereodownmix, 1, "averaging stereo downmix");
51 #endif
52
53 #define FEEDFMT_RESERVOIR 8 /* 32bit stereo */
54
55 static uint8_t ulaw_to_u8_tbl[] = {
56 3, 7, 11, 15, 19, 23, 27, 31,
57 35, 39, 43, 47, 51, 55, 59, 63,
58 66, 68, 70, 72, 74, 76, 78, 80,
59 82, 84, 86, 88, 90, 92, 94, 96,
60 98, 99, 100, 101, 102, 103, 104, 105,
61 106, 107, 108, 109, 110, 111, 112, 113,
62 113, 114, 114, 115, 115, 116, 116, 117,
63 117, 118, 118, 119, 119, 120, 120, 121,
64 121, 121, 122, 122, 122, 122, 123, 123,
65 123, 123, 124, 124, 124, 124, 125, 125,
66 125, 125, 125, 125, 126, 126, 126, 126,
67 126, 126, 126, 126, 127, 127, 127, 127,
68 127, 127, 127, 127, 127, 127, 127, 127,
69 128, 128, 128, 128, 128, 128, 128, 128,
70 128, 128, 128, 128, 128, 128, 128, 128,
71 128, 128, 128, 128, 128, 128, 128, 128,
72 253, 249, 245, 241, 237, 233, 229, 225,
73 221, 217, 213, 209, 205, 201, 197, 193,
74 190, 188, 186, 184, 182, 180, 178, 176,
75 174, 172, 170, 168, 166, 164, 162, 160,
76 158, 157, 156, 155, 154, 153, 152, 151,
77 150, 149, 148, 147, 146, 145, 144, 143,
78 143, 142, 142, 141, 141, 140, 140, 139,
79 139, 138, 138, 137, 137, 136, 136, 135,
80 135, 135, 134, 134, 134, 134, 133, 133,
81 133, 133, 132, 132, 132, 132, 131, 131,
82 131, 131, 131, 131, 130, 130, 130, 130,
83 130, 130, 130, 130, 129, 129, 129, 129,
84 129, 129, 129, 129, 129, 129, 129, 129,
85 128, 128, 128, 128, 128, 128, 128, 128,
86 128, 128, 128, 128, 128, 128, 128, 128,
87 128, 128, 128, 128, 128, 128, 128, 128,
88 };
89
90 static uint8_t alaw_to_u8_tbl[] = {
91 108, 109, 106, 107, 112, 113, 110, 111,
92 100, 101, 98, 99, 104, 105, 102, 103,
93 118, 118, 117, 117, 120, 120, 119, 119,
94 114, 114, 113, 113, 116, 116, 115, 115,
95 43, 47, 35, 39, 59, 63, 51, 55,
96 11, 15, 3, 7, 27, 31, 19, 23,
97 86, 88, 82, 84, 94, 96, 90, 92,
98 70, 72, 66, 68, 78, 80, 74, 76,
99 127, 127, 127, 127, 127, 127, 127, 127,
100 127, 127, 127, 127, 127, 127, 127, 127,
101 128, 128, 128, 128, 128, 128, 128, 128,
102 128, 128, 128, 128, 128, 128, 128, 128,
103 123, 123, 123, 123, 124, 124, 124, 124,
104 121, 121, 121, 121, 122, 122, 122, 122,
105 126, 126, 126, 126, 126, 126, 126, 126,
106 125, 125, 125, 125, 125, 125, 125, 125,
107 148, 147, 150, 149, 144, 143, 146, 145,
108 156, 155, 158, 157, 152, 151, 154, 153,
109 138, 138, 139, 139, 136, 136, 137, 137,
110 142, 142, 143, 143, 140, 140, 141, 141,
111 213, 209, 221, 217, 197, 193, 205, 201,
112 245, 241, 253, 249, 229, 225, 237, 233,
113 170, 168, 174, 172, 162, 160, 166, 164,
114 186, 184, 190, 188, 178, 176, 182, 180,
115 129, 129, 129, 129, 129, 129, 129, 129,
116 129, 129, 129, 129, 129, 129, 129, 129,
117 128, 128, 128, 128, 128, 128, 128, 128,
118 128, 128, 128, 128, 128, 128, 128, 128,
119 133, 133, 133, 133, 132, 132, 132, 132,
120 135, 135, 135, 135, 134, 134, 134, 134,
121 130, 130, 130, 130, 130, 130, 130, 130,
122 131, 131, 131, 131, 131, 131, 131, 131,
123 };
124
125 static uint8_t u8_to_ulaw_tbl[] = {
126 0, 0, 0, 0, 0, 1, 1, 1,
127 1, 2, 2, 2, 2, 3, 3, 3,
128 3, 4, 4, 4, 4, 5, 5, 5,
129 5, 6, 6, 6, 6, 7, 7, 7,
130 7, 8, 8, 8, 8, 9, 9, 9,
131 9, 10, 10, 10, 10, 11, 11, 11,
132 11, 12, 12, 12, 12, 13, 13, 13,
133 13, 14, 14, 14, 14, 15, 15, 15,
134 15, 16, 16, 17, 17, 18, 18, 19,
135 19, 20, 20, 21, 21, 22, 22, 23,
136 23, 24, 24, 25, 25, 26, 26, 27,
137 27, 28, 28, 29, 29, 30, 30, 31,
138 31, 32, 33, 34, 35, 36, 37, 38,
139 39, 40, 41, 42, 43, 44, 45, 46,
140 47, 49, 51, 53, 55, 57, 59, 61,
141 63, 66, 70, 74, 78, 84, 92, 104,
142 254, 231, 219, 211, 205, 201, 197, 193,
143 190, 188, 186, 184, 182, 180, 178, 176,
144 175, 174, 173, 172, 171, 170, 169, 168,
145 167, 166, 165, 164, 163, 162, 161, 160,
146 159, 159, 158, 158, 157, 157, 156, 156,
147 155, 155, 154, 154, 153, 153, 152, 152,
148 151, 151, 150, 150, 149, 149, 148, 148,
149 147, 147, 146, 146, 145, 145, 144, 144,
150 143, 143, 143, 143, 142, 142, 142, 142,
151 141, 141, 141, 141, 140, 140, 140, 140,
152 139, 139, 139, 139, 138, 138, 138, 138,
153 137, 137, 137, 137, 136, 136, 136, 136,
154 135, 135, 135, 135, 134, 134, 134, 134,
155 133, 133, 133, 133, 132, 132, 132, 132,
156 131, 131, 131, 131, 130, 130, 130, 130,
157 129, 129, 129, 129, 128, 128, 128, 128,
158 };
159
160 static uint8_t u8_to_alaw_tbl[] = {
161 42, 42, 42, 42, 42, 43, 43, 43,
162 43, 40, 40, 40, 40, 41, 41, 41,
163 41, 46, 46, 46, 46, 47, 47, 47,
164 47, 44, 44, 44, 44, 45, 45, 45,
165 45, 34, 34, 34, 34, 35, 35, 35,
166 35, 32, 32, 32, 32, 33, 33, 33,
167 33, 38, 38, 38, 38, 39, 39, 39,
168 39, 36, 36, 36, 36, 37, 37, 37,
169 37, 58, 58, 59, 59, 56, 56, 57,
170 57, 62, 62, 63, 63, 60, 60, 61,
171 61, 50, 50, 51, 51, 48, 48, 49,
172 49, 54, 54, 55, 55, 52, 52, 53,
173 53, 10, 11, 8, 9, 14, 15, 12,
174 13, 2, 3, 0, 1, 6, 7, 4,
175 5, 24, 30, 28, 18, 16, 22, 20,
176 106, 110, 98, 102, 122, 114, 75, 90,
177 213, 197, 245, 253, 229, 225, 237, 233,
178 149, 151, 145, 147, 157, 159, 153, 155,
179 133, 132, 135, 134, 129, 128, 131, 130,
180 141, 140, 143, 142, 137, 136, 139, 138,
181 181, 181, 180, 180, 183, 183, 182, 182,
182 177, 177, 176, 176, 179, 179, 178, 178,
183 189, 189, 188, 188, 191, 191, 190, 190,
184 185, 185, 184, 184, 187, 187, 186, 186,
185 165, 165, 165, 165, 164, 164, 164, 164,
186 167, 167, 167, 167, 166, 166, 166, 166,
187 161, 161, 161, 161, 160, 160, 160, 160,
188 163, 163, 163, 163, 162, 162, 162, 162,
189 173, 173, 173, 173, 172, 172, 172, 172,
190 175, 175, 175, 175, 174, 174, 174, 174,
191 169, 169, 169, 169, 168, 168, 168, 168,
192 171, 171, 171, 171, 170, 170, 170, 170,
193 };
194
195 static int
196 feed_table_8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
197 uint32_t count, void *source)
198 {
199 int j, sign, k;
200 uint8_t *tbl = (uint8_t *)f->data;
201
202 if (count < PCM_8_BPS)
203 return (0);
204
205 k = FEEDER_FEED(f->source, c, b, count, source);
206 if (k < PCM_8_BPS)
207 return (0);
208
209 j = k;
210 sign = (f->desc->out & AFMT_SIGNED) ? 0x80 : 0x00;
211
212 do {
213 j--;
214 b[j] = tbl[b[j]] ^ sign;
215 } while (j != 0);
216
217 return (k);
218 }
219
220 static int
221 feed_table_16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
222 uint32_t count, void *source)
223 {
224 int i, j, sign, k;
225 uint8_t *tbl = (uint8_t *)f->data;
226
227 if (count < PCM_16_BPS)
228 return (0);
229
230 k = FEEDER_FEED(f->source, c, b, count >> 1, source);
231 if (k < PCM_8_BPS)
232 return (0);
233
234 i = k;
235 k <<= 1;
236 j = k;
237 sign = (f->desc->out & AFMT_SIGNED) ? 0x80 : 0x00;
238
239 if (f->desc->out & AFMT_BIGENDIAN) {
240 do {
241 b[--j] = 0;
242 b[--j] = tbl[b[--i]] ^ sign;
243 } while (i != 0);
244 } else {
245 do {
246 b[--j] = tbl[b[--i]] ^ sign;
247 b[--j] = 0;
248 } while (i != 0);
249 }
250
251 return (k);
252 }
253
254 static int
255 feed_table_xlaw(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
256 uint32_t count, void *source)
257 {
258 int j, sign, k;
259 uint8_t *tbl = (uint8_t *)f->data;
260
261 if (count < PCM_8_BPS)
262 return (0);
263
264 k = FEEDER_FEED(f->source, c, b, count, source);
265 if (k < PCM_8_BPS)
266 return (0);
267
268 j = k ;
269 sign = (f->desc->in & AFMT_SIGNED) ? 0x80 : 0x00;
270
271 do {
272 j--;
273 b[j] = tbl[b[j] ^ sign];
274 } while (j != 0);
275
276 return (k);
277 }
278
279 static struct pcm_feederdesc feeder_ulawto8_desc[] = {
280 {FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
281 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
282 {FEEDER_FMT, AFMT_MU_LAW, AFMT_S8, 0},
283 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
284 {0, 0, 0, 0},
285 };
286 static kobj_method_t feeder_ulawto8_methods[] = {
287 KOBJMETHOD(feeder_feed, feed_table_8),
288 {0, 0}
289 };
290 FEEDER_DECLARE(feeder_ulawto8, 0, ulaw_to_u8_tbl);
291
292 static struct pcm_feederdesc feeder_alawto8_desc[] = {
293 {FEEDER_FMT, AFMT_A_LAW, AFMT_U8, 0},
294 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
295 {FEEDER_FMT, AFMT_A_LAW, AFMT_S8, 0},
296 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
297 {0, 0, 0, 0},
298 };
299 static kobj_method_t feeder_alawto8_methods[] = {
300 KOBJMETHOD(feeder_feed, feed_table_8),
301 {0, 0}
302 };
303 FEEDER_DECLARE(feeder_alawto8, 0, alaw_to_u8_tbl);
304
305 static struct pcm_feederdesc feeder_ulawto16_desc[] = {
306 {FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_LE, 0},
307 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
308 {FEEDER_FMT, AFMT_MU_LAW, AFMT_U16_LE, 0},
309 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
310 {FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_BE, 0},
311 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
312 {FEEDER_FMT, AFMT_MU_LAW, AFMT_U16_BE, 0},
313 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
314 {0, 0, 0, 0},
315 };
316 static kobj_method_t feeder_ulawto16_methods[] = {
317 KOBJMETHOD(feeder_feed, feed_table_16),
318 {0, 0}
319 };
320 FEEDER_DECLARE(feeder_ulawto16, 0, ulaw_to_u8_tbl);
321
322 static struct pcm_feederdesc feeder_alawto16_desc[] = {
323 {FEEDER_FMT, AFMT_A_LAW, AFMT_S16_LE, 0},
324 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
325 {FEEDER_FMT, AFMT_A_LAW, AFMT_U16_LE, 0},
326 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
327 {FEEDER_FMT, AFMT_A_LAW, AFMT_S16_BE, 0},
328 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
329 {FEEDER_FMT, AFMT_A_LAW, AFMT_U16_BE, 0},
330 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
331 {0, 0, 0, 0},
332 };
333 static kobj_method_t feeder_alawto16_methods[] = {
334 KOBJMETHOD(feeder_feed, feed_table_16),
335 {0, 0}
336 };
337 FEEDER_DECLARE(feeder_alawto16, 0, alaw_to_u8_tbl);
338
339 static struct pcm_feederdesc feeder_8toulaw_desc[] = {
340 {FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
341 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
342 {FEEDER_FMT, AFMT_S8, AFMT_MU_LAW, 0},
343 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
344 {0, 0, 0, 0},
345 };
346 static kobj_method_t feeder_8toulaw_methods[] = {
347 KOBJMETHOD(feeder_feed, feed_table_xlaw),
348 {0, 0}
349 };
350 FEEDER_DECLARE(feeder_8toulaw, 0, u8_to_ulaw_tbl);
351
352 static struct pcm_feederdesc feeder_8toalaw_desc[] = {
353 {FEEDER_FMT, AFMT_U8, AFMT_A_LAW, 0},
354 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
355 {FEEDER_FMT, AFMT_S8, AFMT_A_LAW, 0},
356 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
357 {0, 0, 0, 0},
358 };
359 static kobj_method_t feeder_8toalaw_methods[] = {
360 KOBJMETHOD(feeder_feed, feed_table_xlaw),
361 {0, 0}
362 };
363 FEEDER_DECLARE(feeder_8toalaw, 0, u8_to_alaw_tbl);
364
365 /*
366 * All conversion done in byte level to preserve endianess.
367 */
368
369 #define FEEDFMT_SWAP_SIGN(f) (((((f)->desc->in & AFMT_SIGNED) == 0) != \
370 (((f)->desc->out & AFMT_SIGNED) == 0)) \
371 ? 0x80 : 0x00)
372
373 /*
374 * Bit conversion
375 */
376
377 #define FBIT_DATA(i, o, c) ((intptr_t)((((c) & 0xf) << 6) | \
378 (((i) & 0x7) << 3) | ((o) & 0x7)))
379 #define FBIT_OUTBPS(m) ((m) & 0x7)
380 #define FBIT_INBPS(m) FBIT_OUTBPS((m) >> 3)
381 #define FBIT_CHANNELS(m) (((m) >> 6) & 0xf)
382
383 static int
384 feed_updownbit_init(struct pcm_feeder *f)
385 {
386 int ibps, obps, channels;
387
388 if (f->desc->in == f->desc->out || (f->desc->in & AFMT_STEREO) !=
389 (f->desc->out & AFMT_STEREO))
390 return (-1);
391
392 channels = (f->desc->in & AFMT_STEREO) ? 2 : 1;
393
394 if (f->desc->in & AFMT_32BIT)
395 ibps = PCM_32_BPS;
396 else if (f->desc->in & AFMT_24BIT)
397 ibps = PCM_24_BPS;
398 else if (f->desc->in & AFMT_16BIT)
399 ibps = PCM_16_BPS;
400 else
401 ibps = PCM_8_BPS;
402
403 if (f->desc->out & AFMT_32BIT)
404 obps = PCM_32_BPS;
405 else if (f->desc->out & AFMT_24BIT)
406 obps = PCM_24_BPS;
407 else if (f->desc->out & AFMT_16BIT)
408 obps = PCM_16_BPS;
409 else
410 obps = PCM_8_BPS;
411
412 f->data = (void *)FBIT_DATA(ibps, obps, channels);
413
414 return (0);
415 }
416
417 static int
418 feed_upbit(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
419 uint32_t count, void *source)
420 {
421 int i, j, k, sign, ibps, ialign, obps, oalign, pad;
422 uint8_t *src, *dst;
423
424 ibps = FBIT_INBPS((intptr_t)f->data);
425 obps = FBIT_OUTBPS((intptr_t)f->data);
426
427 ialign = ibps * FBIT_CHANNELS((intptr_t)f->data);
428 oalign = obps * FBIT_CHANNELS((intptr_t)f->data);
429
430 if (count < oalign)
431 return (0);
432
433 k = FEEDER_FEED(f->source, c, b, (count / oalign) * ialign, source);
434 if (k < ialign)
435 return (0);
436
437 k -= k % ialign;
438 j = (k / ibps) * obps;
439 pad = obps - ibps;
440 src = b + k;
441 dst = b + j;
442 sign = FEEDFMT_SWAP_SIGN(f);
443
444 if (f->desc->out & AFMT_BIGENDIAN) {
445 do {
446 i = pad;
447 do {
448 *--dst = 0;
449 } while (--i != 0);
450 i = ibps;
451 while (--i != 0)
452 *--dst = *--src;
453 *--dst = *--src ^ sign;
454 } while (dst != b);
455 } else {
456 do {
457 *--dst = *--src ^ sign;
458 i = ibps;
459 while (--i != 0)
460 *--dst = *--src;
461 i = pad;
462 do {
463 *--dst = 0;
464 } while (--i != 0);
465 } while (dst != b);
466 }
467
468 return (j);
469 }
470
471 static struct pcm_feederdesc feeder_8to16_desc[] = {
472 {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
473 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
474 {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
475 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
476 {FEEDER_FMT, AFMT_U8, AFMT_U16_BE, 0},
477 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
478 {FEEDER_FMT, AFMT_S8, AFMT_S16_BE, 0},
479 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
480 {FEEDER_FMT, AFMT_U8, AFMT_S16_LE, 0},
481 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
482 {FEEDER_FMT, AFMT_S8, AFMT_U16_LE, 0},
483 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
484 {FEEDER_FMT, AFMT_U8, AFMT_S16_BE, 0},
485 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
486 {FEEDER_FMT, AFMT_S8, AFMT_U16_BE, 0},
487 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
488 {0, 0, 0, 0},
489 };
490 static kobj_method_t feeder_8to16_methods[] = {
491 KOBJMETHOD(feeder_init, feed_updownbit_init),
492 KOBJMETHOD(feeder_feed, feed_upbit),
493 {0, 0}
494 };
495 FEEDER_DECLARE(feeder_8to16, 0, NULL);
496
497 static struct pcm_feederdesc feeder_8to24_desc[] = {
498 {FEEDER_FMT, AFMT_U8, AFMT_U24_LE, 0},
499 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
500 {FEEDER_FMT, AFMT_S8, AFMT_S24_LE, 0},
501 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
502 {FEEDER_FMT, AFMT_U8, AFMT_U24_BE, 0},
503 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
504 {FEEDER_FMT, AFMT_S8, AFMT_S24_BE, 0},
505 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
506 {FEEDER_FMT, AFMT_U8, AFMT_S24_LE, 0},
507 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
508 {FEEDER_FMT, AFMT_S8, AFMT_U24_LE, 0},
509 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
510 {FEEDER_FMT, AFMT_U8, AFMT_S24_BE, 0},
511 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
512 {FEEDER_FMT, AFMT_S8, AFMT_U24_BE, 0},
513 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
514 {0, 0, 0, 0},
515 };
516 static kobj_method_t feeder_8to24_methods[] = {
517 KOBJMETHOD(feeder_init, feed_updownbit_init),
518 KOBJMETHOD(feeder_feed, feed_upbit),
519 {0, 0}
520 };
521 FEEDER_DECLARE(feeder_8to24, 0, NULL);
522
523 static struct pcm_feederdesc feeder_8to32_desc[] = {
524 {FEEDER_FMT, AFMT_U8, AFMT_U32_LE, 0},
525 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
526 {FEEDER_FMT, AFMT_S8, AFMT_S32_LE, 0},
527 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
528 {FEEDER_FMT, AFMT_U8, AFMT_U32_BE, 0},
529 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
530 {FEEDER_FMT, AFMT_S8, AFMT_S32_BE, 0},
531 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
532 {FEEDER_FMT, AFMT_U8, AFMT_S32_LE, 0},
533 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
534 {FEEDER_FMT, AFMT_S8, AFMT_U32_LE, 0},
535 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
536 {FEEDER_FMT, AFMT_U8, AFMT_S32_BE, 0},
537 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
538 {FEEDER_FMT, AFMT_S8, AFMT_U32_BE, 0},
539 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
540 {0, 0, 0, 0},
541 };
542 static kobj_method_t feeder_8to32_methods[] = {
543 KOBJMETHOD(feeder_init, feed_updownbit_init),
544 KOBJMETHOD(feeder_feed, feed_upbit),
545 {0, 0}
546 };
547 FEEDER_DECLARE(feeder_8to32, 0, NULL);
548
549 static struct pcm_feederdesc feeder_16to24_desc[] = {
550 {FEEDER_FMT, AFMT_U16_LE, AFMT_U24_LE, 0},
551 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
552 {FEEDER_FMT, AFMT_S16_LE, AFMT_S24_LE, 0},
553 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
554 {FEEDER_FMT, AFMT_U16_BE, AFMT_U24_BE, 0},
555 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
556 {FEEDER_FMT, AFMT_S16_BE, AFMT_S24_BE, 0},
557 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
558 {FEEDER_FMT, AFMT_U16_LE, AFMT_S24_LE, 0},
559 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
560 {FEEDER_FMT, AFMT_S16_LE, AFMT_U24_LE, 0},
561 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
562 {FEEDER_FMT, AFMT_U16_BE, AFMT_S24_BE, 0},
563 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
564 {FEEDER_FMT, AFMT_S16_BE, AFMT_U24_BE, 0},
565 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
566 {0, 0, 0, 0},
567 };
568 static kobj_method_t feeder_16to24_methods[] = {
569 KOBJMETHOD(feeder_init, feed_updownbit_init),
570 KOBJMETHOD(feeder_feed, feed_upbit),
571 {0, 0}
572 };
573 FEEDER_DECLARE(feeder_16to24, 0, NULL);
574
575 static struct pcm_feederdesc feeder_16to32_desc[] = {
576 {FEEDER_FMT, AFMT_U16_LE, AFMT_U32_LE, 0},
577 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
578 {FEEDER_FMT, AFMT_S16_LE, AFMT_S32_LE, 0},
579 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
580 {FEEDER_FMT, AFMT_U16_BE, AFMT_U32_BE, 0},
581 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
582 {FEEDER_FMT, AFMT_S16_BE, AFMT_S32_BE, 0},
583 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
584 {FEEDER_FMT, AFMT_U16_LE, AFMT_S32_LE, 0},
585 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
586 {FEEDER_FMT, AFMT_S16_LE, AFMT_U32_LE, 0},
587 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
588 {FEEDER_FMT, AFMT_U16_BE, AFMT_S32_BE, 0},
589 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
590 {FEEDER_FMT, AFMT_S16_BE, AFMT_U32_BE, 0},
591 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
592 {0, 0, 0, 0},
593 };
594 static kobj_method_t feeder_16to32_methods[] = {
595 KOBJMETHOD(feeder_init, feed_updownbit_init),
596 KOBJMETHOD(feeder_feed, feed_upbit),
597 {0, 0}
598 };
599 FEEDER_DECLARE(feeder_16to32, 0, NULL);
600
601 static struct pcm_feederdesc feeder_24to32_desc[] = {
602 {FEEDER_FMT, AFMT_U24_LE, AFMT_U32_LE, 0},
603 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
604 {FEEDER_FMT, AFMT_S24_LE, AFMT_S32_LE, 0},
605 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
606 {FEEDER_FMT, AFMT_U24_BE, AFMT_U32_BE, 0},
607 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
608 {FEEDER_FMT, AFMT_S24_BE, AFMT_S32_BE, 0},
609 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
610 {FEEDER_FMT, AFMT_U24_LE, AFMT_S32_LE, 0},
611 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
612 {FEEDER_FMT, AFMT_S24_LE, AFMT_U32_LE, 0},
613 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
614 {FEEDER_FMT, AFMT_U24_BE, AFMT_S32_BE, 0},
615 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
616 {FEEDER_FMT, AFMT_S24_BE, AFMT_U32_BE, 0},
617 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
618 {0, 0, 0, 0},
619 };
620 static kobj_method_t feeder_24to32_methods[] = {
621 KOBJMETHOD(feeder_init, feed_updownbit_init),
622 KOBJMETHOD(feeder_feed, feed_upbit),
623 {0, 0}
624 };
625 FEEDER_DECLARE(feeder_24to32, 0, NULL);
626
627 static int
628 feed_downbit(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
629 uint32_t count, void *source)
630 {
631 int i, j, k, sign, be, ibps, ialign, obps, oalign,dump;
632 uint8_t *src, *dst, *end;
633 uint8_t reservoir[FEEDFMT_RESERVOIR];
634
635 ibps = FBIT_INBPS((intptr_t)f->data);
636 obps = FBIT_OUTBPS((intptr_t)f->data);
637
638 ialign = ibps * FBIT_CHANNELS((intptr_t)f->data);
639 oalign = obps * FBIT_CHANNELS((intptr_t)f->data);
640
641 if (count < oalign)
642 return (0);
643
644 dst = b;
645 dump = ibps - obps;
646 sign = FEEDFMT_SWAP_SIGN(f);
647 be = (f->desc->in & AFMT_BIGENDIAN) ? 1 : 0;
648 k = count - (count % oalign);
649
650 do {
651 if (k < oalign)
652 break;
653
654 if (k < ialign) {
655 src = reservoir;
656 j = ialign;
657 } else {
658 src = dst;
659 j = k;
660 }
661
662 j = FEEDER_FEED(f->source, c, src, j - (j % ialign), source);
663 if (j < ialign)
664 break;
665
666 j -= j % ialign;
667 j *= obps;
668 j /= ibps;
669 end = dst + j;
670
671 if (be != 0) {
672 do {
673 *dst++ = *src++ ^ sign;
674 i = obps;
675 while (--i != 0)
676 *dst++ = *src++;
677 src += dump;
678 } while (dst != end);
679 } else {
680 do {
681 src += dump;
682 i = obps;
683 while (--i != 0)
684 *dst++ = *src++;
685 *dst++ = *src++ ^ sign;
686 } while (dst != end);
687 }
688
689 k -= j;
690 } while (k != 0);
691
692 return (dst - b);
693 }
694
695 static struct pcm_feederdesc feeder_16to8_desc[] = {
696 {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
697 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
698 {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
699 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
700 {FEEDER_FMT, AFMT_U16_BE, AFMT_U8, 0},
701 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
702 {FEEDER_FMT, AFMT_S16_BE, AFMT_S8, 0},
703 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
704 {FEEDER_FMT, AFMT_U16_LE, AFMT_S8, 0},
705 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
706 {FEEDER_FMT, AFMT_S16_LE, AFMT_U8, 0},
707 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
708 {FEEDER_FMT, AFMT_U16_BE, AFMT_S8, 0},
709 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
710 {FEEDER_FMT, AFMT_S16_BE, AFMT_U8, 0},
711 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
712 {0, 0, 0, 0},
713 };
714 static kobj_method_t feeder_16to8_methods[] = {
715 KOBJMETHOD(feeder_init, feed_updownbit_init),
716 KOBJMETHOD(feeder_feed, feed_downbit),
717 {0, 0}
718 };
719 FEEDER_DECLARE(feeder_16to8, 0, NULL);
720
721 static struct pcm_feederdesc feeder_24to8_desc[] = {
722 {FEEDER_FMT, AFMT_U24_LE, AFMT_U8, 0},
723 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
724 {FEEDER_FMT, AFMT_S24_LE, AFMT_S8, 0},
725 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
726 {FEEDER_FMT, AFMT_U24_BE, AFMT_U8, 0},
727 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
728 {FEEDER_FMT, AFMT_S24_BE, AFMT_S8, 0},
729 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
730 {FEEDER_FMT, AFMT_U24_LE, AFMT_S8, 0},
731 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
732 {FEEDER_FMT, AFMT_S24_LE, AFMT_U8, 0},
733 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
734 {FEEDER_FMT, AFMT_U24_BE, AFMT_S8, 0},
735 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
736 {FEEDER_FMT, AFMT_S24_BE, AFMT_U8, 0},
737 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
738 {0, 0, 0, 0},
739 };
740 static kobj_method_t feeder_24to8_methods[] = {
741 KOBJMETHOD(feeder_init, feed_updownbit_init),
742 KOBJMETHOD(feeder_feed, feed_downbit),
743 {0, 0}
744 };
745 FEEDER_DECLARE(feeder_24to8, 0, NULL);
746
747 static struct pcm_feederdesc feeder_24to16_desc[] = {
748 {FEEDER_FMT, AFMT_U24_LE, AFMT_U16_LE, 0},
749 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
750 {FEEDER_FMT, AFMT_S24_LE, AFMT_S16_LE, 0},
751 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
752 {FEEDER_FMT, AFMT_U24_BE, AFMT_U16_BE, 0},
753 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
754 {FEEDER_FMT, AFMT_S24_BE, AFMT_S16_BE, 0},
755 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
756 {FEEDER_FMT, AFMT_U24_LE, AFMT_S16_LE, 0},
757 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
758 {FEEDER_FMT, AFMT_S24_LE, AFMT_U16_LE, 0},
759 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
760 {FEEDER_FMT, AFMT_U24_BE, AFMT_S16_BE, 0},
761 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
762 {FEEDER_FMT, AFMT_S24_BE, AFMT_U16_BE, 0},
763 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
764 {0, 0, 0, 0},
765 };
766 static kobj_method_t feeder_24to16_methods[] = {
767 KOBJMETHOD(feeder_init, feed_updownbit_init),
768 KOBJMETHOD(feeder_feed, feed_downbit),
769 {0, 0}
770 };
771 FEEDER_DECLARE(feeder_24to16, 0, NULL);
772
773 static struct pcm_feederdesc feeder_32to8_desc[] = {
774 {FEEDER_FMT, AFMT_U32_LE, AFMT_U8, 0},
775 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
776 {FEEDER_FMT, AFMT_S32_LE, AFMT_S8, 0},
777 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
778 {FEEDER_FMT, AFMT_U32_BE, AFMT_U8, 0},
779 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
780 {FEEDER_FMT, AFMT_S32_BE, AFMT_S8, 0},
781 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
782 {FEEDER_FMT, AFMT_U32_LE, AFMT_S8, 0},
783 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
784 {FEEDER_FMT, AFMT_S32_LE, AFMT_U8, 0},
785 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
786 {FEEDER_FMT, AFMT_U32_BE, AFMT_S8, 0},
787 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
788 {FEEDER_FMT, AFMT_S32_BE, AFMT_U8, 0},
789 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
790 {0, 0, 0, 0},
791 };
792 static kobj_method_t feeder_32to8_methods[] = {
793 KOBJMETHOD(feeder_init, feed_updownbit_init),
794 KOBJMETHOD(feeder_feed, feed_downbit),
795 {0, 0}
796 };
797 FEEDER_DECLARE(feeder_32to8, 0, NULL);
798
799 static struct pcm_feederdesc feeder_32to16_desc[] = {
800 {FEEDER_FMT, AFMT_U32_LE, AFMT_U16_LE, 0},
801 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
802 {FEEDER_FMT, AFMT_S32_LE, AFMT_S16_LE, 0},
803 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
804 {FEEDER_FMT, AFMT_U32_BE, AFMT_U16_BE, 0},
805 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
806 {FEEDER_FMT, AFMT_S32_BE, AFMT_S16_BE, 0},
807 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
808 {FEEDER_FMT, AFMT_U32_LE, AFMT_S16_LE, 0},
809 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
810 {FEEDER_FMT, AFMT_S32_LE, AFMT_U16_LE, 0},
811 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
812 {FEEDER_FMT, AFMT_U32_BE, AFMT_S16_BE, 0},
813 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
814 {FEEDER_FMT, AFMT_S32_BE, AFMT_U16_BE, 0},
815 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
816 {0, 0, 0, 0},
817 };
818 static kobj_method_t feeder_32to16_methods[] = {
819 KOBJMETHOD(feeder_init, feed_updownbit_init),
820 KOBJMETHOD(feeder_feed, feed_downbit),
821 {0, 0}
822 };
823 FEEDER_DECLARE(feeder_32to16, 0, NULL);
824
825 static struct pcm_feederdesc feeder_32to24_desc[] = {
826 {FEEDER_FMT, AFMT_U32_LE, AFMT_U24_LE, 0},
827 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
828 {FEEDER_FMT, AFMT_S32_LE, AFMT_S24_LE, 0},
829 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
830 {FEEDER_FMT, AFMT_U32_BE, AFMT_U24_BE, 0},
831 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
832 {FEEDER_FMT, AFMT_S32_BE, AFMT_S24_BE, 0},
833 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
834 {FEEDER_FMT, AFMT_U32_LE, AFMT_S24_LE, 0},
835 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
836 {FEEDER_FMT, AFMT_S32_LE, AFMT_U24_LE, 0},
837 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
838 {FEEDER_FMT, AFMT_U32_BE, AFMT_S24_BE, 0},
839 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
840 {FEEDER_FMT, AFMT_S32_BE, AFMT_U24_BE, 0},
841 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
842 {0, 0, 0, 0},
843 };
844 static kobj_method_t feeder_32to24_methods[] = {
845 KOBJMETHOD(feeder_init, feed_updownbit_init),
846 KOBJMETHOD(feeder_feed, feed_downbit),
847 {0, 0}
848 };
849 FEEDER_DECLARE(feeder_32to24, 0, NULL);
850 /*
851 * Bit conversion end
852 */
853
854 /*
855 * Channel conversion (mono -> stereo)
856 */
857 static int
858 feed_monotostereo(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
859 uint32_t count, void *source)
860 {
861 int bps, i, j, k, l;
862 uint8_t v;
863
864 bps = (int)((intptr_t)f->data);
865 if (count < (bps << 1))
866 return (0);
867
868 j = FEEDER_FEED(f->source, c, b, (count - (count % bps)) >> 1, source);
869 if (j < bps)
870 return (0);
871
872 j -= j % bps;
873 i = j << 1;
874 l = i;
875
876 do {
877 k = bps;
878 do {
879 v = b[--j];
880 b[--i] = v;
881 b[i - bps] = v;
882 } while (--k != 0);
883 i -= bps;
884 } while (i != 0);
885
886 return (l);
887 }
888
889 static struct pcm_feederdesc feeder_monotostereo8_desc[] = {
890 {FEEDER_FMT, AFMT_U8, AFMT_U8 | AFMT_STEREO, 0},
891 {FEEDER_FMT, AFMT_S8, AFMT_S8 | AFMT_STEREO, 0},
892 {FEEDER_FMT, AFMT_MU_LAW, AFMT_MU_LAW | AFMT_STEREO, 0},
893 {FEEDER_FMT, AFMT_A_LAW, AFMT_A_LAW | AFMT_STEREO, 0},
894 {0, 0, 0, 0},
895 };
896 static kobj_method_t feeder_monotostereo8_methods[] = {
897 KOBJMETHOD(feeder_feed, feed_monotostereo),
898 {0, 0}
899 };
900 FEEDER_DECLARE(feeder_monotostereo8, 0, (void *)PCM_8_BPS);
901
902 static struct pcm_feederdesc feeder_monotostereo16_desc[] = {
903 {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE | AFMT_STEREO, 0},
904 {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE | AFMT_STEREO, 0},
905 {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE | AFMT_STEREO, 0},
906 {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE | AFMT_STEREO, 0},
907 {0, 0, 0, 0},
908 };
909 static kobj_method_t feeder_monotostereo16_methods[] = {
910 KOBJMETHOD(feeder_feed, feed_monotostereo),
911 {0, 0}
912 };
913 FEEDER_DECLARE(feeder_monotostereo16, 0, (void *)PCM_16_BPS);
914
915 static struct pcm_feederdesc feeder_monotostereo24_desc[] = {
916 {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_LE | AFMT_STEREO, 0},
917 {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_LE | AFMT_STEREO, 0},
918 {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_BE | AFMT_STEREO, 0},
919 {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_BE | AFMT_STEREO, 0},
920 {0, 0, 0, 0},
921 };
922 static kobj_method_t feeder_monotostereo24_methods[] = {
923 KOBJMETHOD(feeder_feed, feed_monotostereo),
924 {0, 0}
925 };
926 FEEDER_DECLARE(feeder_monotostereo24, 0, (void *)PCM_24_BPS);
927
928 static struct pcm_feederdesc feeder_monotostereo32_desc[] = {
929 {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_LE | AFMT_STEREO, 0},
930 {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_LE | AFMT_STEREO, 0},
931 {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_BE | AFMT_STEREO, 0},
932 {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_BE | AFMT_STEREO, 0},
933 {0, 0, 0, 0},
934 };
935 static kobj_method_t feeder_monotostereo32_methods[] = {
936 KOBJMETHOD(feeder_feed, feed_monotostereo),
937 {0, 0}
938 };
939 FEEDER_DECLARE(feeder_monotostereo32, 0, (void *)PCM_32_BPS);
940 /*
941 * Channel conversion (mono -> stereo) end
942 */
943
944 /*
945 * Channel conversion (stereo -> mono)
946 */
947 #define FEEDER_FMT_STEREODOWNMIX(FMTBIT, FMT_INTCAST, SIGN, \
948 SIGNS, ENDIAN, ENDIANS) \
949 static void \
950 SIGNS##FMTBIT##ENDIANS##_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy) \
951 { \
952 int32_t v; \
953 \
954 v = ((FMT_INTCAST)PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sx) + \
955 PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sy)) >> 1; \
956 PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(dst, v); \
957 }
958
959 FEEDER_FMT_STEREODOWNMIX(8, int32_t, S, s, NE, ne);
960 FEEDER_FMT_STEREODOWNMIX(16, int32_t, S, s, LE, le);
961 FEEDER_FMT_STEREODOWNMIX(24, int32_t, S, s, LE, le);
962 FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, S, s, LE, le);
963 FEEDER_FMT_STEREODOWNMIX(16, int32_t, S, s, BE, be);
964 FEEDER_FMT_STEREODOWNMIX(24, int32_t, S, s, BE, be);
965 FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, S, s, BE, be);
966 FEEDER_FMT_STEREODOWNMIX(8, int32_t, U, u, NE, ne);
967 FEEDER_FMT_STEREODOWNMIX(16, int32_t, U, u, LE, le);
968 FEEDER_FMT_STEREODOWNMIX(24, int32_t, U, u, LE, le);
969 FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, U, u, LE, le);
970 FEEDER_FMT_STEREODOWNMIX(16, int32_t, U, u, BE, be);
971 FEEDER_FMT_STEREODOWNMIX(24, int32_t, U, u, BE, be);
972 FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, U, u, BE, be);
973
974 static void
975 ulaw_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy)
976 {
977 uint8_t v;
978
979 v = ((uint32_t)ulaw_to_u8_tbl[*sx] + ulaw_to_u8_tbl[*sy]) >> 1;
980 *dst = u8_to_ulaw_tbl[v];
981 }
982
983 static void
984 alaw_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy)
985 {
986 uint8_t v;
987
988 v = ((uint32_t)alaw_to_u8_tbl[*sx] + alaw_to_u8_tbl[*sy]) >> 1;
989 *dst = u8_to_alaw_tbl[v];
990 }
991
992 typedef void (*feed_fmt_stereodownmix_filter)(uint8_t *,
993 uint8_t *, uint8_t *);
994
995 struct feed_fmt_stereodownmix_info {
996 uint32_t format;
997 int bps;
998 feed_fmt_stereodownmix_filter func[2];
999 };
1000
1001 static struct feed_fmt_stereodownmix_info feed_fmt_stereodownmix_tbl[] = {
1002 { AFMT_S8, PCM_8_BPS, { NULL, s8ne_stereodownmix }},
1003 { AFMT_S16_LE, PCM_16_BPS, { NULL, s16le_stereodownmix }},
1004 { AFMT_S16_BE, PCM_16_BPS, { NULL, s16be_stereodownmix }},
1005 { AFMT_S24_LE, PCM_24_BPS, { NULL, s24le_stereodownmix }},
1006 { AFMT_S24_BE, PCM_24_BPS, { NULL, s24be_stereodownmix }},
1007 { AFMT_S32_LE, PCM_32_BPS, { NULL, s32le_stereodownmix }},
1008 { AFMT_S32_BE, PCM_32_BPS, { NULL, s32be_stereodownmix }},
1009 { AFMT_U8, PCM_8_BPS, { NULL, u8ne_stereodownmix }},
1010 { AFMT_A_LAW, PCM_8_BPS, { NULL, alaw_stereodownmix }},
1011 { AFMT_MU_LAW, PCM_8_BPS, { NULL, ulaw_stereodownmix }},
1012 { AFMT_U16_LE, PCM_16_BPS, { NULL, u16le_stereodownmix }},
1013 { AFMT_U16_BE, PCM_16_BPS, { NULL, u16be_stereodownmix }},
1014 { AFMT_U24_LE, PCM_24_BPS, { NULL, u24le_stereodownmix }},
1015 { AFMT_U24_BE, PCM_24_BPS, { NULL, u24be_stereodownmix }},
1016 { AFMT_U32_LE, PCM_32_BPS, { NULL, u32le_stereodownmix }},
1017 { AFMT_U32_BE, PCM_32_BPS, { NULL, u32be_stereodownmix }},
1018 };
1019
1020 #define FSM_DATA(i, j) ((intptr_t)((((i) & 0x1f) << 1) | ((j) & 0x1)))
1021 #define FSM_INFOIDX(m) (((m) >> 1) & 0x1f)
1022 #define FSM_FUNCIDX(m) ((m) & 0x1)
1023
1024 static int
1025 feed_stereotomono_init(struct pcm_feeder *f)
1026 {
1027 int i, funcidx;
1028
1029 if (!(f->desc->in & AFMT_STEREO) || (f->desc->out & AFMT_STEREO))
1030 return (-1);
1031
1032 funcidx = (feeder_fmt_stereodownmix != 0) ? 1 : 0;
1033
1034 for (i = 0; i < sizeof(feed_fmt_stereodownmix_tbl) /
1035 sizeof(feed_fmt_stereodownmix_tbl[0]); i++) {
1036 if (f->desc->out == feed_fmt_stereodownmix_tbl[i].format) {
1037 f->data = (void *)FSM_DATA(i, funcidx);
1038 return (0);
1039 }
1040 }
1041
1042 return (-1);
1043 }
1044
1045 static int
1046 feed_stereotomono(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1047 uint32_t count, void *source)
1048 {
1049 struct feed_fmt_stereodownmix_info *info;
1050 feed_fmt_stereodownmix_filter stereodownmix;
1051 int i, j, k, ibps, obps;
1052 uint8_t *src, *dst, *end;
1053 uint8_t reservoir[FEEDFMT_RESERVOIR];
1054
1055 info = &feed_fmt_stereodownmix_tbl[FSM_INFOIDX((intptr_t)f->data)];
1056 obps = info->bps;
1057
1058 if (count < obps)
1059 return (0);
1060
1061 stereodownmix = info->func[FSM_FUNCIDX((intptr_t)f->data)];
1062 ibps = obps << 1;
1063 dst = b;
1064 k = count - (count % obps);
1065
1066 do {
1067 if (k < obps)
1068 break;
1069
1070 if (k < ibps) {
1071 src = reservoir;
1072 j = ibps;
1073 } else {
1074 src = dst;
1075 j = k;
1076 }
1077
1078 j = FEEDER_FEED(f->source, c, src, j - (j % ibps), source);
1079 if (j < ibps)
1080 break;
1081
1082 j -= j % ibps;
1083 j >>= 1;
1084 end = dst + j;
1085
1086 if (stereodownmix != NULL) {
1087 do {
1088 stereodownmix(dst, src, src + obps);
1089 dst += obps;
1090 src += ibps;
1091 } while (dst != end);
1092 } else {
1093 do {
1094 i = obps;
1095 do {
1096 *dst++ = *src++;
1097 } while (--i != 0);
1098 src += obps;
1099 } while (dst != end);
1100 }
1101
1102 k -= j;
1103 } while (k != 0);
1104
1105 return (dst - b);
1106 }
1107
1108 static struct pcm_feederdesc feeder_stereotomono8_desc[] = {
1109 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U8, 0},
1110 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S8, 0},
1111 {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_MU_LAW, 0},
1112 {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_A_LAW, 0},
1113 {0, 0, 0, 0},
1114 };
1115 static kobj_method_t feeder_stereotomono8_methods[] = {
1116 KOBJMETHOD(feeder_init, feed_stereotomono_init),
1117 KOBJMETHOD(feeder_feed, feed_stereotomono),
1118 {0, 0}
1119 };
1120 FEEDER_DECLARE(feeder_stereotomono8, 0, NULL);
1121
1122 static struct pcm_feederdesc feeder_stereotomono16_desc[] = {
1123 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE, 0},
1124 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE, 0},
1125 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE, 0},
1126 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE, 0},
1127 {0, 0, 0, 0},
1128 };
1129 static kobj_method_t feeder_stereotomono16_methods[] = {
1130 KOBJMETHOD(feeder_init, feed_stereotomono_init),
1131 KOBJMETHOD(feeder_feed, feed_stereotomono),
1132 {0, 0}
1133 };
1134 FEEDER_DECLARE(feeder_stereotomono16, 0, NULL);
1135
1136 static struct pcm_feederdesc feeder_stereotomono24_desc[] = {
1137 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE, 0},
1138 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE, 0},
1139 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE, 0},
1140 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE, 0},
1141 {0, 0, 0, 0},
1142 };
1143 static kobj_method_t feeder_stereotomono24_methods[] = {
1144 KOBJMETHOD(feeder_init, feed_stereotomono_init),
1145 KOBJMETHOD(feeder_feed, feed_stereotomono),
1146 {0, 0}
1147 };
1148 FEEDER_DECLARE(feeder_stereotomono24, 0, NULL);
1149
1150 static struct pcm_feederdesc feeder_stereotomono32_desc[] = {
1151 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE, 0},
1152 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE, 0},
1153 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE, 0},
1154 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE, 0},
1155 {0, 0, 0, 0},
1156 };
1157 static kobj_method_t feeder_stereotomono32_methods[] = {
1158 KOBJMETHOD(feeder_init, feed_stereotomono_init),
1159 KOBJMETHOD(feeder_feed, feed_stereotomono),
1160 {0, 0}
1161 };
1162 FEEDER_DECLARE(feeder_stereotomono32, 0, NULL);
1163 /*
1164 * Channel conversion (stereo -> mono) end
1165 */
1166
1167 /*
1168 * Sign conversion
1169 */
1170 static int
1171 feed_sign(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1172 uint32_t count, void *source)
1173 {
1174 int i, j, bps, ofs;
1175
1176 bps = (int)((intptr_t)f->data);
1177 if (count < bps)
1178 return (0);
1179
1180 i = FEEDER_FEED(f->source, c, b, count - (count % bps), source);
1181 if (i < bps)
1182 return (0);
1183
1184 i -= i % bps;
1185 j = i;
1186 ofs = (f->desc->in & AFMT_BIGENDIAN) ? bps : 1;
1187
1188 do {
1189 b[i - ofs] ^= 0x80;
1190 i -= bps;
1191 } while (i != 0);
1192
1193 return (j);
1194 }
1195 static struct pcm_feederdesc feeder_sign8_desc[] = {
1196 {FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
1197 {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
1198 {FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
1199 {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
1200 {0, 0, 0, 0},
1201 };
1202 static kobj_method_t feeder_sign8_methods[] = {
1203 KOBJMETHOD(feeder_feed, feed_sign),
1204 {0, 0}
1205 };
1206 FEEDER_DECLARE(feeder_sign8, 0, (void *)PCM_8_BPS);
1207
1208 static struct pcm_feederdesc feeder_sign16_desc[] = {
1209 {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
1210 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
1211 {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
1212 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
1213 {FEEDER_FMT, AFMT_U16_BE, AFMT_S16_BE, 0},
1214 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
1215 {FEEDER_FMT, AFMT_S16_BE, AFMT_U16_BE, 0},
1216 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
1217 {0, 0, 0, 0},
1218 };
1219 static kobj_method_t feeder_sign16_methods[] = {
1220 KOBJMETHOD(feeder_feed, feed_sign),
1221 {0, 0}
1222 };
1223 FEEDER_DECLARE(feeder_sign16, 0, (void *)PCM_16_BPS);
1224
1225 static struct pcm_feederdesc feeder_sign24_desc[] = {
1226 {FEEDER_FMT, AFMT_U24_LE, AFMT_S24_LE, 0},
1227 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
1228 {FEEDER_FMT, AFMT_S24_LE, AFMT_U24_LE, 0},
1229 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
1230 {FEEDER_FMT, AFMT_U24_BE, AFMT_S24_BE, 0},
1231 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
1232 {FEEDER_FMT, AFMT_S24_BE, AFMT_U24_BE, 0},
1233 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
1234 {0, 0, 0, 0},
1235 };
1236 static kobj_method_t feeder_sign24_methods[] = {
1237 KOBJMETHOD(feeder_feed, feed_sign),
1238 {0, 0}
1239 };
1240 FEEDER_DECLARE(feeder_sign24, 0, (void *)PCM_24_BPS);
1241
1242 static struct pcm_feederdesc feeder_sign32_desc[] = {
1243 {FEEDER_FMT, AFMT_U32_LE, AFMT_S32_LE, 0},
1244 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
1245 {FEEDER_FMT, AFMT_S32_LE, AFMT_U32_LE, 0},
1246 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
1247 {FEEDER_FMT, AFMT_U32_BE, AFMT_S32_BE, 0},
1248 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
1249 {FEEDER_FMT, AFMT_S32_BE, AFMT_U32_BE, 0},
1250 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
1251 {0, 0, 0, 0},
1252 };
1253 static kobj_method_t feeder_sign32_methods[] = {
1254 KOBJMETHOD(feeder_feed, feed_sign),
1255 {0, 0}
1256 };
1257 FEEDER_DECLARE(feeder_sign32, 0, (void *)PCM_32_BPS);
1258
1259 /*
1260 * Endian conversion
1261 */
1262 static int
1263 feed_endian(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1264 uint32_t count, void *source)
1265 {
1266 int i, j, k, bps;
1267 uint8_t *buf, v;
1268
1269 bps = (int)((intptr_t)f->data);
1270 if (count < bps)
1271 return (0);
1272
1273 k = FEEDER_FEED(f->source, c, b, count - (count % bps), source);
1274 if (k < bps)
1275 return (0);
1276
1277 k -= k % bps;
1278 j = bps >> 1;
1279 buf = b + k;
1280
1281 do {
1282 buf -= bps;
1283 i = j;
1284 do {
1285 v = buf[--i];
1286 buf[i] = buf[bps - i - 1];
1287 buf[bps - i - 1] = v;
1288 } while (i != 0);
1289 } while (buf != b);
1290
1291 return (k);
1292 }
1293 static struct pcm_feederdesc feeder_endian16_desc[] = {
1294 {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
1295 {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
1296 {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
1297 {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
1298 {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
1299 {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
1300 {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
1301 {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
1302 {0, 0, 0, 0},
1303 };
1304 static kobj_method_t feeder_endian16_methods[] = {
1305 KOBJMETHOD(feeder_feed, feed_endian),
1306 {0, 0}
1307 };
1308 FEEDER_DECLARE(feeder_endian16, 0, (void *)PCM_16_BPS);
1309
1310 static struct pcm_feederdesc feeder_endian24_desc[] = {
1311 {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_BE, 0},
1312 {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
1313 {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_BE, 0},
1314 {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
1315 {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_LE, 0},
1316 {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
1317 {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_LE, 0},
1318 {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
1319 {0, 0, 0, 0},
1320 };
1321 static kobj_method_t feeder_endian24_methods[] = {
1322 KOBJMETHOD(feeder_feed, feed_endian),
1323 {0, 0}
1324 };
1325 FEEDER_DECLARE(feeder_endian24, 0, (void *)PCM_24_BPS);
1326
1327 static struct pcm_feederdesc feeder_endian32_desc[] = {
1328 {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_BE, 0},
1329 {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
1330 {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_BE, 0},
1331 {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
1332 {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_LE, 0},
1333 {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
1334 {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_LE, 0},
1335 {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
1336 {0, 0, 0, 0},
1337 };
1338 static kobj_method_t feeder_endian32_methods[] = {
1339 KOBJMETHOD(feeder_feed, feed_endian),
1340 {0, 0}
1341 };
1342 FEEDER_DECLARE(feeder_endian32, 0, (void *)PCM_32_BPS);
1343 /*
1344 * Endian conversion end
1345 */
1346
1347 /*
1348 * L/R swap conversion
1349 */
1350 static int
1351 feed_swaplr(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1352 uint32_t count, void *source)
1353 {
1354 int i, j, bps, smpsz;
1355 uint8_t *buf, v;
1356
1357 bps = (int)((intptr_t)f->data);
1358 smpsz = bps << 1;
1359 if (count < smpsz)
1360 return (0);
1361
1362 j = FEEDER_FEED(f->source, c, b, count - (count % smpsz), source);
1363 if (j < smpsz)
1364 return (0);
1365
1366 j -= j % smpsz;
1367 buf = b + j;
1368
1369 do {
1370 buf -= smpsz;
1371 i = bps;
1372 do {
1373 v = buf[--i];
1374 buf[i] = buf[bps + i];
1375 buf[bps + i] = v;
1376 } while (i != 0);
1377 } while (buf != b);
1378
1379 return (j);
1380 }
1381
1382 static struct pcm_feederdesc feeder_swaplr8_desc[] = {
1383 {FEEDER_SWAPLR, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
1384 {FEEDER_SWAPLR, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
1385 {FEEDER_SWAPLR, AFMT_A_LAW | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
1386 {FEEDER_SWAPLR, AFMT_MU_LAW | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
1387 {0, 0, 0, 0},
1388 };
1389 static kobj_method_t feeder_swaplr8_methods[] = {
1390 KOBJMETHOD(feeder_feed, feed_swaplr),
1391 {0, 0}
1392 };
1393 FEEDER_DECLARE(feeder_swaplr8, -1, (void *)PCM_8_BPS);
1394
1395 static struct pcm_feederdesc feeder_swaplr16_desc[] = {
1396 {FEEDER_SWAPLR, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
1397 {FEEDER_SWAPLR, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
1398 {FEEDER_SWAPLR, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
1399 {FEEDER_SWAPLR, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
1400 {0, 0, 0, 0},
1401 };
1402 static kobj_method_t feeder_swaplr16_methods[] = {
1403 KOBJMETHOD(feeder_feed, feed_swaplr),
1404 {0, 0}
1405 };
1406 FEEDER_DECLARE(feeder_swaplr16, -1, (void *)PCM_16_BPS);
1407
1408 static struct pcm_feederdesc feeder_swaplr24_desc[] = {
1409 {FEEDER_SWAPLR, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
1410 {FEEDER_SWAPLR, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
1411 {FEEDER_SWAPLR, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
1412 {FEEDER_SWAPLR, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
1413 {0, 0, 0, 0},
1414 };
1415 static kobj_method_t feeder_swaplr24_methods[] = {
1416 KOBJMETHOD(feeder_feed, feed_swaplr),
1417 {0, 0}
1418 };
1419 FEEDER_DECLARE(feeder_swaplr24, -1, (void *)PCM_24_BPS);
1420
1421 static struct pcm_feederdesc feeder_swaplr32_desc[] = {
1422 {FEEDER_SWAPLR, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
1423 {FEEDER_SWAPLR, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
1424 {FEEDER_SWAPLR, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
1425 {FEEDER_SWAPLR, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
1426 {0, 0, 0, 0},
1427 };
1428 static kobj_method_t feeder_swaplr32_methods[] = {
1429 KOBJMETHOD(feeder_feed, feed_swaplr),
1430 {0, 0}
1431 };
1432 FEEDER_DECLARE(feeder_swaplr32, -1, (void *)PCM_32_BPS);
1433 /*
1434 * L/R swap conversion end
1435 */
Cache object: 823747e30e65ce5006f9c9990e5ee673
|