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