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