[BACK]Return to auconv.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev

Annotation of src/sys/dev/auconv.c, Revision 1.15.2.1

1.15.2.1! yamt        1: /*     $NetBSD: auconv.c,v 1.15 2006/02/26 23:52:08 pooka Exp $        */
1.1       augustss    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:  */
1.5       lukem      36:
                     37: #include <sys/cdefs.h>
1.15.2.1! yamt       38: __KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.15 2006/02/26 23:52:08 pooka Exp $");
1.1       augustss   39:
                     40: #include <sys/types.h>
                     41: #include <sys/audioio.h>
1.11      kent       42: #include <sys/errno.h>
                     43: #include <sys/malloc.h>
                     44: #include <sys/null.h>
                     45: #include <sys/systm.h>
                     46: #include <dev/audio_if.h>
                     47: #include <dev/auconv.h>
                     48: #include <dev/mulaw.h>
                     49: #include <machine/limits.h>
                     50: #ifndef _KERNEL
                     51: #include <stddef.h>
                     52: #include <stdio.h>
                     53: #include <stdlib.h>
                     54: #include <string.h>
                     55: #endif
                     56:
1.12      kent       57: #include <aurateconv.h>                /* generated by config(8) */
                     58: #include <mulaw.h>             /* generated by config(8) */
1.11      kent       59:
                     60: /* #define AUCONV_DEBUG */
1.12      kent       61: #ifdef AUCONV_DEBUG
                     62: # define DPRINTF(x)    printf x
                     63: #else
                     64: # define DPRINTF(x)
                     65: #endif
                     66:
1.11      kent       67: #if NAURATECONV > 0
                     68: static int auconv_rateconv_supportable(u_int, u_int, u_int);
                     69: static int auconv_rateconv_check_channels(const struct audio_format *, int,
1.12      kent       70:                                          int, const audio_params_t *,
                     71:                                          stream_filter_list_t *);
1.11      kent       72: static int auconv_rateconv_check_rates(const struct audio_format *, int,
1.12      kent       73:                                       int, const audio_params_t *,
                     74:                                       audio_params_t *,
                     75:                                       stream_filter_list_t *);
1.11      kent       76: #endif
                     77: #ifdef AUCONV_DEBUG
                     78: static void auconv_dump_formats(const struct audio_format *, int);
                     79: #endif
1.12      kent       80: static void auconv_dump_params(const audio_params_t *);
1.11      kent       81: static int auconv_exact_match(const struct audio_format *, int, int,
                     82:                              const struct audio_params *);
                     83: static u_int auconv_normalize_encoding(u_int, u_int);
1.12      kent       84: static int auconv_is_supported_rate(const struct audio_format *, u_int);
1.11      kent       85: static int auconv_add_encoding(int, int, int, struct audio_encoding_set **,
                     86:                               int *);
                     87:
                     88: #ifdef _KERNEL
                     89: #define AUCONV_MALLOC(size)    malloc(size, M_DEVBUF, M_NOWAIT)
                     90: #define AUCONV_REALLOC(p, size)        realloc(p, size, M_DEVBUF, M_NOWAIT)
                     91: #define AUCONV_FREE(p)         free(p, M_DEVBUF)
                     92: #else
                     93: #define AUCONV_MALLOC(size)    malloc(size)
                     94: #define AUCONV_REALLOC(p, size)        realloc(p, size)
                     95: #define AUCONV_FREE(p)         free(p)
                     96: #define FALSE                  0
                     97: #define TRUE                   1
                     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 {
1.12      kent      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;
1.11      kent      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,
1.12      kent      120:         linear8_to_linear16, linear16_to_linear8},
1.11      kent      121:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      122:         linear8_to_linear16, linear16_to_linear8},
1.11      kent      123:        {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
1.12      kent      124:         change_sign8, change_sign8},
                    125:        {0, 0, 0, NULL, NULL}};
