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>