Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev add the following four functions:
details: https://anonhg.NetBSD.org/src/rev/b5ab44392d9b
branches: trunk
changeset: 571187:b5ab44392d9b
user: kent <kent%NetBSD.org@localhost>
date: Sat Nov 13 08:08:22 2004 +0000
description:
add the following four functions:
extern int auconv_set_converter(const struct audio_format *, int,
int, struct audio_params *, int);
extern int auconv_create_encodings(const struct audio_format *, int,
struct audio_encoding_set **);
extern int auconv_delete_encodings(struct audio_encoding_set *);
extern int auconv_query_encoding(const struct audio_encoding_set *,
audio_encoding_t *);
These are helper functions for implementing audio_hw_if::set_params() and
audio_hw_if::query_encodings().
diffstat:
sys/dev/auconv.c | 817 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/auconv.h | 90 +++++-
2 files changed, 903 insertions(+), 4 deletions(-)
diffs (truncated from 941 to 300 lines):
diff -r 68c95ae35117 -r b5ab44392d9b sys/dev/auconv.c
--- a/sys/dev/auconv.c Sat Nov 13 07:58:14 2004 +0000
+++ b/sys/dev/auconv.c Sat Nov 13 08:08:22 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: auconv.c,v 1.10 2002/03/15 14:55:03 kent Exp $ */
+/* $NetBSD: auconv.c,v 1.11 2004/11/13 08:08:22 kent Exp $ */
/*
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -35,12 +35,159 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.10 2002/03/15 14:55:03 kent Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.11 2004/11/13 08:08:22 kent Exp $");
#include <sys/types.h>
#include <sys/audioio.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/null.h>
+#include <sys/systm.h>
+#include <dev/audio_if.h>
+#include <dev/auconv.h>
+#include <dev/mulaw.h>
+#include <machine/limits.h>
+#ifndef _KERNEL
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
-#include "auconv.h"
+#include <aurateconv.h>
+#include <mulaw.h>
+
+/* #define AUCONV_DEBUG */
+#if NAURATECONV > 0
+static int auconv_rateconv_supportable(u_int, u_int, u_int);
+static int auconv_rateconv_check_channels(const struct audio_format *, int,
+ int, struct audio_params *);
+static int auconv_rateconv_check_rates(const struct audio_format *, int,
+ int, struct audio_params *);
+#endif
+#ifdef AUCONV_DEBUG
+static void auconv_dump_formats(const struct audio_format *, int);
+#endif
+static int auconv_exact_match(const struct audio_format *, int, int,
+ const struct audio_params *);
+static u_int auconv_normalize_encoding(u_int, u_int);
+static int auconv_is_supported_rate(const struct audio_format *, u_long);
+static int auconv_add_encoding(int, int, int, struct audio_encoding_set **,
+ int *);
+
+#ifdef _KERNEL
+#define AUCONV_MALLOC(size) malloc(size, M_DEVBUF, M_NOWAIT)
+#define AUCONV_REALLOC(p, size) realloc(p, size, M_DEVBUF, M_NOWAIT)
+#define AUCONV_FREE(p) free(p, M_DEVBUF)
+#else
+#define AUCONV_MALLOC(size) malloc(size)
+#define AUCONV_REALLOC(p, size) realloc(p, size)
+#define AUCONV_FREE(p) free(p)
+#define FALSE 0
+#define TRUE 1
+#endif
+
+struct audio_encoding_set {
+ int size;
+ audio_encoding_t items[1];
+};
+#define ENCODING_SET_SIZE(n) (offsetof(struct audio_encoding_set, items) \
+ + sizeof(audio_encoding_t) * (n))
+
+struct conv_table {
+ u_int hw_encoding;
+ u_int hw_precision;
+ u_int hw_subframe;
+ void (*play_conv)(void *, u_char *, int);
+ void (*rec_conv)(void *, u_char *, int);
+ int factor;
+};
+/*
+ * SLINEAR-16 or SLINEAR-24 should precede in a table because
+ * aurateconv supports only SLINEAR.
+ */
+static const struct conv_table s8_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ linear8_to_linear16_le, linear16_to_linear8_le, 2},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ linear8_to_linear16_be, linear16_to_linear8_be, 2},
+ {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
+ change_sign8, change_sign8, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table u8_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ ulinear8_to_slinear16_le, slinear16_to_ulinear8_le, 2},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ ulinear8_to_slinear16_be, slinear16_to_ulinear8_be, 2},
+ {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
+ change_sign8, change_sign8, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ linear8_to_linear16_le, linear16_to_linear8_le, 2},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ linear8_to_linear16_be, linear16_to_linear8_be, 2},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table s16le_table[] = {
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ swap_bytes, swap_bytes, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ change_sign16_le, change_sign16_le, 1},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ swap_bytes_change_sign16_be, change_sign16_swap_bytes_be, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table s16be_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ swap_bytes, swap_bytes, 1},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ change_sign16_be, change_sign16_be, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ swap_bytes_change_sign16_le, change_sign16_swap_bytes_le, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table u16le_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ change_sign16_le, change_sign16_le, 1},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ swap_bytes, swap_bytes, 1},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ swap_bytes_change_sign16_be, change_sign16_swap_bytes_be, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table u16be_table[] = {
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ change_sign16_be, change_sign16_be, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ swap_bytes, swap_bytes, 1},
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ swap_bytes_change_sign16_le, change_sign16_swap_bytes_le, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+#if NMULAW > 0
+static const struct conv_table mulaw_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ mulaw_to_slinear16_le, slinear16_to_mulaw_le, 2},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ mulaw_to_slinear16_be, slinear16_to_mulaw_be, 2},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ mulaw_to_ulinear16_le, ulinear16_to_mulaw_le, 2},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ mulaw_to_ulinear16_be, ulinear16_to_mulaw_be, 2},
+ {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
+ mulaw_to_slinear8, slinear8_to_mulaw, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
+ mulaw_to_ulinear8, ulinear8_to_mulaw, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+static const struct conv_table alaw_table[] = {
+ {AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ alaw_to_slinear16_le, slinear16_to_alaw_le, 2},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ alaw_to_slinear16_be, slinear16_to_alaw_be, 2},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, 16,
+ alaw_to_ulinear16_le, ulinear16_to_alaw_le, 2},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, 16,
+ alaw_to_ulinear16_be, ulinear16_to_alaw_be, 2},
+ {AUDIO_ENCODING_SLINEAR_LE, 8, 8,
+ alaw_to_slinear8, slinear8_to_alaw, 1},
+ {AUDIO_ENCODING_ULINEAR_LE, 8, 8,
+ alaw_to_ulinear8, ulinear8_to_alaw, 1},
+ {0, 0, 0, NULL, NULL, 0}};
+#endif
void
change_sign8(void *v, u_char *p, int cc)
@@ -219,3 +366,667 @@
p += 2;
}
}
+
+/**
+ * Set appropriate parameters in `param,' and return the index in
+ * the hardware capability array `formats.'
+ *
+ * @param formats [IN] An array of formats which a hardware can support.
+ * @param nformats [IN] The number of elements of the array.
+ * @param mode [IN] Either AUMODE_PLAY or AUMODE_RECORD.
+ * @param param [IN/OUT] Requested format. param->sw_code may be set.
+ * @param rateconv [IN] TRUE if aurateconv may be used.
+ * @return The index of selected audio_format entry. -1 if the device
+ * can not support the specified param.
+ */
+int
+auconv_set_converter(const struct audio_format *formats, int nformats,
+ int mode, struct audio_params *param, int rateconv)
+{
+ struct audio_params work;
+ const struct conv_table *table;
+ int enc;
+ int i, j;
+
+#ifdef AUCONV_DEBUG
+ auconv_dump_formats(formats, nformats);
+#endif
+ work = *param;
+ work.sw_code = NULL;
+ work.factor = 1;
+ work.factor_denom = 1;
+ work.hw_sample_rate = work.sample_rate;
+ work.hw_encoding = work.encoding;
+ work.hw_precision = work.precision;
+ /* work.hw_subframe = work.precision; */
+ work.hw_channels = work.channels;
+ enc = auconv_normalize_encoding(work.encoding, work.precision);
+
+ /* check support by native format */
+ i = auconv_exact_match(formats, nformats, mode, &work);
+ if (i >= 0) {
+ *param = work;
+ return i;
+ }
+
+ work = *param;
+#if NAURATECONV > 0
+ /* native format with aurateconv */
+ if (rateconv
+ && auconv_rateconv_supportable(enc, work.hw_precision,
+ work.hw_precision)) {
+ i = auconv_rateconv_check_channels(formats, nformats,
+ mode, &work);
+ if (i >= 0) {
+ *param = work;
+ return i;
+ }
+ }
+#endif
+
+ /* check for emulation */
+ table = NULL;
+ switch (enc) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (param->precision == 8)
+ table = s8_table;
+ else if (param->precision == 16)
+ table = s16le_table;
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (param->precision == 8)
+ table = s8_table;
+ else if (param->precision == 16)
+ table = s16be_table;
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (param->precision == 8)
+ table = u8_table;
+ else if (param->precision == 16)
+ table = u16le_table;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (param->precision == 8)
+ table = u8_table;
+ else if (param->precision == 16)
+ table = u16be_table;
+ break;
+#if NMULAW > 0
+ case AUDIO_ENCODING_ULAW:
+ table = mulaw_table;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ table = alaw_table;
+ break;
+#endif
+ }
+ if (table == NULL)
+ return -1;
+ work = *param;
+ for (j = 0; table[j].hw_precision != 0; j++) {
+ work.hw_encoding = table[j].hw_encoding;
+ work.hw_precision = table[j].hw_precision;
+ /* work.hw_subframe = table[j].hw_subframe; */
+ i = auconv_exact_match(formats, nformats, mode, &work);
+ if (i >= 0) {
+ *param = work;
+ param->sw_code = mode == AUMODE_PLAY
+ ? table[j].play_conv : table[j].rec_conv;
+ param->factor = table[j].factor;
+ param->factor_denom = 1;
+ return i;
+ }
+ }
+ /* not found */
+
+#if NAURATECONV > 0
+ /* emulation with aurateconv */
+ if (!rateconv)
+ return -1;
+ work = *param;
+ for (j = 0; table[j].hw_precision != 0; j++) {
+ if (!auconv_rateconv_supportable(table[j].hw_encoding,
+ table[j].hw_precision,
+ table[j].hw_subframe))
+ continue;
+ work.hw_encoding = table[j].hw_encoding;
+ work.hw_precision = table[j].hw_precision;
Home |
Main Index |
Thread Index |
Old Index