1.11      kent      126: static const struct conv_table u8_table[] = {
                    127:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      128:         linear8_to_linear16, linear16_to_linear8},
1.11      kent      129:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      130:         linear8_to_linear16, linear16_to_linear8},
1.11      kent      131:        {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
1.12      kent      132:         change_sign8, change_sign8},
1.11      kent      133:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      134:         linear8_to_linear16, linear16_to_linear8},
1.11      kent      135:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      136:         linear8_to_linear16, linear16_to_linear8},
                    137:        {0, 0, 0, NULL, NULL}};
1.11      kent      138: static const struct conv_table s16le_table[] = {
                    139:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      140:         swap_bytes, swap_bytes},
1.11      kent      141:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      142:         change_sign16, change_sign16},
1.11      kent      143:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      144:         swap_bytes_change_sign16, swap_bytes_change_sign16},
                    145:        {0, 0, 0, NULL, NULL}};
1.11      kent      146: static const struct conv_table s16be_table[] = {
                    147:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      148:         swap_bytes, swap_bytes},
1.11      kent      149:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      150:         change_sign16, change_sign16},
1.11      kent      151:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      152:         swap_bytes_change_sign16, swap_bytes_change_sign16},
                    153:        {0, 0, 0, NULL, NULL}};
1.11      kent      154: static const struct conv_table u16le_table[] = {
                    155:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      156:         change_sign16, change_sign16},
1.11      kent      157:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      158:         swap_bytes, swap_bytes},
1.11      kent      159:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      160:         swap_bytes_change_sign16, swap_bytes_change_sign16},
                    161:        {0, 0, 0, NULL, NULL}};
1.11      kent      162: static const struct conv_table u16be_table[] = {
                    163:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      164:         change_sign16, change_sign16},
1.11      kent      165:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      166:         swap_bytes, swap_bytes},
1.11      kent      167:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      168:         swap_bytes_change_sign16, swap_bytes_change_sign16},
                    169:        {0, 0, 0, NULL, NULL}};
1.11      kent      170: #if NMULAW > 0
                    171: static const struct conv_table mulaw_table[] = {
                    172:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      173:         mulaw_to_linear16, linear16_to_mulaw},
1.11      kent      174:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      175:         mulaw_to_linear16, linear16_to_mulaw},
1.11      kent      176:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      177:         mulaw_to_linear16, linear16_to_mulaw},
1.11      kent      178:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      179:         mulaw_to_linear16, linear16_to_mulaw},
1.11      kent      180:        {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
1.12      kent      181:         mulaw_to_linear8, linear8_to_mulaw},
1.11      kent      182:        {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
1.12      kent      183:         mulaw_to_linear8, linear8_to_mulaw},
                    184:        {0, 0, 0, NULL, NULL}};
1.11      kent      185: static const struct conv_table alaw_table[] = {
                    186:        {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
1.12      kent      187:         alaw_to_linear16, linear16_to_alaw},
1.11      kent      188:        {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
1.12      kent      189:         alaw_to_linear16, linear16_to_alaw},
1.11      kent      190:        {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
1.12      kent      191:         alaw_to_linear16, linear16_to_alaw},
1.11      kent      192:        {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
1.12      kent      193:         alaw_to_linear16, linear16_to_alaw},
1.11      kent      194:        {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
1.12      kent      195:         alaw_to_linear8, linear8_to_alaw},
1.11      kent      196:        {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
1.12      kent      197:         alaw_to_linear8, linear8_to_alaw},
                    198:        {0, 0, 0, NULL, NULL}};
                    199: #endif
                    200: #ifdef AUCONV_DEBUG
1.14      pooka     201: static const char *encoding_dbg_names[] = {
1.12      kent      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: };
1.11      kent      210: #endif
1.1       augustss  211:
                    212: void
