The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pcm/feeder_fmt.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 24398da15b7f3dbdf7505fe97aa94298


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.