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