1.12      kent      213: stream_filter_set_fetcher(stream_filter_t *this, stream_fetcher_t *p)
1.1       augustss  214: {
1.12      kent      215:        this->prev = p;
1.1       augustss  216: }
                    217:
                    218: void
1.12      kent      219: stream_filter_set_inputbuffer(stream_filter_t *this, audio_stream_t *stream)
1.3       augustss  220: {
1.12      kent      221:        this->src = stream;
1.3       augustss  222: }
                    223:
1.12      kent      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;
1.1       augustss  240: }
                    241:
                    242: void
1.12      kent      243: auconv_nocontext_filter_dtor(struct stream_filter *this)
1.1       augustss  244: {
1.12      kent      245:        if (this != NULL)
                    246:                AUCONV_FREE(this);
1.1       augustss  247: }
                    248:
1.12      kent      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;
1.1       augustss  275: }
                    276:
1.12      kent      277: DEFINE_FILTER(change_sign16)
1.1       augustss  278: {
1.12      kent      279:        stream_filter_t *this;
                    280:        int m, err, enc;
1.1       augustss  281:
1.12      kent      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);
1.2       augustss  300:        }
1.12      kent      301:        return 0;
1.2       augustss  302: }
                    303:
1.12      kent      304: DEFINE_FILTER(swap_bytes)
1.3       augustss  305: {
1.12      kent      306:        stream_filter_t *this;
                    307:        int m, err;
1.3       augustss  308:
1.12      kent      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;
1.3       augustss  320: }
                    321:
1.12      kent      322: DEFINE_FILTER(swap_bytes_change_sign16)
1.2       augustss  323: {
1.12      kent      324:        stream_filter_t *this;
                    325:        int m, err, enc;
1.2       augustss  326:
1.12      kent      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);
1.3       augustss  345:        }
1.12      kent      346:        return 0;
1.3       augustss  347: }
                    348:
1.12      kent      349: DEFINE_FILTER(linear8_to_linear16)
1.3       augustss  350: {
1.12      kent      351:        stream_filter_t *this;
                    352:        int m, err, enc_dst, enc_src;
1.3       augustss  353:
1.12      kent      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);
1.3       augustss  407:        }
1.12      kent      408:        return 0;
1.3       augustss  409: }
                    410:
1.12      kent      411: DEFINE_FILTER(linear16_to_linear8)
1.3       augustss  412: {
1.12      kent      413:        stream_filter_t *this;
                    414:        int m, err, enc_src, enc_dst;
1.3       augustss  415:
1.12      kent      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);
1.1       augustss  464:        }
1.12      kent      465:        return 0;
1.1       augustss  466: }
1.11      kent      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.
1.12      kent      475:  * @param param                [IN] Requested format.  param->sw_code may be set.
1.11      kent      476:  * @param rateconv     [IN] TRUE if aurateconv may be used.
1.12      kent      477:  * @param list         [OUT] stream_filters required for param.
1.11      kent      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,
1.12      kent      483:                     int mode, const audio_params_t *param, int rateconv,
                    484:                     stream_filter_list_t *list)
