Merge branches 'hammer2' and 'master' of ssh://crater.dragonflybsd.org/repository...
[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_WAITOK|M_ZERO);
328         return 0;
329 }
330
331 static int
332 feed_common_free(struct pcm_feeder *f)
333 {
334         if (f->data)
335                 kfree(f->data, M_FMTFEEDER);
336         f->data = NULL;
337         return 0;
338 }
339
340 /*
341  * Bit conversion
342  */
343 static int
344 feed_8to16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
345                         uint32_t count, void *source)
346 {
347         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
348         
349         i = k;
350         k <<= 1;
351         j = k;
352         while (i > 0) {
353                 b[--j] = b[--i];
354                 b[--j] = 0;
355         }
356         return k;
357 }
358 static struct pcm_feederdesc feeder_8to16le_desc[] = {
359         {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
360         {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
361         {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
362         {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
363         {0, 0, 0, 0},
364 };
365 static kobj_method_t feeder_8to16le_methods[] = {
366         KOBJMETHOD(feeder_feed, feed_8to16le),
367         {0, 0}
368 };
369 FEEDER_DECLARE(feeder_8to16le, 0, NULL);
370
371 static int
372 feed_16leto8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
373                         uint32_t count, void *source)
374 {
375         int i, j, k;
376         uint8_t *src = (uint8_t *)f->data;
377         
378         k = count << 1;
379         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
380         if (k < 2) {
381                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
382                                 __func__, k);
383                 return 0;
384         }
385         FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
386         FMT_ALIGNBYTE(k &= ~1);
387         i = k;
388         j = k >> 1;
389         while (i > 0) {
390                 b[--j] = src[--i];
391                 i--;
392         }
393         return k >> 1;
394 }
395 static struct pcm_feederdesc feeder_16leto8_desc[] = {
396         {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
397         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
398         {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
399         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
400         {0, 0, 0, 0},
401 };
402 static kobj_method_t feeder_16leto8_methods[] = {
403         KOBJMETHOD(feeder_init, feed_common_init),
404         KOBJMETHOD(feeder_free, feed_common_free),
405         KOBJMETHOD(feeder_feed, feed_16leto8),
406         {0, 0}
407 };
408 FEEDER_DECLARE(feeder_16leto8, 0, NULL);
409
410 static int
411 feed_16leto24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
412                         uint32_t count, void *source)
413 {
414         int i, j, k;
415
416         k = (count / 3) << 1;
417         k = FEEDER_FEED(f->source, c, b, k, source);
418         if (k < 2) {
419                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
420                                 __func__, k);
421                 return 0;
422         }
423         FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
424         FMT_ALIGNBYTE(k &= ~1);
425         i = k;
426         j = (k >> 1) * 3;
427         k = j;
428         while (i > 0) {
429                 b[--j] = b[--i];
430                 b[--j] = b[--i];
431                 b[--j] = 0;
432         }
433         return k;
434 }
435 static struct pcm_feederdesc feeder_16leto24le_desc[] = {
436         {FEEDER_FMT, AFMT_U16_LE, AFMT_U24_LE, 0},
437         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
438         {FEEDER_FMT, AFMT_S16_LE, AFMT_S24_LE, 0},
439         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
440         {0, 0, 0, 0},
441 };
442 static kobj_method_t feeder_16leto24le_methods[] = {
443         KOBJMETHOD(feeder_feed, feed_16leto24le),
444         {0, 0}
445 };
446 FEEDER_DECLARE(feeder_16leto24le, 0, NULL);
447
448 static int
449 feed_24leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
450                         uint32_t count, void *source)
451 {
452         int i, j, k;
453         uint8_t *src = (uint8_t *)f->data;
454
455         k = (count * 3) >> 1;
456         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
457         if (k < 3) {
458                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
459                                 __func__, k);
460                 return 0;
461         }
462         FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.\n", __func__);
463         FMT_ALIGNBYTE(k -= k % 3);
464         i = (k / 3) << 1;
465         j = i;
466         while (i > 0) {
467                 b[--i] = src[--k];
468                 b[--i] = src[--k];
469                 k--;
470         }
471         return j;
472 }
473 static struct pcm_feederdesc feeder_24leto16le_desc[] = {
474         {FEEDER_FMT, AFMT_U24_LE, AFMT_U16_LE, 0},
475         {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
476         {FEEDER_FMT, AFMT_S24_LE, AFMT_S16_LE, 0},
477         {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
478         {0, 0, 0, 0},
479 };
480 static kobj_method_t feeder_24leto16le_methods[] = {
481         KOBJMETHOD(feeder_init, feed_common_init),
482         KOBJMETHOD(feeder_free, feed_common_free),
483         KOBJMETHOD(feeder_feed, feed_24leto16le),
484         {0, 0}
485 };
486 FEEDER_DECLARE(feeder_24leto16le, 1, NULL);
487
488 static int
489 feed_16leto32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
490                         uint32_t count, void *source)
491 {
492         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
493         if (k < 2) {
494                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
495                                 __func__, k);
496                 return 0;
497         }
498         FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
499         FMT_ALIGNBYTE(k &= ~1);
500         i = k;
501         j = k << 1;
502         k = j;
503         while (i > 0) {
504                 b[--j] = b[--i];
505                 b[--j] = b[--i];
506                 b[--j] = 0;
507                 b[--j] = 0;
508         }
509         return k;
510 }
511 static struct pcm_feederdesc feeder_16leto32le_desc[] = {
512         {FEEDER_FMT, AFMT_U16_LE, AFMT_U32_LE, 0},
513         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
514         {FEEDER_FMT, AFMT_S16_LE, AFMT_S32_LE, 0},
515         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
516         {0, 0, 0, 0},
517 };
518 static kobj_method_t feeder_16leto32le_methods[] = {
519         KOBJMETHOD(feeder_feed, feed_16leto32le),
520         {0, 0}
521 };
522 FEEDER_DECLARE(feeder_16leto32le, 0, NULL);
523
524 static int
525 feed_32leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
526                         uint32_t count, void *source)
527 {
528         int i, j, k;
529         uint8_t *src = (uint8_t *)f->data;
530
531         k = count << 1;
532         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
533         if (k < 4) {
534                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
535                                 __func__, k);
536                 return 0;
537         }
538         FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.\n", __func__);
539         FMT_ALIGNBYTE(k &= ~3);
540         i = k;
541         k >>= 1;
542         j = k;
543         while (i > 0) {
544                 b[--j] = src[--i];
545                 b[--j] = src[--i];
546                 i -= 2;
547         }
548         return k;
549 }
550 static struct pcm_feederdesc feeder_32leto16le_desc[] = {
551         {FEEDER_FMT, AFMT_U32_LE, AFMT_U16_LE, 0},
552         {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
553         {FEEDER_FMT, AFMT_S32_LE, AFMT_S16_LE, 0},
554         {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
555         {0, 0, 0, 0},
556 };
557 static kobj_method_t feeder_32leto16le_methods[] = {
558         KOBJMETHOD(feeder_init, feed_common_init),
559         KOBJMETHOD(feeder_free, feed_common_free),
560         KOBJMETHOD(feeder_feed, feed_32leto16le),
561         {0, 0}
562 };
563 FEEDER_DECLARE(feeder_32leto16le, 1, NULL);
564 /*
565  * Bit conversion end
566  */
567
568 /*
569  * Channel conversion (mono -> stereo)
570  */
571 static int
572 feed_monotostereo8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
573                         uint32_t count, void *source)
574 {
575         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
576
577         i = k;
578         j = k << 1;
579         while (i > 0) {
580                 b[--j] = b[--i];
581                 b[--j] = b[i];
582         }
583         return k << 1;
584 }
585 static struct pcm_feederdesc feeder_monotostereo8_desc[] = {
586         {FEEDER_FMT, AFMT_U8, AFMT_U8|AFMT_STEREO, 0},
587         {FEEDER_FMT, AFMT_S8, AFMT_S8|AFMT_STEREO, 0},
588         {0, 0, 0, 0},
589 };
590 static kobj_method_t feeder_monotostereo8_methods[] = {
591         KOBJMETHOD(feeder_feed, feed_monotostereo8),
592         {0, 0}
593 };
594 FEEDER_DECLARE(feeder_monotostereo8, 0, NULL);
595
596 static int
597 feed_monotostereo16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
598                         uint32_t count, void *source)
599 {
600         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
601         uint8_t l, m;
602
603         if (k < 2) {
604                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
605                                 __func__, k);
606                 return 0;
607         }
608         FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.\n", __func__);
609         FMT_ALIGNBYTE(k &= ~1);
610         i = k;
611         j = k << 1;
612         while (i > 0) {
613                 l = b[--i];
614                 m = b[--i];
615                 b[--j] = l;
616                 b[--j] = m;
617                 b[--j] = l;
618                 b[--j] = m;
619         }
620         return k << 1;
621 }
622 static struct pcm_feederdesc feeder_monotostereo16_desc[] = {
623         {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE|AFMT_STEREO, 0},
624         {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE|AFMT_STEREO, 0},
625         {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE|AFMT_STEREO, 0},
626         {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE|AFMT_STEREO, 0},
627         {0, 0, 0, 0},
628 };
629 static kobj_method_t feeder_monotostereo16_methods[] = {
630         KOBJMETHOD(feeder_feed, feed_monotostereo16),
631         {0, 0}
632 };
633 FEEDER_DECLARE(feeder_monotostereo16, 0, NULL);
634
635 static int
636 feed_monotostereo24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
637                         uint32_t count, void *source)
638 {
639         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
640         uint8_t l, m, n;
641
642         if (k < 3) {
643                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
644                                 __func__, k);
645                 return 0;
646         }
647         FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.\n", __func__);
648         FMT_ALIGNBYTE(k -= k % 3);
649         i = k;
650         j = k << 1;
651         while (i > 0) {
652                 l = b[--i];
653                 m = b[--i];
654                 n = b[--i];
655                 b[--j] = l;
656                 b[--j] = m;
657                 b[--j] = n;
658                 b[--j] = l;
659                 b[--j] = m;
660                 b[--j] = n;
661         }
662         return k << 1;
663 }
664 static struct pcm_feederdesc feeder_monotostereo24_desc[] = {
665         {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_LE|AFMT_STEREO, 0},
666         {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_LE|AFMT_STEREO, 0},
667         {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_BE|AFMT_STEREO, 0},
668         {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_BE|AFMT_STEREO, 0},
669         {0, 0, 0, 0},
670 };
671 static kobj_method_t feeder_monotostereo24_methods[] = {
672         KOBJMETHOD(feeder_feed, feed_monotostereo24),
673         {0, 0}
674 };
675 FEEDER_DECLARE(feeder_monotostereo24, 0, NULL);
676
677 static int
678 feed_monotostereo32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
679                         uint32_t count, void *source)
680 {
681         int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
682         uint8_t l, m, n, o;
683
684         if (k < 4) {
685                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
686                                 __func__, k);
687                 return 0;
688         }
689         FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.\n", __func__);
690         FMT_ALIGNBYTE(k &= ~3);
691         i = k;
692         j = k << 1;
693         while (i > 0) {
694                 l = b[--i];
695                 m = b[--i];
696                 n = b[--i];
697                 o = b[--i];
698                 b[--j] = l;
699                 b[--j] = m;
700                 b[--j] = n;
701                 b[--j] = o;
702                 b[--j] = l;
703                 b[--j] = m;
704                 b[--j] = n;
705                 b[--j] = o;
706         }
707         return k << 1;
708 }
709 static struct pcm_feederdesc feeder_monotostereo32_desc[] = {
710         {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_LE|AFMT_STEREO, 0},
711         {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_LE|AFMT_STEREO, 0},
712         {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_BE|AFMT_STEREO, 0},
713         {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_BE|AFMT_STEREO, 0},
714         {0, 0, 0, 0},
715 };
716 static kobj_method_t feeder_monotostereo32_methods[] = {
717         KOBJMETHOD(feeder_feed, feed_monotostereo32),
718         {0, 0}
719 };
720 FEEDER_DECLARE(feeder_monotostereo32, 0, NULL);
721 /*
722  * Channel conversion (mono -> stereo) end
723  */
724
725 /*
726  * Channel conversion (stereo -> mono)
727  */
728 static int
729 feed_stereotomono8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
730                         uint32_t count, void *source)
731 {
732         int i, j, k;
733         uint8_t *src = (uint8_t *)f->data;
734
735         k = count << 1;
736         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
737         if (k < 2) {
738                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
739                                 __func__, k);
740                 return 0;
741         }
742         FMT_TEST(k & 1, "%s: Bytes not 8bit (stereo) aligned.\n", __func__);
743         FMT_ALIGNBYTE(k &= ~1);
744         i = k >> 1;
745         j = i;
746         while (i > 0) {
747                 k--;
748                 b[--i] = src[--k];
749         }
750         return j;
751 }
752 static struct pcm_feederdesc feeder_stereotomono8_desc[] = {
753         {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U8, 0},
754         {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S8, 0},
755         {0, 0, 0, 0},
756 };
757 static kobj_method_t feeder_stereotomono8_methods[] = {
758         KOBJMETHOD(feeder_init, feed_common_init),
759         KOBJMETHOD(feeder_free, feed_common_free),
760         KOBJMETHOD(feeder_feed, feed_stereotomono8),
761         {0, 0}
762 };
763 FEEDER_DECLARE(feeder_stereotomono8, 0, NULL);
764
765 static int
766 feed_stereotomono16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
767                         uint32_t count, void *source)
768 {
769         int i, j, k;
770         uint8_t *src = (uint8_t *)f->data;
771
772         k = count << 1;
773         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
774         if (k < 4) {
775                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
776                                 __func__, k);
777                 return 0;
778         }
779         FMT_TEST(k & 3, "%s: Bytes not 16bit (stereo) aligned.\n", __func__);
780         FMT_ALIGNBYTE(k &= ~3);
781         i = k >> 1;
782         j = i;
783         while (i > 0) {
784                 k -= 2;
785                 b[--i] = src[--k];
786                 b[--i] = src[--k];
787         }
788         return j;
789 }
790 static struct pcm_feederdesc feeder_stereotomono16_desc[] = {
791         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_LE, 0},
792         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_LE, 0},
793         {FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_BE, 0},
794         {FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_BE, 0},
795         {0, 0, 0, 0},
796 };
797 static kobj_method_t feeder_stereotomono16_methods[] = {
798         KOBJMETHOD(feeder_init, feed_common_init),
799         KOBJMETHOD(feeder_free, feed_common_free),
800         KOBJMETHOD(feeder_feed, feed_stereotomono16),
801         {0, 0}
802 };
803 FEEDER_DECLARE(feeder_stereotomono16, 0, NULL);
804
805 static int
806 feed_stereotomono24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
807                         uint32_t count, void *source)
808 {
809         int i, j, k;
810         uint8_t *src = (uint8_t *)f->data;
811
812         k = count << 1;
813         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
814         if (k < 6) {
815                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
816                                 __func__, k);
817                 return 0;
818         }
819         FMT_TEST(k % 6, "%s: Bytes not 24bit (stereo) aligned.\n", __func__);
820         FMT_ALIGNBYTE(k -= k % 6);
821         i = k >> 1;
822         j = i;
823         while (i > 0) {
824                 k -= 3;
825                 b[--i] = src[--k];
826                 b[--i] = src[--k];
827                 b[--i] = src[--k];
828         }
829         return j;
830 }
831 static struct pcm_feederdesc feeder_stereotomono24_desc[] = {
832         {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_LE, 0},
833         {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_LE, 0},
834         {FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_BE, 0},
835         {FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_BE, 0},
836         {0, 0, 0, 0},
837 };
838 static kobj_method_t feeder_stereotomono24_methods[] = {
839         KOBJMETHOD(feeder_init, feed_common_init),
840         KOBJMETHOD(feeder_free, feed_common_free),
841         KOBJMETHOD(feeder_feed, feed_stereotomono24),
842         {0, 0}
843 };
844 FEEDER_DECLARE(feeder_stereotomono24, 0, NULL);
845
846 static int
847 feed_stereotomono32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
848                         uint32_t count, void *source)
849 {
850         int i, j, k;
851         uint8_t *src = (uint8_t *)f->data;
852
853         k = count << 1;
854         k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
855         if (k < 8) {
856                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
857                                 __func__, k);
858                 return 0;
859         }
860         FMT_TEST(k & 7, "%s: Bytes not 32bit (stereo) aligned.\n", __func__);
861         FMT_ALIGNBYTE(k &= ~7);
862         i = k >> 1;
863         j = i;
864         while (i > 0) {
865                 k -= 4;
866                 b[--i] = src[--k];
867                 b[--i] = src[--k];
868                 b[--i] = src[--k];
869                 b[--i] = src[--k];
870         }
871         return j;
872 }
873 static struct pcm_feederdesc feeder_stereotomono32_desc[] = {
874         {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_LE, 0},
875         {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_LE, 0},
876         {FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_BE, 0},
877         {FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_BE, 0},
878         {0, 0, 0, 0},
879 };
880 static kobj_method_t feeder_stereotomono32_methods[] = {
881         KOBJMETHOD(feeder_init, feed_common_init),
882         KOBJMETHOD(feeder_free, feed_common_free),
883         KOBJMETHOD(feeder_feed, feed_stereotomono32),
884         {0, 0}
885 };
886 FEEDER_DECLARE(feeder_stereotomono32, 0, NULL);
887 /*
888  * Channel conversion (stereo -> mono) end
889  */
890
891 /*
892  * Sign conversion
893  */
894 static int
895 feed_sign8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
896                         uint32_t count, void *source)
897 {
898         int i, j = FEEDER_FEED(f->source, c, b, count, source);
899
900         i = j;
901         while (i > 0)
902                 b[--i] ^= 0x80;
903         return j;
904 }
905 static struct pcm_feederdesc feeder_sign8_desc[] = {
906         {FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
907         {FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
908         {FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
909         {FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
910         {0, 0, 0, 0},
911 };
912 static kobj_method_t feeder_sign8_methods[] = {
913         KOBJMETHOD(feeder_feed, feed_sign8),
914         {0, 0}
915 };
916 FEEDER_DECLARE(feeder_sign8, 0, NULL);
917
918 static int
919 feed_sign16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
920                         uint32_t count, void *source)
921 {
922         int i, j = FEEDER_FEED(f->source, c, b, count, source);
923
924         if (j < 2) {
925                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
926                                 __func__, j);
927                 return 0;
928         }
929         FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.\n", __func__);
930         FMT_ALIGNBYTE(j &= ~1);
931         i = j;
932         while (i > 0) {
933                 b[--i] ^= 0x80;
934                 i--;
935         }
936         return j;
937 }
938 static struct pcm_feederdesc feeder_sign16le_desc[] = {
939         {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
940         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
941         {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
942         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
943         {0, 0, 0, 0},
944 };
945 static kobj_method_t feeder_sign16le_methods[] = {
946         KOBJMETHOD(feeder_feed, feed_sign16le),
947         {0, 0}
948 };
949 FEEDER_DECLARE(feeder_sign16le, 0, NULL);
950
951 static int
952 feed_sign24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
953                         uint32_t count, void *source)
954 {
955         int i, j = FEEDER_FEED(f->source, c, b, count, source);
956
957         if (j < 3) {
958                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
959                                 __func__, j);
960                 return 0;
961         }
962         FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.\n", __func__);
963         FMT_ALIGNBYTE(j -= j % 3);
964         i = j;
965         while (i > 0) {
966                 b[--i] ^= 0x80;
967                 i -= 2;
968         }
969         return j;
970 }
971 static struct pcm_feederdesc feeder_sign24le_desc[] = {
972         {FEEDER_FMT, AFMT_U24_LE, AFMT_S24_LE, 0},
973         {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
974         {FEEDER_FMT, AFMT_S24_LE, AFMT_U24_LE, 0},
975         {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
976         {0, 0, 0, 0},
977 };
978 static kobj_method_t feeder_sign24le_methods[] = {
979         KOBJMETHOD(feeder_feed, feed_sign24le),
980         {0, 0}
981 };
982 FEEDER_DECLARE(feeder_sign24le, 0, NULL);
983
984 static int
985 feed_sign32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
986                         uint32_t count, void *source)
987 {
988         int i, j = FEEDER_FEED(f->source, c, b, count, source);
989
990         if (j < 4) {
991                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
992                                 __func__, j);
993                 return 0;
994         }
995         FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.\n", __func__);
996         FMT_ALIGNBYTE(j &= ~3);
997         i = j;
998         while (i > 0) {
999                 b[--i] ^= 0x80;
1000                 i -= 3;
1001         }
1002         return j;
1003 }
1004 static struct pcm_feederdesc feeder_sign32le_desc[] = {
1005         {FEEDER_FMT, AFMT_U32_LE, AFMT_S32_LE, 0},
1006         {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
1007         {FEEDER_FMT, AFMT_S32_LE, AFMT_U32_LE, 0},
1008         {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
1009         {0, 0, 0, 0},
1010 };
1011 static kobj_method_t feeder_sign32le_methods[] = {
1012         KOBJMETHOD(feeder_feed, feed_sign32le),
1013         {0, 0}
1014 };
1015 FEEDER_DECLARE(feeder_sign32le, 0, NULL);
1016 /*
1017  * Sign conversion end.
1018  */
1019
1020 /*
1021  * Endian conversion.
1022  */
1023 static int
1024 feed_endian16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1025                         uint32_t count, void *source)
1026 {
1027         int i, j = FEEDER_FEED(f->source, c, b, count, source);
1028         uint8_t v;
1029
1030         if (j < 2) {
1031                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1032                                 __func__, j);
1033                 return 0;
1034         }
1035         FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.\n", __func__);
1036         FMT_ALIGNBYTE(j &= ~1);
1037         i = j;
1038         while (i > 0) {
1039                 v = b[--i];
1040                 b[i] = b[i - 1];
1041                 b[--i] = v;
1042         }
1043         return j;
1044 }
1045 static struct pcm_feederdesc feeder_endian16_desc[] = {
1046         {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
1047         {FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_BE|AFMT_STEREO, 0},
1048         {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
1049         {FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_BE|AFMT_STEREO, 0},
1050         {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
1051         {FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
1052         {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
1053         {FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
1054         {0, 0, 0, 0},
1055 };
1056 static kobj_method_t feeder_endian16_methods[] = {
1057         KOBJMETHOD(feeder_feed, feed_endian16),
1058         {0, 0}
1059 };
1060 FEEDER_DECLARE(feeder_endian16, 0, NULL);
1061
1062 static int
1063 feed_endian24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1064                         uint32_t count, void *source)
1065 {
1066         int i, j = FEEDER_FEED(f->source, c, b, count, source);
1067         uint8_t v;
1068
1069         if (j < 3) {
1070                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1071                                 __func__, j);
1072                 return 0;
1073         }
1074         FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.\n", __func__);
1075         FMT_ALIGNBYTE(j -= j % 3);
1076         i = j;
1077         while (i > 0) {
1078                 v = b[--i];
1079                 b[i] = b[i - 2];
1080                 b[i -= 2] = v;
1081         }
1082         return j;
1083 }
1084 static struct pcm_feederdesc feeder_endian24_desc[] = {
1085         {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_BE, 0},
1086         {FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_BE|AFMT_STEREO, 0},
1087         {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_BE, 0},
1088         {FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_BE|AFMT_STEREO, 0},
1089         {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_LE, 0},
1090         {FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
1091         {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_LE, 0},
1092         {FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
1093         {0, 0, 0, 0},
1094 };
1095 static kobj_method_t feeder_endian24_methods[] = {
1096         KOBJMETHOD(feeder_feed, feed_endian24),
1097         {0, 0}
1098 };
1099 FEEDER_DECLARE(feeder_endian24, 0, NULL);
1100
1101 static int
1102 feed_endian32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
1103                         uint32_t count, void *source)
1104 {
1105         int i, j = FEEDER_FEED(f->source, c, b, count, source);
1106         uint8_t l, m;
1107
1108         if (j < 4) {
1109                 FMT_TRACE("%s: Not enough data (Got: %d bytes)\n",
1110                                 __func__, j);
1111                 return 0;
1112         }
1113         FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.\n", __func__);
1114         FMT_ALIGNBYTE(j &= ~3);
1115         i = j;
1116         while (i > 0) {
1117                 l = b[--i];
1118                 m = b[--i];
1119                 b[i] = b[i - 1];
1120                 b[i + 1] = b[i - 2];
1121                 b[--i] = m;
1122                 b[--i] = l;
1123         }
1124         return j;
1125 }
1126 static struct pcm_feederdesc feeder_endian32_desc[] = {
1127         {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_BE, 0},
1128         {FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_BE|AFMT_STEREO, 0},
1129         {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_BE, 0},
1130         {FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_BE|AFMT_STEREO, 0},
1131         {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_LE, 0},
1132         {FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
1133         {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_LE, 0},
1134         {FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
1135         {0, 0, 0, 0},
1136 };
1137 static kobj_method_t feeder_endian32_methods[] = {
1138         KOBJMETHOD(feeder_feed, feed_endian32),
1139         {0, 0}
1140 };
1141 FEEDER_DECLARE(feeder_endian32, 0, NULL);
1142 /*
1143  * Endian conversion end
1144  */