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/auconv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: auconv.c,v 1.21 2008/03/04 18:23:44 cube Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by the Computer Systems
   18  *      Engineering Group at Lawrence Berkeley Laboratory.
   19  * 4. Neither the name of the University nor of the Laboratory may be used
   20  *    to endorse or promote products derived from this software without
   21  *    specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.21 2008/03/04 18:23:44 cube Exp $");
   39 
   40 #include <sys/types.h>
   41 #include <sys/audioio.h>
   42 #include <sys/device.h>
   43 #include <sys/errno.h>
   44 #include <sys/malloc.h>
   45 #include <sys/null.h>
   46 #include <sys/systm.h>
   47 #include <dev/audio_if.h>
   48 #include <dev/auconv.h>
   49 #include <dev/mulaw.h>
   50 #include <machine/limits.h>
   51 #ifndef _KERNEL
   52 #include <stddef.h>
   53 #include <stdio.h>
   54 #include <stdlib.h>
   55 #include <string.h>
   56 #include <stdbool.h>
   57 #endif
   58 
   59 #include <aurateconv.h>         /* generated by config(8) */
   60 #include <mulaw.h>              /* generated by config(8) */
   61 
   62 /* #define AUCONV_DEBUG */
   63 #ifdef AUCONV_DEBUG
   64 # define DPRINTF(x)     printf x
   65 #else
   66 # define DPRINTF(x)
   67 #endif
   68 
   69 #if NAURATECONV > 0
   70 static int auconv_rateconv_supportable(u_int, u_int, u_int);
   71 static int auconv_rateconv_check_channels(const struct audio_format *, int,
   72                                           int, const audio_params_t *,
   73                                           stream_filter_list_t *);
   74 static int auconv_rateconv_check_rates(const struct audio_format *, int,
   75                                        int, const audio_params_t *,
   76                                        audio_params_t *,
   77                                        stream_filter_list_t *);
   78 #endif
   79 #ifdef AUCONV_DEBUG
   80 static void auconv_dump_formats(const struct audio_format *, int);
   81 #endif
   82 static void auconv_dump_params(const audio_params_t *);
   83 static int auconv_exact_match(const struct audio_format *, int, int,
   84                               const struct audio_params *);
   85 static u_int auconv_normalize_encoding(u_int, u_int);
   86 static int auconv_is_supported_rate(const struct audio_format *, u_int);
   87 static int auconv_add_encoding(int, int, int, struct audio_encoding_set **,
   88                                int *);
   89 
   90 #ifdef _KERNEL
   91 #define AUCONV_MALLOC(size)     malloc(size, M_DEVBUF, M_NOWAIT)
   92 #define AUCONV_REALLOC(p, size) realloc(p, size, M_DEVBUF, M_NOWAIT)
   93 #define AUCONV_FREE(p)          free(p, M_DEVBUF)
   94 #else
   95 #define AUCONV_MALLOC(size)     malloc(size)
   96 #define AUCONV_REALLOC(p, size) realloc(p, size)
   97 #define AUCONV_FREE(p)          free(p)
   98 #endif
   99 
  100 struct audio_encoding_set {
  101         int size;
  102         audio_encoding_t items[1];
  103 };
  104 #define ENCODING_SET_SIZE(n)    (offsetof(struct audio_encoding_set, items) \
  105                                 + sizeof(audio_encoding_t) * (n))
  106 
  107 struct conv_table {
  108         u_int encoding;
  109         u_int validbits;
  110         u_int precision;
  111         stream_filter_factory_t *play_conv;
  112         stream_filter_factory_t *rec_conv;
  113 };
  114 /*
  115  * SLINEAR-16 or SLINEAR-24 should precede in a table because
  116  * aurateconv supports only SLINEAR.
  117  */
  118 static const struct conv_table s8_table[] = {
  119         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  120          linear8_to_linear16, linear16_to_linear8},
  121         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  122          linear8_to_linear16, linear16_to_linear8},
  123         {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
  124          change_sign8, change_sign8},
  125         {0, 0, 0, NULL, NULL}};
  126 static const struct conv_table u8_table[] = {
  127         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  128          linear8_to_linear16, linear16_to_linear8},
  129         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  130          linear8_to_linear16, linear16_to_linear8},
  131         {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
  132          change_sign8, change_sign8},
  133         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  134          linear8_to_linear16, linear16_to_linear8},
  135         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  136          linear8_to_linear16, linear16_to_linear8},
  137         {0, 0, 0, NULL, NULL}};
  138 static const struct conv_table s16le_table[] = {
  139         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  140          swap_bytes, swap_bytes},
  141         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  142          change_sign16, change_sign16},
  143         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  144          swap_bytes_change_sign16, swap_bytes_change_sign16},
  145         {0, 0, 0, NULL, NULL}};
  146 static const struct conv_table s16be_table[] = {
  147         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  148          swap_bytes, swap_bytes},
  149         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  150          change_sign16, change_sign16},
  151         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  152          swap_bytes_change_sign16, swap_bytes_change_sign16},
  153         {0, 0, 0, NULL, NULL}};
  154 static const struct conv_table u16le_table[] = {
  155         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  156          change_sign16, change_sign16},
  157         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  158          swap_bytes, swap_bytes},
  159         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  160          swap_bytes_change_sign16, swap_bytes_change_sign16},
  161         {0, 0, 0, NULL, NULL}};
  162 static const struct conv_table u16be_table[] = {
  163         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  164          change_sign16, change_sign16},
  165         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  166          swap_bytes, swap_bytes},
  167         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  168          swap_bytes_change_sign16, swap_bytes_change_sign16},
  169         {0, 0, 0, NULL, NULL}};
  170 #if NMULAW > 0
  171 static const struct conv_table mulaw_table[] = {
  172         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  173          mulaw_to_linear16, linear16_to_mulaw},
  174         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  175          mulaw_to_linear16, linear16_to_mulaw},
  176         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  177          mulaw_to_linear16, linear16_to_mulaw},
  178         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  179          mulaw_to_linear16, linear16_to_mulaw},
  180         {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
  181          mulaw_to_linear8, linear8_to_mulaw},
  182         {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
  183          mulaw_to_linear8, linear8_to_mulaw},
  184         {0, 0, 0, NULL, NULL}};
  185 static const struct conv_table alaw_table[] = {
  186         {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
  187          alaw_to_linear16, linear16_to_alaw},
  188         {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
  189          alaw_to_linear16, linear16_to_alaw},
  190         {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
  191          alaw_to_linear16, linear16_to_alaw},
  192         {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
  193          alaw_to_linear16, linear16_to_alaw},
  194         {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
  195          alaw_to_linear8, linear8_to_alaw},
  196         {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
  197          alaw_to_linear8, linear8_to_alaw},
  198         {0, 0, 0, NULL, NULL}};
  199 #endif
  200 #ifdef AUCONV_DEBUG
  201 static const char *encoding_dbg_names[] = {
  202         "none", AudioEmulaw, AudioEalaw, "pcm16",
  203         "pcm8", AudioEadpcm, AudioEslinear_le, AudioEslinear_be,
  204         AudioEulinear_le, AudioEulinear_be,
  205         AudioEslinear, AudioEulinear,
  206         AudioEmpeg_l1_stream, AudioEmpeg_l1_packets,
  207         AudioEmpeg_l1_system, AudioEmpeg_l2_stream,
  208         AudioEmpeg_l2_packets, AudioEmpeg_l2_system
  209 };
  210 #endif
  211 
  212 void
  213 stream_filter_set_fetcher(stream_filter_t *this, stream_fetcher_t *p)
  214 {
  215         this->prev = p;
  216 }
  217 
  218 void
  219 stream_filter_set_inputbuffer(stream_filter_t *this, audio_stream_t *stream)
  220 {
  221         this->src = stream;
  222 }
  223 
  224 stream_filter_t *
  225 auconv_nocontext_filter_factory(
  226         int (*fetch_to)(stream_fetcher_t *, audio_stream_t *, int))
  227 {
  228         stream_filter_t *this;
  229 
  230         this = AUCONV_MALLOC(sizeof(stream_filter_t));
  231         if (this == NULL)
  232                 return NULL;
  233         this->base.fetch_to = fetch_to;
  234         this->dtor = auconv_nocontext_filter_dtor;
  235         this->set_fetcher = stream_filter_set_fetcher;
  236         this->set_inputbuffer = stream_filter_set_inputbuffer;
  237         this->prev = NULL;
  238         this->src = NULL;
  239         return this;
  240 }
  241 
  242 void
  243 auconv_nocontext_filter_dtor(struct stream_filter *this)
  244 {
  245         if (this != NULL)
  246                 AUCONV_FREE(this);
  247 }
  248 
  249 #define DEFINE_FILTER(name)     \
  250 static int \
  251 name##_fetch_to(stream_fetcher_t *, audio_stream_t *, int); \
  252 stream_filter_t * \
  253 name(struct audio_softc *sc, const audio_params_t *from, \
  254      const audio_params_t *to) \
  255 { \
  256         return auconv_nocontext_filter_factory(name##_fetch_to); \
  257 } \
  258 static int \
  259 name##_fetch_to(stream_fetcher_t *self, audio_stream_t *dst, int max_used)
  260 
  261 DEFINE_FILTER(change_sign8)
  262 {
  263         stream_filter_t *this;
  264         int m, err;
  265 
  266         this = (stream_filter_t *)self;
  267         if ((err = this->prev->fetch_to(this->prev, this->src, max_used)))
  268                 return err;
  269         m = dst->end - dst->start;
  270         m = min(m, max_used);
  271         FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
  272                 *d = *s ^ 0x80;
  273         } FILTER_LOOP_EPILOGUE(this->src, dst);
  274         return 0;
  275 }
  276 
  277 DEFINE_FILTER(change_sign16)
  278 {
  279         stream_filter_t *this;
  280         int m, err, enc;
  281 
  282         this = (stream_filter_t *)self;
  283         max_used = (max_used + 1) & ~1; /* round up to even */
  284         if ((err = this->prev->fetch_to(this->prev, this->src, max_used)))
  285                 return err;
  286         m = (dst->end - dst->start) & ~1;
  287         m = min(m, max_used);
  288         enc = dst->param.encoding;
  289         if (enc == AUDIO_ENCODING_SLINEAR_LE
  290             || enc == AUDIO_ENCODING_ULINEAR_LE) {
  291                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
  292                         d[0] = s[0];
  293                         d[1] = s[1] ^ 0x80;
  294                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  295         } else {
  296                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
  297                         d[0] = s[0] ^ 0x80;
  298                         d[1] = s[1];
  299                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  300         }
  301         return 0;
  302 }
  303 
  304 DEFINE_FILTER(swap_bytes)
  305 {
  306         stream_filter_t *this;
  307         int m, err;
  308 
  309         this = (stream_filter_t *)self;
  310         max_used = (max_used + 1) & ~1; /* round up to even */
  311         if ((err = this->prev->fetch_to(this->prev, this->src, max_used)))
  312                 return err;
  313         m = (dst->end - dst->start) & ~1;
  314         m = min(m, max_used);
  315         FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
  316                 d[0] = s[1];
  317                 d[1] = s[0];
  318         } FILTER_LOOP_EPILOGUE(this->src, dst);
  319         return 0;
  320 }
  321 
  322 DEFINE_FILTER(swap_bytes_change_sign16)
  323 {
  324         stream_filter_t *this;
  325         int m, err, enc;
  326 
  327         this = (stream_filter_t *)self;
  328         max_used = (max_used + 1) & ~1; /* round up to even */
  329         if ((err = this->prev->fetch_to(this->prev, this->src, max_used)))
  330                 return err;
  331         m = (dst->end - dst->start) & ~1;
  332         m = min(m, max_used);
  333         enc = dst->param.encoding;
  334         if (enc == AUDIO_ENCODING_SLINEAR_LE
  335             || enc == AUDIO_ENCODING_ULINEAR_LE) {
  336                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
  337                         d[0] = s[1];
  338                         d[1] = s[0] ^ 0x80;
  339                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  340         } else {
  341                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
  342                         d[0] = s[1] ^ 0x80;
  343                         d[1] = s[0];
  344                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  345         }
  346         return 0;
  347 }
  348 
  349 DEFINE_FILTER(linear8_to_linear16)
  350 {
  351         stream_filter_t *this;
  352         int m, err, enc_dst, enc_src;
  353 
  354         this = (stream_filter_t *)self;
  355         max_used = (max_used + 1) & ~1; /* round up to even */
  356         if ((err = this->prev->fetch_to(this->prev, this->src, max_used / 2)))
  357                 return err;
  358         m = (dst->end - dst->start) & ~1;
  359         m = min(m, max_used);
  360         enc_dst = dst->param.encoding;
  361         enc_src = this->src->param.encoding;
  362         if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
  363              && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
  364             || (enc_src == AUDIO_ENCODING_ULINEAR_LE
  365                 && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
  366                 /*
  367                  * slinear8 -> slinear16_le
  368                  * ulinear8 -> ulinear16_le
  369                  */
  370                 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
  371                         d[0] = 0;
  372                         d[1] = s[0];
  373                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  374         } else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
  375                     && enc_dst == AUDIO_ENCODING_SLINEAR_BE)
  376                    || (enc_src == AUDIO_ENCODING_ULINEAR_LE
  377                        && enc_dst == AUDIO_ENCODING_ULINEAR_BE)) {
  378                 /*
  379                  * slinear8 -> slinear16_be
  380                  * ulinear8 -> ulinear16_be
  381                  */
  382                 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
  383                         d[0] = s[0];
  384                         d[1] = 0;
  385                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  386         } else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
  387                     && enc_dst == AUDIO_ENCODING_ULINEAR_LE)
  388                    || (enc_src == AUDIO_ENCODING_ULINEAR_LE
  389                        && enc_dst == AUDIO_ENCODING_SLINEAR_LE)) {
  390                 /*
  391                  * slinear8 -> ulinear16_le
  392                  * ulinear8 -> slinear16_le
  393                  */
  394                 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
  395                         d[0] = 0;
  396                         d[1] = s[0] ^ 0x80;
  397                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  398         } else {
  399                 /*
  400                  * slinear8 -> ulinear16_be
  401                  * ulinear8 -> slinear16_be
  402                  */
  403                 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
  404                         d[0] = s[0] ^ 0x80;
  405                         d[1] = 0;
  406                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  407         }
  408         return 0;
  409 }
  410 
  411 DEFINE_FILTER(linear16_to_linear8)
  412 {
  413         stream_filter_t *this;
  414         int m, err, enc_src, enc_dst;
  415 
  416         this = (stream_filter_t *)self;
  417         if ((err = this->prev->fetch_to(this->prev, this->src, max_used * 2)))
  418                 return err;
  419         m = dst->end - dst->start;
  420         m = min(m, max_used);
  421         enc_dst = dst->param.encoding;
  422         enc_src = this->src->param.encoding;
  423         if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
  424              && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
  425             || (enc_src == AUDIO_ENCODING_ULINEAR_LE
  426                 && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
  427                 /*
  428                  * slinear16_le -> slinear8
  429                  * ulinear16_le -> ulinear8
  430                  */
  431                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
  432                         d[0] = s[1];
  433                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  434         } else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
  435                     && enc_dst == AUDIO_ENCODING_ULINEAR_LE)
  436                    || (enc_src == AUDIO_ENCODING_ULINEAR_LE
  437                        && enc_dst == AUDIO_ENCODING_SLINEAR_LE)) {
  438                 /*
  439                  * slinear16_le -> ulinear8
  440                  * ulinear16_le -> slinear8
  441                  */
  442                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
  443                         d[0] = s[1] ^ 0x80;
  444                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  445         } else if ((enc_src == AUDIO_ENCODING_SLINEAR_BE
  446                     && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
  447                    || (enc_src == AUDIO_ENCODING_ULINEAR_BE
  448                        && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
  449                 /*
  450                  * slinear16_be -> slinear8
  451                  * ulinear16_be -> ulinear8
  452                  */
  453                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
  454                         d[0] = s[0];
  455                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  456         } else {
  457                 /*
  458                  * slinear16_be -> ulinear8
  459                  * ulinear16_be -> slinear8
  460                  */
  461                 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
  462                         d[0] = s[0] ^ 0x80;
  463                 } FILTER_LOOP_EPILOGUE(this->src, dst);
  464         }
  465         return 0;
  466 }
  467 
  468 /**
  469  * Set appropriate parameters in `param,' and return the index in
  470  * the hardware capability array `formats.'
  471  *
  472  * @param formats       [IN] An array of formats which a hardware can support.
  473  * @param nformats      [IN] The number of elements of the array.
  474  * @param mode          [IN] Either AUMODE_PLAY or AUMODE_RECORD.
  475  * @param param         [IN] Requested format.  param->sw_code may be set.
  476  * @param rateconv      [IN] true if aurateconv may be used.
  477  * @param list          [OUT] stream_filters required for param.
  478  * @return The index of selected audio_format entry.  -1 if the device
  479  *      can not support the specified param.
  480  */
  481 int
  482 auconv_set_converter(const struct audio_format *formats, int nformats,
  483     int mode, const audio_params_t *param, int rateconv,
  484     stream_filter_list_t *list)
  485 {
  486         audio_params_t work;
  487         const struct conv_table *table;
  488         stream_filter_factory_t *conv;
  489         int enc;
  490         int i, j;
  491 
  492 #ifdef AUCONV_DEBUG
  493         DPRINTF(("%s: ENTER rateconv=%d\n", __func__, rateconv));
  494         auconv_dump_formats(formats, nformats);
  495 #endif
  496         enc = auconv_normalize_encoding(param->encoding, param->precision);
  497 
  498         /* check support by native format */
  499         i = auconv_exact_match(formats, nformats, mode, param);
  500         if (i >= 0) {
  501                 DPRINTF(("%s: LEAVE with %d (exact)\n", __func__, i));
  502                 return i;
  503         }
  504 
  505 #if NAURATECONV > 0
  506         /* native format with aurateconv */
  507         DPRINTF(("%s: native with aurateconv\n", __func__));
  508         if (rateconv
  509             && auconv_rateconv_supportable(enc, param->precision,
  510                                            param->validbits)) {
  511                 i = auconv_rateconv_check_channels(formats, nformats,
  512                                                    mode, param, list);
  513                 if (i >= 0) {
  514                         DPRINTF(("%s: LEAVE with %d (aurateconv1)\n", __func__, i));
  515                         return i;
  516                 }
  517         }
  518 #endif
  519 
  520         /* check for emulation */
  521         DPRINTF(("%s: encoding emulation\n", __func__));
  522         table = NULL;
  523         switch (enc) {
  524         case AUDIO_ENCODING_SLINEAR_LE:
  525                 if (param->precision == 8)
  526                         table = s8_table;
  527                 else if (param->precision == 16)
  528                         table = s16le_table;
  529                 break;
  530         case AUDIO_ENCODING_SLINEAR_BE:
  531                 if (param->precision == 8)
  532                         table = s8_table;
  533                 else if (param->precision == 16)
  534                         table = s16be_table;
  535                 break;
  536         case AUDIO_ENCODING_ULINEAR_LE:
  537                 if (param->precision == 8)
  538                         table = u8_table;
  539                 else if (param->precision == 16)
  540                         table = u16le_table;
  541                 break;
  542         case AUDIO_ENCODING_ULINEAR_BE:
  543                 if (param->precision == 8)
  544                         table = u8_table;
  545                 else if (param->precision == 16)
  546                         table = u16be_table;
  547                 break;
  548 #if NMULAW > 0
  549         case AUDIO_ENCODING_ULAW:
  550                 table = mulaw_table;
  551                 break;
  552         case AUDIO_ENCODING_ALAW:
  553                 table = alaw_table;
  554                 break;
  555 #endif
  556         }
  557         if (table == NULL) {
  558                 DPRINTF(("%s: LEAVE with -1 (no-emultable)\n", __func__));
  559                 return -1;
  560         }
  561         work = *param;
  562         for (j = 0; table[j].precision != 0; j++) {
  563                 work.encoding = table[j].encoding;
  564                 work.precision = table[j].precision;
  565                 work.validbits = table[j].validbits;
  566                 i = auconv_exact_match(formats, nformats, mode, &work);
  567                 if (i >= 0) {
  568                         conv = mode == AUMODE_PLAY
  569                                 ? table[j].play_conv : table[j].rec_conv;
  570                         list->append(list, conv, &work);
  571                         DPRINTF(("%s: LEAVE with %d (emultable)\n", __func__, i));
  572                         return i;
  573                 }
  574         }
  575         /* not found */
  576 
  577 #if NAURATECONV > 0
  578         /* emulation with aurateconv */
  579         DPRINTF(("%s: encoding emulation with aurateconv\n", __func__));
  580         if (!rateconv) {
  581                 DPRINTF(("%s: LEAVE with -1 (no-rateconv)\n", __func__));
  582                 return -1;
  583         }
  584         work = *param;
  585         for (j = 0; table[j].precision != 0; j++) {
  586                 if (!auconv_rateconv_supportable(table[j].encoding,
  587                                                  table[j].precision,
  588                                                  table[j].validbits))
  589                         continue;
  590                 work.encoding = table[j].encoding;
  591                 work.precision = table[j].precision;
  592                 work.validbits = table[j].validbits;
  593                 i = auconv_rateconv_check_channels(formats, nformats,
  594                                                    mode, &work, list);
  595                 if (i >= 0) {
  596                         /* work<=>hw conversion is already registered */
  597                         conv = mode == AUMODE_PLAY
  598                                 ? table[j].play_conv : table[j].rec_conv;
  599                         /* register userland<=>work conversion */
  600                         list->append(list, conv, &work);
  601                         DPRINTF(("%s: LEAVE with %d (rateconv2)\n", __func__, i));
  602                         return i;
  603                 }
  604         }
  605 
  606 #endif
  607         DPRINTF(("%s: LEAVE with -1 (bottom)\n", __func__));
  608         return -1;
  609 }
  610 
  611 #if NAURATECONV > 0
  612 static int
  613 auconv_rateconv_supportable(u_int encoding, u_int precision, u_int validbits)
  614 {
  615         if (encoding != AUDIO_ENCODING_SLINEAR_LE
  616             && encoding != AUDIO_ENCODING_SLINEAR_BE)
  617                 return false;
  618         if (precision != 16 && precision != 24 && precision != 32)
  619                 return false;
  620         if (precision < validbits)
  621                 return false;
  622         return true;
  623 }
  624 
  625 static int
  626 auconv_rateconv_check_channels(const struct audio_format *formats, int nformats,
  627                                int mode, const audio_params_t *param,
  628                                stream_filter_list_t *list)
  629 {
  630         audio_params_t hw_param;
  631         int ind, n;
  632 
  633         hw_param = *param;
  634         /* check for the specified number of channels */
  635         ind = auconv_rateconv_check_rates(formats, nformats, mode, param,
  636                                           &hw_param, list);
  637         if (ind >= 0)
  638                 return ind;
  639 
  640         /* check for larger numbers */
  641         for (n = param->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
  642                 hw_param.channels = n;
  643                 ind = auconv_rateconv_check_rates(formats, nformats, mode,
  644                                                   param, &hw_param, list);
  645                 if (ind >= 0)
  646                         return ind;
  647         }
  648 
  649         /* check for stereo:monaural conversion */
  650         if (param->channels == 2) {
  651                 hw_param.channels = 1;
  652                 ind = auconv_rateconv_check_rates(formats, nformats, mode,
  653                                                   param, &hw_param, list);
  654                 if (ind >= 0)
  655                         return ind;
  656         }
  657         return -1;
  658 }
  659 
  660 static int
  661 auconv_rateconv_check_rates(const struct audio_format *formats, int nformats,
  662                             int mode, const audio_params_t *param,
  663                             audio_params_t *hw_param, stream_filter_list_t *list)
  664 {
  665         int ind, i, j, enc, f_enc;
  666         u_int rate, minrate, maxrate, orig_rate;;
  667 
  668         /* exact match */
  669         ind = auconv_exact_match(formats, nformats, mode, hw_param);
  670         if (ind >= 0)
  671                 goto found;
  672 
  673         /* determine min/max of specified encoding/precision/channels */
  674         minrate = UINT_MAX;
  675         maxrate = 0;
  676         enc = auconv_normalize_encoding(param->encoding,
  677                                         param->precision);
  678         for (i = 0; i < nformats; i++) {
  679                 if (!AUFMT_IS_VALID(&formats[i]))
  680                         continue;
  681                 if ((formats[i].mode & mode) == 0)
  682                         continue;
  683                 f_enc = auconv_normalize_encoding(formats[i].encoding,
  684                                                   formats[i].precision);
  685                 if (f_enc != enc)
  686                         continue;
  687                 if (formats[i].validbits != hw_param->validbits)
  688                         continue;
  689                 if (formats[i].precision != hw_param->precision)
  690                         continue;
  691                 if (formats[i].channels != hw_param->channels)
  692                         continue;
  693                 if (formats[i].frequency_type == 0) {
  694                         if (formats[i].frequency[0] < minrate)
  695                                 minrate = formats[i].frequency[0];
  696                         if (formats[i].frequency[1] > maxrate)
  697                                 maxrate = formats[i].frequency[1];
  698                 } else {
  699                         for (j = 0; j < formats[i].frequency_type; j++) {
  700                                 if (formats[i].frequency[j] < minrate)
  701                                         minrate = formats[i].frequency[j];
  702                                 if (formats[i].frequency[j] > maxrate)
  703                                         maxrate = formats[i].frequency[j];
  704                         }
  705                 }
  706         }
  707         if (maxrate == 0)
  708                 return -1;
  709 
  710         /* try multiples of sample_rate */
  711         orig_rate = hw_param->sample_rate;
  712         for (i = 2; (rate = param->sample_rate * i) <= maxrate; i++) {
  713                 hw_param->sample_rate = rate;
  714                 ind = auconv_exact_match(formats, nformats, mode, hw_param);
  715                 if (ind >= 0)
  716                         goto found;
  717         }
  718 
  719         hw_param->sample_rate = param->sample_rate >= minrate
  720                 ? maxrate : minrate;
  721         ind = auconv_exact_match(formats, nformats, mode, hw_param);
  722         if (ind >= 0)
  723                 goto found;
  724         hw_param->sample_rate = orig_rate;
  725         return -1;
  726 
  727  found:
  728         list->append(list, aurateconv, hw_param);
  729         return ind;
  730 }
  731 #endif /* NAURATECONV */
  732 
  733 #ifdef AUCONV_DEBUG
  734 static void
  735 auconv_dump_formats(const struct audio_format *formats, int nformats)
  736 {
  737         const struct audio_format *f;
  738         int i, j;
  739 
  740         for (i = 0; i < nformats; i++) {
  741                 f = &formats[i];
  742                 printf("[%2d]: mode=", i);
  743                 if (!AUFMT_IS_VALID(f)) {
  744                         printf("INVALID");
  745                 } else if (f->mode == AUMODE_PLAY) {
  746                         printf("PLAY");
  747                 } else if (f->mode == AUMODE_RECORD) {
  748                         printf("RECORD");
  749                 } else if (f->mode == (AUMODE_PLAY | AUMODE_RECORD)) {
  750                         printf("PLAY|RECORD");
  751                 } else {
  752                         printf("0x%x", f->mode);
  753                 }
  754                 printf(" enc=%s", encoding_dbg_names[f->encoding]);
  755                 printf(" %u/%ubit", f->validbits, f->precision);
  756                 printf(" %uch", f->channels);
  757 
  758                 printf(" channel_mask=");
  759                 if (f->channel_mask == AUFMT_MONAURAL) {
  760                         printf("MONAURAL");
  761                 } else if (f->channel_mask == AUFMT_STEREO) {
  762                         printf("STEREO");
  763                 } else if (f->channel_mask == AUFMT_SURROUND4) {
  764                         printf("SURROUND4");
  765                 } else if (f->channel_mask == AUFMT_DOLBY_5_1) {
  766                         printf("DOLBY5.1");
  767                 } else {
  768                         printf("0x%x", f->channel_mask);
  769                 }
  770 
  771                 if (f->frequency_type == 0) {
  772                         printf(" %uHz-%uHz", f->frequency[0],
  773                                f->frequency[1]);
  774                 } else {
  775                         printf(" %uHz", f->frequency[0]);
  776                         for (j = 1; j < f->frequency_type; j++)
  777                                 printf(",%uHz", f->frequency[j]);
  778                 }
  779                 printf("\n");
  780         }
  781 }
  782 
  783 static void
  784 auconv_dump_params(const audio_params_t *p)
  785 {
  786         printf("enc=%s", encoding_dbg_names[p->encoding]);
  787         printf(" %u/%ubit", p->validbits, p->precision);
  788         printf(" %uch", p->channels);
  789         printf(" %uHz", p->sample_rate);
  790         printf("\n");
  791 }
  792 #else
  793 static void
  794 auconv_dump_params(const audio_params_t *p)
  795 {
  796 }
  797 #endif /* AUCONV_DEBUG */
  798 
  799 /**
  800  * a sub-routine for auconv_set_converter()
  801  */
  802 static int
  803 auconv_exact_match(const struct audio_format *formats, int nformats,
  804                    int mode, const audio_params_t *param)
  805 {
  806         int i, enc, f_enc;
  807 
  808         DPRINTF(("%s: ENTER: mode=0x%x target:", __func__, mode));
  809         auconv_dump_params(param);
  810         enc = auconv_normalize_encoding(param->encoding,
  811                                         param->precision);
  812         DPRINTF(("%s: target normalized: %s\n", __func__,
  813             encoding_dbg_names[enc]));
  814         for (i = 0; i < nformats; i++) {
  815                 if (!AUFMT_IS_VALID(&formats[i]))
  816                         continue;
  817                 if ((formats[i].mode & mode) == 0)
  818                         continue;
  819                 f_enc = auconv_normalize_encoding(formats[i].encoding,
  820                                                   formats[i].precision);
  821                 DPRINTF(("%s: format[%d] normalized: %s\n",
  822                          __func__, i, encoding_dbg_names[f_enc]));
  823                 if (f_enc != enc)
  824                         continue;
  825                 /**
  826                  * XXX  we need encoding-dependent check.
  827                  * XXX  Is to check precision/channels meaningful for
  828                  *      MPEG encodings?
  829                  */
  830                 if (formats[i].validbits != param->validbits)
  831                         continue;
  832                 if (formats[i].precision != param->precision)
  833                         continue;
  834                 if (formats[i].channels != param->channels)
  835                         continue;
  836                 if (!auconv_is_supported_rate(&formats[i],
  837                                               param->sample_rate))
  838                         continue;
  839                 return i;
  840         }
  841         return -1;
  842 }
  843 
  844 /**
  845  * a sub-routine for auconv_set_converter()
  846  *   SLINEAR ==> SLINEAR_<host-endian>
  847  *   ULINEAR ==> ULINEAR_<host-endian>
  848  *   SLINEAR_BE 8bit ==> SLINEAR_LE 8bit
  849  *   ULINEAR_BE 8bit ==> ULINEAR_LE 8bit
  850  * This should be the same rule as audio_check_params()
  851  */
  852 static u_int
  853 auconv_normalize_encoding(u_int encoding, u_int precision)
  854 {
  855         int enc;
  856 
  857         enc = encoding;
  858         if (enc == AUDIO_ENCODING_SLINEAR_LE)
  859                 return enc;
  860         if (enc == AUDIO_ENCODING_ULINEAR_LE)
  861                 return enc;
  862 #if BYTE_ORDER == LITTLE_ENDIAN
  863         if (enc == AUDIO_ENCODING_SLINEAR)
  864                 return AUDIO_ENCODING_SLINEAR_LE;
  865         else if (enc == AUDIO_ENCODING_ULINEAR)
  866                 return AUDIO_ENCODING_ULINEAR_LE;
  867 #else
  868         if (enc == AUDIO_ENCODING_SLINEAR)
  869                 enc = AUDIO_ENCODING_SLINEAR_BE;
  870         else if (enc == AUDIO_ENCODING_ULINEAR)
  871                 enc = AUDIO_ENCODING_ULINEAR_BE;
  872 #endif
  873         if (precision == 8 && enc == AUDIO_ENCODING_SLINEAR_BE)
  874                 return AUDIO_ENCODING_SLINEAR_LE;
  875         if (precision == 8 && enc == AUDIO_ENCODING_ULINEAR_BE)
  876                 return AUDIO_ENCODING_ULINEAR_LE;
  877         return enc;
  878 }
  879 
  880 /**
  881  * a sub-routine for auconv_set_converter()
  882  */
  883 static int
  884 auconv_is_supported_rate(const struct audio_format *format, u_int rate)
  885 {
  886         u_int i;
  887 
  888         if (format->frequency_type == 0) {
  889                 return format->frequency[0] <= rate
  890                         && rate <= format->frequency[1];
  891         }
  892         for (i = 0; i < format->frequency_type; i++) {
  893                 if (format->frequency[i] == rate)
  894                         return true;
  895         }
  896         return false;
  897 }
  898 
  899 /**
  900  * Create an audio_encoding_set besed on hardware capability represented
  901  * by audio_format.
  902  *
  903  * Usage:
  904  *      foo_attach(...) {
  905  *              :
  906  *              if (auconv_create_encodings(formats, nformats,
  907  *                      &sc->sc_encodings) != 0) {
  908  *                      // attach failure
  909  *              }
  910  *
  911  * @param formats       [IN] An array of formats which a hardware can support.
  912  * @param nformats      [IN] The number of elements of the array.
  913  * @param encodings     [OUT] receives an address of an audio_encoding_set.
  914  * @return errno; 0 for success.
  915  */
  916 int
  917 auconv_create_encodings(const struct audio_format *formats, int nformats,
  918                         struct audio_encoding_set **encodings)
  919 {
  920         struct audio_encoding_set *buf;
  921         int capacity;
  922         int i;
  923         int err;
  924 
  925 #define ADD_ENCODING(enc, prec, flags)  do { \
  926         err = auconv_add_encoding(enc, prec, flags, &buf, &capacity); \
  927         if (err != 0) goto err_exit; \
  928 } while (/*CONSTCOND*/0)
  929 
  930         capacity = 10;
  931         buf = AUCONV_MALLOC(ENCODING_SET_SIZE(capacity));
  932         if (buf == NULL) {
  933                 err = ENOMEM;
  934                 goto err_exit;
  935         }
  936         buf->size = 0;
  937         for (i = 0; i < nformats; i++) {
  938                 if (!AUFMT_IS_VALID(&formats[i]))
  939                         continue;
  940                 switch (formats[i].encoding) {
  941                 case AUDIO_ENCODING_SLINEAR_LE:
  942                         ADD_ENCODING(formats[i].encoding,
  943                                      formats[i].precision, 0);
  944                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE,
  945                                      formats[i].precision,
  946                                      AUDIO_ENCODINGFLAG_EMULATED);
  947                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE,
  948                                      formats[i].precision,
  949                                      AUDIO_ENCODINGFLAG_EMULATED);
  950                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE,
  951                                      formats[i].precision,
  952                                      AUDIO_ENCODINGFLAG_EMULATED);
  953 #if NMULAW > 0
  954                         if (formats[i].precision == 8
  955                             || formats[i].precision == 16) {
  956                                 ADD_ENCODING(AUDIO_ENCODING_ULAW, 8,
  957                                              AUDIO_ENCODINGFLAG_EMULATED);
  958                                 ADD_ENCODING(AUDIO_ENCODING_ALAW, 8,
  959                                              AUDIO_ENCODINGFLAG_EMULATED);
  960                         }
  961 #endif
  962                         break;
  963                 case AUDIO_ENCODING_SLINEAR_BE:
  964                         ADD_ENCODING(formats[i].encoding,
  965                                      formats[i].precision, 0);
  966                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE,
  967                                      formats[i].precision,
  968                                      AUDIO_ENCODINGFLAG_EMULATED);
  969                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE,
  970                                      formats[i].precision,
  971                                      AUDIO_ENCODINGFLAG_EMULATED);
  972                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE,
  973                                      formats[i].precision,
  974                                      AUDIO_ENCODINGFLAG_EMULATED);
  975 #if NMULAW > 0
  976                         if (formats[i].precision == 8
  977                             || formats[i].precision == 16) {
  978                                 ADD_ENCODING(AUDIO_ENCODING_ULAW, 8,
  979                                              AUDIO_ENCODINGFLAG_EMULATED);
  980                                 ADD_ENCODING(AUDIO_ENCODING_ALAW, 8,
  981                                              AUDIO_ENCODINGFLAG_EMULATED);
  982                         }
  983 #endif
  984                         break;
  985                 case AUDIO_ENCODING_ULINEAR_LE:
  986                         ADD_ENCODING(formats[i].encoding,
  987                                      formats[i].precision, 0);
  988                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE,
  989                                      formats[i].precision,
  990                                      AUDIO_ENCODINGFLAG_EMULATED);
  991                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE,
  992                                      formats[i].precision,
  993                                      AUDIO_ENCODINGFLAG_EMULATED);
  994                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE,
  995                                      formats[i].precision,
  996                                      AUDIO_ENCODINGFLAG_EMULATED);
  997 #if NMULAW > 0
  998                         if (formats[i].precision == 8
  999                             || formats[i].precision == 16) {
 1000                                 ADD_ENCODING(AUDIO_ENCODING_ULAW, 8,
 1001                                              AUDIO_ENCODINGFLAG_EMULATED);
 1002                                 ADD_ENCODING(AUDIO_ENCODING_ALAW, 8,
 1003                                              AUDIO_ENCODINGFLAG_EMULATED);
 1004                         }
 1005 #endif
 1006                         break;
 1007                 case AUDIO_ENCODING_ULINEAR_BE:
 1008                         ADD_ENCODING(formats[i].encoding,
 1009                                      formats[i].precision, 0);
 1010                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE,
 1011                                      formats[i].precision,
 1012                                      AUDIO_ENCODINGFLAG_EMULATED);
 1013                         ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE,
 1014                                      formats[i].precision,
 1015                                      AUDIO_ENCODINGFLAG_EMULATED);
 1016                         ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE,
 1017                                      formats[i].precision,
 1018                                      AUDIO_ENCODINGFLAG_EMULATED);
 1019 #if NMULAW > 0
 1020                         if (formats[i].precision == 8
 1021                             || formats[i].precision == 16) {
 1022                                 ADD_ENCODING(AUDIO_ENCODING_ULAW, 8,
 1023                                              AUDIO_ENCODINGFLAG_EMULATED);
 1024                                 ADD_ENCODING(AUDIO_ENCODING_ALAW, 8,
 1025                                              AUDIO_ENCODINGFLAG_EMULATED);
 1026                         }
 1027 #endif
 1028                         break;
 1029 
 1030                 case AUDIO_ENCODING_ULAW:
 1031                 case AUDIO_ENCODING_ALAW:
 1032                 case AUDIO_ENCODING_ADPCM:
 1033                 case AUDIO_ENCODING_MPEG_L1_STREAM:
 1034                 case AUDIO_ENCODING_MPEG_L1_PACKETS:
 1035                 case AUDIO_ENCODING_MPEG_L1_SYSTEM:
 1036                 case AUDIO_ENCODING_MPEG_L2_STREAM:
 1037                 case AUDIO_ENCODING_MPEG_L2_PACKETS:
 1038                 case AUDIO_ENCODING_MPEG_L2_SYSTEM:
 1039                         ADD_ENCODING(formats[i].encoding,
 1040                                      formats[i].precision, 0);
 1041                         break;
 1042 
 1043                 case AUDIO_ENCODING_SLINEAR:
 1044                 case AUDIO_ENCODING_ULINEAR:
 1045                 case AUDIO_ENCODING_LINEAR:
 1046                 case AUDIO_ENCODING_LINEAR8:
 1047                 default:
 1048                         printf("%s: invalid encoding value "
 1049                                "for audio_format: %d\n",
 1050                                __func__, formats[i].encoding);
 1051                         break;
 1052                 }
 1053         }
 1054         *encodings = buf;
 1055         return 0;
 1056 
 1057  err_exit:
 1058         if (buf != NULL)
 1059                 AUCONV_FREE(buf);
 1060         *encodings = NULL;
 1061         return err;
 1062 }
 1063 
 1064 /**
 1065  * a sub-routine for auconv_create_encodings()
 1066  */
 1067 static int
 1068 auconv_add_encoding(int enc, int prec, int flags,
 1069                     struct audio_encoding_set **buf, int *capacity)
 1070 {
 1071         static const char *encoding_names[] = {
 1072                 NULL, AudioEmulaw, AudioEalaw, NULL,
 1073                 NULL, AudioEadpcm, AudioEslinear_le, AudioEslinear_be,
 1074                 AudioEulinear_le, AudioEulinear_be,
 1075                 AudioEslinear, AudioEulinear,
 1076                 AudioEmpeg_l1_stream, AudioEmpeg_l1_packets,
 1077                 AudioEmpeg_l1_system, AudioEmpeg_l2_stream,
 1078                 AudioEmpeg_l2_packets, AudioEmpeg_l2_system
 1079         };
 1080         struct audio_encoding_set *set;
 1081         struct audio_encoding_set *new_buf;
 1082         audio_encoding_t *e;
 1083         int i;
 1084 
 1085         set = *buf;
 1086         /* already has the same encoding? */
 1087         e = set->items;
 1088         for (i = 0; i < set->size; i++, e++) {
 1089                 if (e->encoding == enc && e->precision == prec) {
 1090                         /* overwrite EMULATED flag */
 1091                         if ((e->flags & AUDIO_ENCODINGFLAG_EMULATED)
 1092                             && (flags & AUDIO_ENCODINGFLAG_EMULATED) == 0) {
 1093                                 e->flags &= ~AUDIO_ENCODINGFLAG_EMULATED;
 1094                         }
 1095                         return 0;
 1096                 }
 1097         }
 1098         /* We don't have the specified one. */
 1099 
 1100         if (set->size >= *capacity) {
 1101                 new_buf = AUCONV_REALLOC(set,
 1102                                          ENCODING_SET_SIZE(*capacity + 10));
 1103                 if (new_buf == NULL)
 1104                         return ENOMEM;
 1105                 *buf = new_buf;
 1106                 set = new_buf;
 1107                 *capacity += 10;
 1108         }
 1109 
 1110         e = &set->items[set->size];
 1111         e->index = 0;
 1112         strlcpy(e->name, encoding_names[enc], MAX_AUDIO_DEV_LEN);
 1113         e->encoding = enc;
 1114         e->precision = prec;
 1115         e->flags = flags;
 1116         set->size += 1;
 1117         return 0;
 1118 }
 1119 
 1120 /**
 1121  * Delete an audio_encoding_set created by auconv_create_encodings().
 1122  *
 1123  * Usage:
 1124  *      foo_detach(...) {
 1125  *              :
 1126  *              auconv_delete_encodings(sc->sc_encodings);
 1127  *              :
 1128  *      }
 1129  *
 1130  * @param encodings     [IN] An audio_encoding_set which was created by
 1131  *                      auconv_create_encodings().
 1132  * @return errno; 0 for success.
 1133  */
 1134 int auconv_delete_encodings(struct audio_encoding_set *encodings)
 1135 {
 1136         if (encodings != NULL)
 1137                 AUCONV_FREE(encodings);
 1138         return 0;
 1139 }
 1140 
 1141 /**
 1142  * Copy the element specified by aep->index.
 1143  *
 1144  * Usage:
 1145  * int foo_query_encoding(void *v, audio_encoding_t *aep) {
 1146  *      struct foo_softc *sc = (struct foo_softc *)v;
 1147  *      return auconv_query_encoding(sc->sc_encodings, aep);
 1148  * }
 1149  *
 1150  * @param encodings     [IN] An audio_encoding_set created by
 1151  *                      auconv_create_encodings().
 1152  * @param aep           [IN/OUT] resultant audio_encoding_t.
 1153  */
 1154 int
 1155 auconv_query_encoding(const struct audio_encoding_set *encodings,
 1156                       audio_encoding_t *aep)
 1157 {
 1158         if (aep->index >= encodings->size)
 1159                 return EINVAL;
 1160         strlcpy(aep->name, encodings->items[aep->index].name,
 1161                 MAX_AUDIO_DEV_LEN);
 1162         aep->encoding = encodings->items[aep->index].encoding;
 1163         aep->precision = encodings->items[aep->index].precision;
 1164         aep->flags = encodings->items[aep->index].flags;
 1165         return 0;
 1166 }

Cache object: 57dd7f0f0730e32f1a247efad1280293


[ 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.