1.11      kent      485: {
1.12      kent      486:        audio_params_t work;
1.11      kent      487:        const struct conv_table *table;
1.12      kent      488:        stream_filter_factory_t *conv;
1.11      kent      489:        int enc;
                    490:        int i, j;
                    491:
                    492: #ifdef AUCONV_DEBUG
1.12      kent      493:        DPRINTF(("%s: ENTER rateconv=%d\n", __func__, rateconv));
1.11      kent      494:        auconv_dump_formats(formats, nformats);
                    495: #endif
1.12      kent      496:        enc = auconv_normalize_encoding(param->encoding, param->precision);
1.11      kent      497:
                    498:        /* check support by native format */
1.12      kent      499:        i = auconv_exact_match(formats, nformats, mode, param);
1.11      kent      500:        if (i >= 0) {
1.12      kent      501:                DPRINTF(("%s: LEAVE with %d (exact)\n", __func__, i));
1.11      kent      502:                return i;
                    503:        }
                    504:
                    505: #if NAURATECONV > 0
                    506:        /* native format with aurateconv */
1.12      kent      507:        DPRINTF(("%s: native with aurateconv\n", __func__));
1.11      kent      508:        if (rateconv
1.12      kent      509:            && auconv_rateconv_supportable(enc, param->precision,
                    510:                                           param->validbits)) {
1.11      kent      511:                i = auconv_rateconv_check_channels(formats, nformats,
1.12      kent      512:                                                   mode, param, list);
1.11      kent      513:                if (i >= 0) {
1.12      kent      514:                        DPRINTF(("%s: LEAVE with %d (aurateconv1)\n", __func__, i));
1.11      kent      515:                        return i;
                    516:                }
                    517:        }
                    518: #endif
                    519:
                    520:        /* check for emulation */
1.12      kent      521:        DPRINTF(("%s: encoding emulation\n", __func__));
1.11      kent      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:        }
1.12      kent      557:        if (table == NULL) {
                    558:                DPRINTF(("%s: LEAVE with -1 (no-emultable)\n", __func__));
1.11      kent      559:                return -1;
1.12      kent      560:        }
1.11      kent      561:        work = *param;
1.12      kent      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;
1.11      kent      566:                i = auconv_exact_match(formats, nformats, mode, &work);
                    567:                if (i >= 0) {
1.12      kent      568:                        conv = mode == AUMODE_PLAY
1.11      kent      569:                                ? table[j].play_conv : table[j].rec_conv;
1.12      kent      570:                        list->append(list, conv, &work);
                    571:                        DPRINTF(("%s: LEAVE with %d (emultable)\n", __func__, i));
1.11      kent      572:                        return i;
                    573:                }
                    574:        }
                    575:        /* not found */
                    576:
                    577: #if NAURATECONV > 0
                    578:        /* emulation with aurateconv */
1.12      kent      579:        DPRINTF(("%s: encoding emulation with aurateconv\n", __func__));
                    580:        if (!rateconv) {
                    581:                DPRINTF(("%s: LEAVE with -1 (no-rateconv)\n", __func__));
1.11      kent      582:                return -1;
1.12      kent      583:        }
1.11      kent      584:        work = *param;
1.12      kent      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))
1.11      kent      589:                        continue;
1.12      kent      590:                work.encoding = table[j].encoding;
                    591:                work.precision = table[j].precision;
                    592:                work.validbits = table[j].validbits;
1.11      kent      593:                i = auconv_rateconv_check_channels(formats, nformats,
1.12      kent      594:                                                   mode, &work, list);
1.11      kent      595:                if (i >= 0) {
1.12      kent      596:                        /* work<=>hw conversion is already registered */
                    597:                        conv = mode == AUMODE_PLAY
1.11      kent      598:                                ? table[j].play_conv : table[j].rec_conv;
1.12      kent      599:                        /* register userland<=>work conversion */
                    600:                        list->append(list, conv, &work);
                    601:                        DPRINTF(("%s: LEAVE with %d (rateconv2)\n", __func__, i));
1.11      kent      602:                        return i;
                    603:                }
                    604:        }
                    605:
                    606: #endif
1.12      kent      607:        DPRINTF(("%s: LEAVE with -1 (bottom)\n", __func__));
1.11      kent      608:        return -1;
                    609: }
                    610:
                    611: #if NAURATECONV > 0
                    612: static int
