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