1.12      kent      613: auconv_rateconv_supportable(u_int encoding, u_int precision, u_int validbits)
1.11      kent      614: {
                    615:        if (encoding != AUDIO_ENCODING_SLINEAR_LE
                    616:            && encoding != AUDIO_ENCODING_SLINEAR_BE)
                    617:                return FALSE;
1.12      kent      618:        if (precision != 16 && precision != 24 && precision != 32)
1.11      kent      619:                return FALSE;
1.12      kent      620:        if (precision < validbits)
1.11      kent      621:                return FALSE;
                    622:        return TRUE;
                    623: }
                    624:
                    625: static int
                    626: auconv_rateconv_check_channels(const struct audio_format *formats, int nformats,
1.12      kent      627:                               int mode, const audio_params_t *param,
                    628:                               stream_filter_list_t *list)
1.11      kent      629: {
1.12      kent      630:        audio_params_t hw_param;
1.11      kent      631:        int ind, n;
                    632:
1.12      kent      633:        hw_param = *param;
1.11      kent      634:        /* check for the specified number of channels */
1.12      kent      635:        ind = auconv_rateconv_check_rates(formats, nformats, mode, param,
                    636:                                          &hw_param, list);
1.11      kent      637:        if (ind >= 0)
                    638:                return ind;
                    639:
                    640:        /* check for larger numbers */
                    641:        for (n = param->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
1.12      kent      642:                hw_param.channels = n;
                    643:                ind = auconv_rateconv_check_rates(formats, nformats, mode,
                    644:                                                  param, &hw_param, list);
1.11      kent      645:                if (ind >= 0)
                    646:                        return ind;
                    647:        }
                    648:
                    649:        /* check for stereo:monaural conversion */
                    650:        if (param->channels == 2) {
1.12      kent      651:                hw_param.channels = 1;
                    652:                ind = auconv_rateconv_check_rates(formats, nformats, mode,
                    653:                                                  param, &hw_param, list);
1.11      kent      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,
1.12      kent      662:                            int mode, const audio_params_t *param,
                    663:                            audio_params_t *hw_param, stream_filter_list_t *list)
1.11      kent      664: {
                    665:        int ind, i, j, enc, f_enc;
1.12      kent      666:        u_int rate, minrate, maxrate, orig_rate;;
1.11      kent      667:
                    668:        /* exact match */
1.12      kent      669:        ind = auconv_exact_match(formats, nformats, mode, hw_param);
1.11      kent      670:        if (ind >= 0)
1.12      kent      671:                goto found;
1.11      kent      672:
                    673:        /* determine min/max of specified encoding/precision/channels */
1.12      kent      674:        minrate = UINT_MAX;
1.11      kent      675:        maxrate = 0;
1.12      kent      676:        enc = auconv_normalize_encoding(param->encoding,
                    677:                                        param->precision);
1.11      kent      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;
1.12      kent      687:                if (formats[i].validbits != hw_param->validbits)
1.11      kent      688:                        continue;
1.12      kent      689:                if (formats[i].precision != hw_param->precision)
1.11      kent      690:                        continue;
1.12      kent      691:                if (formats[i].channels != hw_param->channels)
1.11      kent      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 */
1.12      kent      711:        orig_rate = hw_param->sample_rate;
1.11      kent      712:        for (i = 2; (rate = param->sample_rate * i) <= maxrate; i++) {
1.12      kent      713:                hw_param->sample_rate = rate;
                    714:                ind = auconv_exact_match(formats, nformats, mode, hw_param);
1.11      kent      715:                if (ind >= 0)
1.12      kent      716:                        goto found;
1.11      kent      717:        }
                    718:
1.12      kent      719:        hw_param->sample_rate = param->sample_rate >= minrate
1.11      kent      720:                ? maxrate : minrate;
1.12      kent      721:        ind = auconv_exact_match(formats, nformats, mode, hw_param);
1.11      kent      722:        if (ind >= 0)
1.12      kent      723:                goto found;
                    724:        hw_param->sample_rate = orig_rate;
1.11      kent      725:        return -1;
1.12      kent      726:
                    727:  found:
                    728:        list->append(list, aurateconv, hw_param);
                    729:        return ind;
1.11      kent      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:                }
1.14      pooka     754:                printf(" enc=%s", encoding_dbg_names[f->encoding]);
1.12      kent      755:                printf(" %u/%ubit", f->validbits, f->precision);
1.11      kent      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) {
1.12      kent      772:                        printf(" %uHz-%uHz", f->frequency[0],
1.11      kent      773:                               f->frequency[1]);
                    774:                } else {
1.12      kent      775:                        printf(" %uHz", f->frequency[0]);
1.11      kent      776:                        for (j = 1; j < f->frequency_type; j++)
1.12      kent      777:                                printf(",%uHz", f->frequency[j]);
1.11      kent      778:                }
                    779:                printf("\n");
                    780:        }
                    781: }
1.12      kent      782:
                    783: static void
                    784: auconv_dump_params(const audio_params_t *p)
                    785: {
1.14      pooka     786:        printf("enc=%s", encoding_dbg_names[p->encoding]);
1.12      kent      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: }
1.11      kent      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,
1.12      kent      804:                   int mode, const audio_params_t *param)
1.11      kent      805: {
                    806:        int i, enc, f_enc;
                    807:
1.12      kent      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);
1.14      pooka     812:        DPRINTF(("%s: target normalized: %s\n", __func__,
                    813:            encoding_dbg_names[enc]));
1.11      kent      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);
1.15      pooka     821:                DPRINTF(("%s: format[%d] normalized: %s\n",
1.14      pooka     822:                         __func__, i, encoding_dbg_names[f_enc]));
1.11      kent      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:                 */
1.12      kent      830:                if (formats[i].validbits != param->validbits)
1.11      kent      831:                        continue;
1.12      kent      832:                if (formats[i].precision != param->precision)
1.11      kent      833:                        continue;
1.12      kent      834:                if (formats[i].channels != param->channels)
1.11      kent      835:                        continue;
                    836:                if (!auconv_is_supported_rate(&formats[i],
1.12      kent      837:                                              param->sample_rate))
1.11      kent      838:                        continue;
                    839:                return i;
                    840:        }
                    841:        return -1;
                    842: }
                    843:
                    844: /**
                    845:  * a sub-routine for auconv_set_converter()
1.12      kent      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()
1.11      kent      851:  */
                    852: static u_int
                    853: auconv_normalize_encoding(u_int encoding, u_int precision)
                    854: {
                    855:        int enc;
                    856:
                    857:        enc = encoding;
1.12      kent      858:        if (enc == AUDIO_ENCODING_SLINEAR_LE)
                    859:                return enc;
                    860:        if (enc == AUDIO_ENCODING_ULINEAR_LE)
                    861:                return enc;
1.11      kent      862: #if BYTE_ORDER == LITTLE_ENDIAN
                    863:        if (enc == AUDIO_ENCODING_SLINEAR)
1.12      kent      864:                return AUDIO_ENCODING_SLINEAR_LE;
1.11      kent      865:        else if (enc == AUDIO_ENCODING_ULINEAR)
1.12      kent      866:                return AUDIO_ENCODING_ULINEAR_LE;
1.11      kent      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)
1.12      kent      874:                return AUDIO_ENCODING_SLINEAR_LE;
1.11      kent      875:        if (precision == 8 && enc == AUDIO_ENCODING_ULINEAR_BE)
1.12      kent      876:                return AUDIO_ENCODING_ULINEAR_LE;
1.11      kent      877:        return enc;
                    878: }
                    879:
                    880: /**
                    881:  * a sub-routine for auconv_set_converter()
                    882:  */
                    883: static int
1.12      kent      884: auconv_is_supported_rate(const struct audio_format *format, u_int rate)
1.11      kent      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));
1.15.2.1! yamt      932:        if (buf == NULL) {
        !           933:                err = ENOMEM;
        !           934:                goto err_exit;
        !           935:        }
1.11      kent      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: }

CVSweb <webmaster@jp.NetBSD.org>