Module Name:    src
Committed By:   nat
Date:           Tue Jun 20 07:21:50 UTC 2017

Modified Files:
        src/sys/dev: auconv.c auconv.h mulaw.c mulaw.h

Log Message:
Add support for more formats.  At present 24 bit formats do not work and
have been disabled.

Ok christos@.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/dev/auconv.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/auconv.h
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/mulaw.c
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/mulaw.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/auconv.c
diff -u src/sys/dev/auconv.c:1.26 src/sys/dev/auconv.c:1.27
--- src/sys/dev/auconv.c:1.26	Thu Jun  1 09:44:30 2017
+++ src/sys/dev/auconv.c	Tue Jun 20 07:21:50 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: auconv.c,v 1.26 2017/06/01 09:44:30 pgoyette Exp $	*/
+/*	$NetBSD: auconv.c,v 1.27 2017/06/20 07:21:50 nat Exp $	*/
 
 /*
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.26 2017/06/01 09:44:30 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.27 2017/06/20 07:21:50 nat Exp $");
 
 #include <sys/types.h>
 #include <sys/audioio.h>
@@ -113,86 +113,216 @@ struct conv_table {
 	stream_filter_factory_t *play_conv;
 	stream_filter_factory_t *rec_conv;
 };
+#define TABLE_LIST(prec, valid, target) 				\
+	{AUDIO_ENCODING_SLINEAR_LE, prec, valid,			\
+	 linear##target##_##target##_to_linear##prec,			\
+		linear##prec##_##valid##_to_linear##target},		\
+	{AUDIO_ENCODING_SLINEAR_BE, prec, valid,			\
+	 linear##target##_##target##_to_linear##prec,			\
+		linear##prec##_##valid##_to_linear##target},		\
+	{AUDIO_ENCODING_ULINEAR_LE, prec, valid,			\
+	 linear##target##_##target##_to_linear##prec,			\
+		linear##prec##_##valid##_to_linear##target},		\
+	{AUDIO_ENCODING_ULINEAR_BE, prec, valid,			\
+	 linear##target##_##target##_to_linear##prec,			\
+		linear##prec##_##valid##_to_linear##target},
+#if NMULAW > 0
+#define MULAW_TABLE(prec, valid, target) 				\
+	{AUDIO_ENCODING_ULAW, 8, 8,					\
+	 linear##prec##_##valid##_to_mulaw,				\
+	 mulaw_to_linear##target},					\
+	{AUDIO_ENCODING_ALAW, 8, 8,					\
+	 linear##prec##_##valid##_to_alaw,				\
+	 alaw_to_linear##target},
+#endif
 /*
  * 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, linear16_to_linear8},
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 linear8_to_linear16, linear16_to_linear8},
-	{AUDIO_ENCODING_ULINEAR_LE, 8, 8,
-	 change_sign8, change_sign8},
+	TABLE_LIST(32, 32, 8)
+	TABLE_LIST(24, 32, 8)
+	TABLE_LIST(24, 24, 8)
+	TABLE_LIST(16, 16, 8)
+	TABLE_LIST(8, 8, 8)
+#if NMULAW > 0
+	MULAW_TABLE(8, 8, 8)
+#endif
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table u8_table[] = {
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 linear8_to_linear16, linear16_to_linear8},
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 linear8_to_linear16, linear16_to_linear8},
-	{AUDIO_ENCODING_SLINEAR_LE, 8, 8,
-	 change_sign8, change_sign8},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 linear8_to_linear16, linear16_to_linear8},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 linear8_to_linear16, linear16_to_linear8},
+	TABLE_LIST(32, 32, 8)
+	TABLE_LIST(24, 32, 8)
+	TABLE_LIST(24, 24, 8)
+	TABLE_LIST(16, 16, 8)
+	TABLE_LIST(8, 8, 8)
+#if NMULAW > 0
+	MULAW_TABLE(8, 8, 8)
+#endif
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table s16le_table[] = {
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 swap_bytes, swap_bytes},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 change_sign16, change_sign16},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 swap_bytes_change_sign16, swap_bytes_change_sign16},
+	TABLE_LIST(32, 32, 16)
+	TABLE_LIST(24, 32, 16)
+	TABLE_LIST(24, 24, 16)
+	TABLE_LIST(16, 16, 16)
+	TABLE_LIST(8, 8, 16)
+#if NMULAW > 0
+	MULAW_TABLE(16, 16, 16)
+#endif
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table s16be_table[] = {
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 swap_bytes, swap_bytes},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 change_sign16, change_sign16},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 swap_bytes_change_sign16, swap_bytes_change_sign16},
+	TABLE_LIST(32, 32, 16)
+	TABLE_LIST(24, 32, 16)
+	TABLE_LIST(24, 24, 16)
+	TABLE_LIST(16, 16, 16)
+	TABLE_LIST(8, 8, 16)
+#if NMULAW > 0
+	MULAW_TABLE(16, 16, 16)
+#endif
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table u16le_table[] = {
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 change_sign16, change_sign16},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 swap_bytes, swap_bytes},
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 swap_bytes_change_sign16, swap_bytes_change_sign16},
+	TABLE_LIST(32, 32, 16)
+	TABLE_LIST(24, 32, 16)
+	TABLE_LIST(24, 24, 16)
+	TABLE_LIST(16, 16, 16)
+	TABLE_LIST(8, 8, 16)
+#if NMULAW > 0
+	MULAW_TABLE(16, 16, 16)
+#endif
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table u16be_table[] = {
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 change_sign16, change_sign16},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 swap_bytes, swap_bytes},
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 swap_bytes_change_sign16, swap_bytes_change_sign16},
+	TABLE_LIST(32, 32, 16)
+	TABLE_LIST(24, 32, 16)
+	TABLE_LIST(24, 24, 16)
+	TABLE_LIST(16, 16, 16)
+	TABLE_LIST(8, 8, 16)
+#if NMULAW > 0
+	MULAW_TABLE(16, 16, 16)
+#endif
 	{0, 0, 0, NULL, NULL}};
+static const struct conv_table s24le_table[] = {
+	TABLE_LIST(32, 32, 24)
+	TABLE_LIST(24, 32, 24)
+	TABLE_LIST(24, 24, 24)
+	TABLE_LIST(16, 16, 24)
+	TABLE_LIST(8, 8, 24)
 #if NMULAW > 0
+	MULAW_TABLE(24, 24, 24)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table s24be_table[] = {
+	TABLE_LIST(32, 32, 24)
+	TABLE_LIST(24, 32, 24)
+	TABLE_LIST(24, 24, 24)
+	TABLE_LIST(16, 16, 24)
+	TABLE_LIST(8, 8, 24)
+#if NMULAW > 0
+	MULAW_TABLE(24, 24, 24)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table u24le_table[] = {
+	TABLE_LIST(32, 32, 24)
+	TABLE_LIST(24, 32, 24)
+	TABLE_LIST(24, 24, 24)
+	TABLE_LIST(16, 16, 24)
+	TABLE_LIST(8, 8, 24)
+#if NMULAW > 0
+	MULAW_TABLE(24, 24, 24)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table u24be_table[] = {
+	TABLE_LIST(32, 32, 24)
+	TABLE_LIST(24, 32, 24)
+	TABLE_LIST(24, 24, 24)
+	TABLE_LIST(16, 16, 24)
+	TABLE_LIST(8, 8, 24)
+#if NMULAW > 0
+	MULAW_TABLE(24, 24, 24)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table s32le_table[] = {
+	TABLE_LIST(32, 32, 32)
+	TABLE_LIST(24, 32, 32)
+	TABLE_LIST(24, 24, 32)
+	TABLE_LIST(16, 16, 32)
+	TABLE_LIST(8, 8, 32)
+#if NMULAW > 0
+	MULAW_TABLE(32, 32, 32)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table s32be_table[] = {
+	TABLE_LIST(32, 32, 32)
+	TABLE_LIST(24, 32, 32)
+	TABLE_LIST(24, 24, 32)
+	TABLE_LIST(16, 16, 32)
+	TABLE_LIST(8, 8, 32)
+#if NMULAW > 0
+	MULAW_TABLE(32, 32, 32)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table u32le_table[] = {
+	TABLE_LIST(32, 32, 32)
+	TABLE_LIST(24, 32, 32)
+	TABLE_LIST(24, 24, 32)
+	TABLE_LIST(16, 16, 32)
+	TABLE_LIST(8, 8, 32)
+#if NMULAW > 0
+	MULAW_TABLE(32, 32, 32)
+#endif
+	{0, 0, 0, NULL, NULL}};
+static const struct conv_table u32be_table[] = {
+	TABLE_LIST(32, 32, 32)
+	TABLE_LIST(24, 32, 32)
+	TABLE_LIST(24, 24, 32)
+	TABLE_LIST(16, 16, 32)
+	TABLE_LIST(8, 8, 32)
+#if NMULAW > 0
+	MULAW_TABLE(32, 32, 32)
+#endif
+	{0, 0, 0, NULL, NULL}};
+#if NMULAW > 0
+#define MULAW_LIST(prec, valid, target) 				\
+	{AUDIO_ENCODING_SLINEAR_LE, prec, valid,			\
+	 mulaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_mulaw},				\
+	{AUDIO_ENCODING_SLINEAR_BE, prec, valid,			\
+	 mulaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_mulaw},				\
+	{AUDIO_ENCODING_ULINEAR_LE, prec, valid,			\
+	 mulaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_mulaw},				\
+	{AUDIO_ENCODING_ULINEAR_BE, prec, valid,			\
+	 mulaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_mulaw},
+
+#define ALAW_LIST(prec, valid, target) 					\
+	{AUDIO_ENCODING_SLINEAR_LE, prec, valid,			\
+	 alaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_alaw},				\
+	{AUDIO_ENCODING_SLINEAR_BE, prec, valid,			\
+	 alaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_alaw},				\
+	{AUDIO_ENCODING_ULINEAR_LE, prec, valid,			\
+	 alaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_alaw},				\
+	{AUDIO_ENCODING_ULINEAR_BE, prec, valid,			\
+	 alaw_to_linear##target,					\
+	 linear##prec##_##valid##_to_alaw},
+
 static const struct conv_table mulaw_table[] = {
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 mulaw_to_linear16, linear16_to_mulaw},
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 mulaw_to_linear16, linear16_to_mulaw},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 mulaw_to_linear16, linear16_to_mulaw},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 mulaw_to_linear16, linear16_to_mulaw},
+	MULAW_LIST(32, 32, 32)
+	MULAW_LIST(24, 32, 24)
+	MULAW_LIST(24, 24, 24)
+	MULAW_LIST(16, 16, 16)
 	{AUDIO_ENCODING_SLINEAR_LE, 8, 8,
 	 mulaw_to_linear8, linear8_to_mulaw},
 	{AUDIO_ENCODING_ULINEAR_LE, 8, 8,
 	 mulaw_to_linear8, linear8_to_mulaw},
 	{0, 0, 0, NULL, NULL}};
 static const struct conv_table alaw_table[] = {
-	{AUDIO_ENCODING_SLINEAR_LE, 16, 16,
-	 alaw_to_linear16, linear16_to_alaw},
-	{AUDIO_ENCODING_SLINEAR_BE, 16, 16,
-	 alaw_to_linear16, linear16_to_alaw},
-	{AUDIO_ENCODING_ULINEAR_LE, 16, 16,
-	 alaw_to_linear16, linear16_to_alaw},
-	{AUDIO_ENCODING_ULINEAR_BE, 16, 16,
-	 alaw_to_linear16, linear16_to_alaw},
+	ALAW_LIST(32, 32, 32)
+	ALAW_LIST(24, 32, 24)
+	ALAW_LIST(24, 24, 24)
+	ALAW_LIST(16, 16, 16)
 	{AUDIO_ENCODING_SLINEAR_LE, 8, 8,
 	 alaw_to_linear8, linear8_to_alaw},
 	{AUDIO_ENCODING_ULINEAR_LE, 8, 8,
@@ -351,124 +481,193 @@ DEFINE_FILTER(swap_bytes_change_sign16)
 	return 0;
 }
 
-DEFINE_FILTER(linear8_to_linear16)
-{
-	stream_filter_t *this;
-	int m, err, enc_dst, enc_src;
-
-	this = (stream_filter_t *)self;
-	max_used = (max_used + 1) & ~1; /* round up to even */
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used / 2)))
-		return err;
-	m = (dst->end - dst->start) & ~1;
-	m = min(m, max_used);
-	enc_dst = dst->param.encoding;
-	enc_src = this->src->param.encoding;
-	if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
-	     && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
-	    || (enc_src == AUDIO_ENCODING_ULINEAR_LE
-		&& enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
-		/*
-		 * slinear8 -> slinear16_le
-		 * ulinear8 -> ulinear16_le
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = 0;
-			d[1] = s[0];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
-		    && enc_dst == AUDIO_ENCODING_SLINEAR_BE)
-		   || (enc_src == AUDIO_ENCODING_ULINEAR_LE
-		       && enc_dst == AUDIO_ENCODING_ULINEAR_BE)) {
-		/*
-		 * slinear8 -> slinear16_be
-		 * ulinear8 -> ulinear16_be
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = s[0];
-			d[1] = 0;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
-		    && enc_dst == AUDIO_ENCODING_ULINEAR_LE)
-		   || (enc_src == AUDIO_ENCODING_ULINEAR_LE
-		       && enc_dst == AUDIO_ENCODING_SLINEAR_LE)) {
-		/*
-		 * slinear8 -> ulinear16_le
-		 * ulinear8 -> slinear16_le
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = 0;
-			d[1] = s[0] ^ 0x80;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else {
-		/*
-		 * slinear8 -> ulinear16_be
-		 * ulinear8 -> slinear16_be
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = s[0] ^ 0x80;
-			d[1] = 0;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	}
-	return 0;
-}
-
-DEFINE_FILTER(linear16_to_linear8)
-{
-	stream_filter_t *this;
-	int m, err, enc_src, enc_dst;
-
-	this = (stream_filter_t *)self;
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used * 2)))
-		return err;
-	m = dst->end - dst->start;
-	m = min(m, max_used);
-	enc_dst = dst->param.encoding;
-	enc_src = this->src->param.encoding;
-	if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
-	     && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
-	    || (enc_src == AUDIO_ENCODING_ULINEAR_LE
-		&& enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
-		/*
-		 * slinear16_le -> slinear8
-		 * ulinear16_le -> ulinear8
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = s[1];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE
-		    && enc_dst == AUDIO_ENCODING_ULINEAR_LE)
-		   || (enc_src == AUDIO_ENCODING_ULINEAR_LE
-		       && enc_dst == AUDIO_ENCODING_SLINEAR_LE)) {
-		/*
-		 * slinear16_le -> ulinear8
-		 * ulinear16_le -> slinear8
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = s[1] ^ 0x80;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_BE
-		    && enc_dst == AUDIO_ENCODING_SLINEAR_LE)
-		   || (enc_src == AUDIO_ENCODING_ULINEAR_BE
-		       && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {
-		/*
-		 * slinear16_be -> slinear8
-		 * ulinear16_be -> ulinear8
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = s[0];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	} else {
-		/*
-		 * slinear16_be -> ulinear8
-		 * ulinear16_be -> slinear8
-		 */
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = s[0] ^ 0x80;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-	}
-	return 0;
-}
+#define LINEARN_LINEAR(n_prec, n_validbits, t_prec)			\
+	DEFINE_FILTER(linear##n_prec##_##n_validbits##_to_linear##t_prec)\
+{									\
+	stream_filter_t *this;						\
+	int m, err, enc_dst, enc_src;					\
+	int target, valid, hw, i, j;					\
+									\
+	hw = n_prec / NBBY;						\
+	valid = n_validbits / NBBY;					\
+	target = t_prec / NBBY;						\
+	this = (stream_filter_t *)self;					\
+	max_used = ((max_used / hw) * hw) & ~1;				\
+									\
+	if ((err = this->prev->fetch_to(sc, this->prev, this->src,	\
+			max_used)))					\
+		return err;						\
+	m = (((dst->end - dst->start) / target) * target) & ~1;		\
+	m = min(m, max_used * hw / target);				\
+	enc_dst = dst->param.encoding;					\
+	enc_src = this->src->param.encoding;				\
+	if ((enc_src == AUDIO_ENCODING_SLINEAR_LE			\
+	     && enc_dst == AUDIO_ENCODING_SLINEAR_LE)			\
+	    || (enc_src == AUDIO_ENCODING_ULINEAR_LE			\
+		&& enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {		\
+		/*							\
+		 * slinearNle -> slinearNle				\
+		 * ulinearNle -> ulinearNle				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0)				\
+					d[--j] = s[--i];		\
+			} else {					\
+				while (i > 0)				\
+					d[--j] = s[--i];		\
+				while (j > 0)				\
+					d[--j] = 0;			\
+			}						\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_LE		\
+		    && enc_dst == AUDIO_ENCODING_SLINEAR_BE)		\
+		   || (enc_src == AUDIO_ENCODING_ULINEAR_LE		\
+		       && enc_dst == AUDIO_ENCODING_ULINEAR_BE)) {	\
+		/*							\
+		 * slinearNle -> slinearNbe				\
+		 * ulinearNle -> ulinearNbe				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0) {				\
+					d[--j] = s[target - i];		\
+					i--;				\
+				}					\
+			} else {					\
+				while (j > i)				\
+					d[--j] = 0;			\
+				while (j > 0) {				\
+					d[--j] = s[target - i];		\
+					i--;				\
+				}					\
+			}						\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	} else if ((enc_src == AUDIO_ENCODING_ULINEAR_BE		\
+		    && enc_dst == AUDIO_ENCODING_SLINEAR_LE)		\
+		   || (enc_src == AUDIO_ENCODING_SLINEAR_BE		\
+		       && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {	\
+		/*							\
+		 * ulinearNbe -> slinearNle				\
+		 * slinearNbe -> ulinearNle				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0) {				\
+					d[--j] = s[valid - i];		\
+					i--;				\
+				}					\
+			} else {					\
+				while (j > 0) {				\
+					d[--j] = s[valid - i];		\
+					i--;				\
+				}					\
+				while (j > 0)				\
+					d[--j] = 0;			\
+			}						\
+			d[target - 1] ^= 0x80;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_BE		\
+		    && enc_dst == AUDIO_ENCODING_SLINEAR_LE)		\
+		   || (enc_src == AUDIO_ENCODING_ULINEAR_BE		\
+		       && enc_dst == AUDIO_ENCODING_ULINEAR_LE)) {	\
+		/*							\
+		 * slinearNbe -> slinearNle				\
+		 * ulinearNbe -> ulinearNle				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0) {				\
+					d[--j] = s[valid - i];		\
+					i--;				\
+				}					\
+			} else {					\
+				while (j > 0) {				\
+					d[--j] = s[valid - i];		\
+					i--;				\
+				}					\
+				while (j > 0)				\
+					d[--j] = 0;			\
+			}						\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	} else if ((enc_src == AUDIO_ENCODING_SLINEAR_BE		\
+		    && enc_dst == AUDIO_ENCODING_ULINEAR_BE)		\
+		   || (enc_src == AUDIO_ENCODING_ULINEAR_BE		\
+		       && enc_dst == AUDIO_ENCODING_SLINEAR_BE)) {	\
+		/*							\
+		 * slinearNbe -> ulinearNbe				\
+		 * ulinearNbe -> slinearNbe				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0) {				\
+					d[target - j] = s[target - j];	\
+					j--;				\
+				}					\
+			} else {					\
+				while (i > 0) {				\
+					d[target - j] = s[target - j];	\
+					j--;				\
+					i--;				\
+				}					\
+				while (j > 0)				\
+					d[target - j] = 0;		\
+			}						\
+			d[0] ^= 0x80;					\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	} else {							\
+		/*							\
+		 * slinearNle -> ulinearNle				\
+		 * ulinearNle -> slinearNle				\
+		 */							\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, target, m) {	\
+			i = valid;					\
+			j = target;					\
+			if (j < i) {					\
+				while (j > 0)				\
+					d[--j] = s[--i];		\
+			} else {					\
+				while (i > 0)				\
+					d[--j] = s[--i];		\
+				while (j > 0)				\
+					d[--j] = 0;			\
+			}						\
+			d[target - 1] ^= 0x80;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+	}								\
+	return 0;							\
+}
+
+LINEARN_LINEAR(32, 32, 32);
+LINEARN_LINEAR(32, 32, 24);
+LINEARN_LINEAR(32, 32, 16);
+LINEARN_LINEAR(32, 32, 8);
+LINEARN_LINEAR(24, 32, 32);
+LINEARN_LINEAR(24, 32, 24);
+LINEARN_LINEAR(24, 32, 16);
+LINEARN_LINEAR(24, 32, 8);
+LINEARN_LINEAR(24, 24, 32);
+LINEARN_LINEAR(24, 24, 24);
+LINEARN_LINEAR(24, 24, 16);
+LINEARN_LINEAR(24, 24, 8);
+LINEARN_LINEAR(16, 16, 32);
+LINEARN_LINEAR(16, 16, 24);
+LINEARN_LINEAR(16, 16, 16);
+LINEARN_LINEAR(16, 16, 8);
+LINEARN_LINEAR(8, 8, 32);
+LINEARN_LINEAR(8, 8, 24);
+LINEARN_LINEAR(8, 8, 16);
+LINEARN_LINEAR(8, 8, 8);
 
 /**
  * Set appropriate parameters in `param,' and return the index in
@@ -531,24 +730,32 @@ auconv_set_converter(const struct audio_
 			table = s8_table;
 		else if (param->precision == 16)
 			table = s16le_table;
+		else if (param->precision == 32)
+			table = s32le_table;
 		break;
 	case AUDIO_ENCODING_SLINEAR_BE:
 		if (param->precision == 8)
 			table = s8_table;
 		else if (param->precision == 16)
 			table = s16be_table;
+		else if (param->precision == 32)
+			table = s32be_table;
 		break;
 	case AUDIO_ENCODING_ULINEAR_LE:
 		if (param->precision == 8)
 			table = u8_table;
 		else if (param->precision == 16)
 			table = u16le_table;
+		else if (param->precision == 32)
+			table = u32le_table;
 		break;
 	case AUDIO_ENCODING_ULINEAR_BE:
 		if (param->precision == 8)
 			table = u8_table;
 		else if (param->precision == 16)
 			table = u16be_table;
+		else if (param->precision == 32)
+			table = u32be_table;
 		break;
 #if NMULAW > 0
 	case AUDIO_ENCODING_ULAW:
@@ -620,7 +827,7 @@ auconv_rateconv_supportable(u_int encodi
 	if (encoding != AUDIO_ENCODING_SLINEAR_LE
 	    && encoding != AUDIO_ENCODING_SLINEAR_BE)
 		return false;
-	if (precision != 16 && precision != 24 && precision != 32)
+	if (precision != 8 && precision != 16 && precision != 24 && precision != 32)
 		return false;
 	if (precision < validbits)
 		return false;

Index: src/sys/dev/auconv.h
diff -u src/sys/dev/auconv.h:1.16 src/sys/dev/auconv.h:1.17
--- src/sys/dev/auconv.h:1.16	Wed Nov 23 23:07:31 2011
+++ src/sys/dev/auconv.h	Tue Jun 20 07:21:50 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: auconv.h,v 1.16 2011/11/23 23:07:31 jmcneill Exp $	*/
+/*	$NetBSD: auconv.h,v 1.17 2017/06/20 07:21:50 nat Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -62,8 +62,30 @@ extern stream_filter_factory_t change_si
 extern stream_filter_factory_t swap_bytes;
 extern stream_filter_factory_t swap_bytes_change_sign16;
 /* Byte expansion/contraction */
-extern stream_filter_factory_t linear8_to_linear16;
-extern stream_filter_factory_t linear16_to_linear8;
+extern stream_filter_factory_t linear32_32_to_linear32;
+extern stream_filter_factory_t linear32_32_to_linear24;
+extern stream_filter_factory_t linear32_32_to_linear16;
+extern stream_filter_factory_t linear32_32_to_linear8;
+extern stream_filter_factory_t linear24_32_to_linear32;
+extern stream_filter_factory_t linear24_32_to_linear24;
+extern stream_filter_factory_t linear24_32_to_linear16;
+extern stream_filter_factory_t linear24_32_to_linear8;
+extern stream_filter_factory_t linear24_24_to_linear32;
+extern stream_filter_factory_t linear24_24_to_linear24;
+extern stream_filter_factory_t linear24_24_to_linear16;
+extern stream_filter_factory_t linear24_24_to_linear8;
+extern stream_filter_factory_t linear16_16_to_linear32;
+extern stream_filter_factory_t linear16_16_to_linear24;
+extern stream_filter_factory_t linear16_16_to_linear16;
+extern stream_filter_factory_t linear16_16_to_linear8;
+extern stream_filter_factory_t linear8_8_to_linear32;
+extern stream_filter_factory_t linear8_8_to_linear24;
+extern stream_filter_factory_t linear8_8_to_linear16;
+extern stream_filter_factory_t linear8_8_to_linear8;
+
+#define linear16_to_linear8 linear_16_16_to_linear8
+#define linear8_to_linear16 linear_8_8_to_linear16
+
 /* sampling rate conversion (aurateconv.c) */
 extern stream_filter_factory_t aurateconv;
 

Index: src/sys/dev/mulaw.c
diff -u src/sys/dev/mulaw.c:1.28 src/sys/dev/mulaw.c:1.29
--- src/sys/dev/mulaw.c:1.28	Wed Nov 23 23:07:31 2011
+++ src/sys/dev/mulaw.c	Tue Jun 20 07:21:50 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mulaw.c,v 1.28 2011/11/23 23:07:31 jmcneill Exp $	*/
+/*	$NetBSD: mulaw.c,v 1.29 2017/06/20 07:21:50 nat Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mulaw.c,v 1.28 2011/11/23 23:07:31 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mulaw.c,v 1.29 2017/06/20 07:21:50 nat Exp $");
 
 #include <sys/types.h>
 #include <sys/systm.h>
@@ -295,80 +295,117 @@ DEFINE_FILTER(mulaw_to_linear8)
 	return 0;
 }
 
-DEFINE_FILTER(mulaw_to_linear16)
-{
-	stream_filter_t *this;
-	int m, err;
-
-	this = (stream_filter_t *)self;
-	max_used = (max_used + 1) & ~1; /* round up to even */
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used / 2)))
-		return err;
-	m = (dst->end - dst->start) & ~1;
-	m = min(m, max_used);
-	switch (dst->param.encoding) {
-	case AUDIO_ENCODING_ULINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = mulawtolin16[s[0]][1];
-			d[1] = mulawtolin16[s[0]][0];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = mulawtolin16[s[0]][0];
-			d[1] = mulawtolin16[s[0]][1];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = mulawtolin16[s[0]][1];
-			d[1] = mulawtolin16[s[0]][0] ^ 0x80;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = mulawtolin16[s[0]][0] ^ 0x80;
-			d[1] = mulawtolin16[s[0]][1];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	}
-	return 0;
+#define MULAWTOLINEARN(n_prec) 						\
+DEFINE_FILTER(mulaw_to_linear##n_prec)					\
+{									\
+	stream_filter_t *this;						\
+	int hw, j, m, err;						\
+									\
+	hw = n_prec / NBBY;						\
+	this = (stream_filter_t *)self;					\
+	max_used = (max_used + 1) & ~1; /* round up to even */		\
+	if ((err = this->prev->fetch_to(sc, this->prev,			\
+		this->src, max_used / hw)))				\
+		return err;						\
+	m = (dst->end - dst->start) & ~1;				\
+	m = min(m, max_used);						\
+	switch (dst->param.encoding) {					\
+	case AUDIO_ENCODING_ULINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[hw - 2] = mulawtolin16[s[0]][1];		\
+			d[hw - 1] = mulawtolin16[s[0]][0];		\
+			while (j > 0)					\
+				d[--j] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[0] = mulawtolin16[s[0]][0];			\
+			d[1] = mulawtolin16[s[0]][1];			\
+			while (j < hw)					\
+				d[j++] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[hw - 2] = mulawtolin16[s[0]][1];		\
+			d[hw - 1] = mulawtolin16[s[0]][0] ^ 0x80;	\
+			while (j > 0)					\
+				d[--j] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[0] = mulawtolin16[s[0]][0] ^ 0x80;		\
+			d[1] = mulawtolin16[s[0]][1];			\
+			while (j < hw)					\
+				d[j++] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	default:							\
+		aprint_error(						\
+		    "%s: encoding must be [s/u]linear_[le/be]\n",	\
+		    __func__);						\
+		break;							\
+	}								\
+	return 0;							\
+}								
+
+MULAWTOLINEARN(32)
+MULAWTOLINEARN(24)
+MULAWTOLINEARN(16)
+
+#define LINEARNTOMULAW(n_prec, n_valid)					\
+DEFINE_FILTER(linear##n_prec##_##n_valid##_to_mulaw)			\
+{									\
+	stream_filter_t *this;						\
+	int hw, m, err;							\
+									\
+	hw = n_prec / NBBY;						\
+	this = (stream_filter_t *)self;					\
+	if ((err = this->prev->fetch_to(sc, this->prev, this->src,	\
+		 max_used * hw)))					\
+		return err;						\
+	m = dst->end - dst->start;					\
+	m = min(m, max_used);						\
+	switch (this->src->param.encoding) {				\
+	case AUDIO_ENCODING_SLINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintomulaw[s[hw - 1] ^ 0x80];		\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintomulaw[s[0] ^ 0x80];			\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintomulaw[s[hw - 1]];			\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintomulaw[s[0]];			\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	default:							\
+		aprint_error(						\
+		    "%s: encoding must be [s/u]linear_[le/be]\n",	\
+		    __func__);						\
+		break;							\
+	}								\
+	return 0;							\
 }
 
-DEFINE_FILTER(linear16_to_mulaw)
-{
-	stream_filter_t *this;
-	int m, err;
-
-	this = (stream_filter_t *)self;
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used * 2)))
-		return err;
-	m = dst->end - dst->start;
-	m = min(m, max_used);
-	switch (this->src->param.encoding) {
-	case AUDIO_ENCODING_SLINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintomulaw[s[1] ^ 0x80];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintomulaw[s[0] ^ 0x80];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintomulaw[s[1]];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintomulaw[s[0]];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	}
-	return 0;
-}
+LINEARNTOMULAW(32, 32)
+LINEARNTOMULAW(24, 32)
+LINEARNTOMULAW(24, 24)
+LINEARNTOMULAW(16, 16)
 
 DEFINE_FILTER(linear8_to_mulaw)
 {
@@ -414,46 +451,70 @@ DEFINE_FILTER(alaw_to_linear8)
 	return 0;
 }
 
-DEFINE_FILTER(alaw_to_linear16)
-{
-	stream_filter_t *this;
-	int m, err;
-
-	this = (stream_filter_t *)self;
-	max_used = (max_used + 1) & ~1; /* round up to even */
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used / 2)))
-		return err;
-	m = (dst->end - dst->start) & ~1;
-	m = min(m, max_used);
-	switch (dst->param.encoding) {
-	case AUDIO_ENCODING_ULINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = alawtolin16[s[0]][1];
-			d[1] = alawtolin16[s[0]][0];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = alawtolin16[s[0]][0];
-			d[1] = alawtolin16[s[0]][1];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = alawtolin16[s[0]][1];
-			d[1] = alawtolin16[s[0]][0] ^ 0x80;
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
-			d[0] = alawtolin16[s[0]][0] ^ 0x80;
-			d[1] = alawtolin16[s[0]][1];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	}
-	return 0;
+#define ALAWTOLINEARN(n_prec) 						\
+DEFINE_FILTER(alaw_to_linear##n_prec)					\
+{									\
+	stream_filter_t *this;						\
+	int hw, j, m, err;						\
+									\
+	hw = n_prec / NBBY;						\
+	this = (stream_filter_t *)self;					\
+	max_used = (max_used + 1) & ~1; /* round up to even */		\
+	if ((err = this->prev->fetch_to(sc, this->prev, this->src,	\
+		 max_used / hw)))					\
+		return err;						\
+	m = (dst->end - dst->start) & ~1;				\
+	m = min(m, max_used);						\
+	switch (dst->param.encoding) {					\
+	case AUDIO_ENCODING_ULINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[hw - 2] = alawtolin16[s[0]][1];		\
+			d[hw - 1] = alawtolin16[s[0]][0];		\
+			while (j > 0)					\
+				d[--j] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[0] = alawtolin16[s[0]][0];			\
+			d[1] = alawtolin16[s[0]][1];			\
+			while (j < hw)					\
+				d[j++] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[hw - 2] = alawtolin16[s[0]][1];		\
+			d[hw - 1] = alawtolin16[s[0]][0] ^ 0x80;	\
+			while (j > 0)					\
+				d[--j] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, 1, dst, hw, m) {	\
+			j = hw - 2;					\
+			d[0] = alawtolin16[s[0]][0] ^ 0x80;		\
+			d[1] = alawtolin16[s[0]][1];			\
+			while (j < hw)	 				\
+				d[j++] = 0;				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	default:							\
+		aprint_error(						\
+		    "%s: encoding must be [s/u]linear_[le/be]\n",	\
+		    __func__);						\
+		break;							\
+	}								\
+	return 0;							\
 }
 
+ALAWTOLINEARN(32)
+ALAWTOLINEARN(24)
+ALAWTOLINEARN(16)
+
 DEFINE_FILTER(linear8_to_alaw)
 {
 	stream_filter_t *this;
@@ -476,37 +537,50 @@ DEFINE_FILTER(linear8_to_alaw)
 	return 0;
 }
 
-DEFINE_FILTER(linear16_to_alaw)
-{
-	stream_filter_t *this;
-	int m, err;
-
-	this = (stream_filter_t *)self;
-	if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used * 2)))
-		return err;
-	m = dst->end - dst->start;
-	m = min(m, max_used);
-	switch (this->src->param.encoding) {
-	case AUDIO_ENCODING_SLINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintoalaw[s[1] ^ 0x80];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_SLINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintoalaw[s[0] ^ 0x80];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_LE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintoalaw[s[1]];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	case AUDIO_ENCODING_ULINEAR_BE:
-		FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
-			d[0] = lintoalaw[s[0]];
-		} FILTER_LOOP_EPILOGUE(this->src, dst);
-		break;
-	}
-	return 0;
+#define LINEARNTOALAW(n_prec, n_valid)					\
+DEFINE_FILTER(linear##n_prec##_##n_valid##_to_alaw)			\
+{									\
+	stream_filter_t *this;						\
+	int hw, m, err;							\
+									\
+	hw = n_prec / NBBY;						\
+	this = (stream_filter_t *)self;					\
+	if ((err = this->prev->fetch_to(sc, this->prev, this->src,	\
+			max_used * hw)))				\
+		return err;						\
+	m = dst->end - dst->start;					\
+	m = min(m, max_used);						\
+	switch (this->src->param.encoding) {				\
+	case AUDIO_ENCODING_SLINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintoalaw[s[hw - 1] ^ 0x80];		\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_SLINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintoalaw[s[0] ^ 0x80];			\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_LE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintoalaw[s[hw - 1]];			\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	case AUDIO_ENCODING_ULINEAR_BE:					\
+		FILTER_LOOP_PROLOGUE(this->src, hw, dst, 1, m) {	\
+			d[0] = lintoalaw[s[0]];				\
+		} FILTER_LOOP_EPILOGUE(this->src, dst);			\
+		break;							\
+	default:							\
+		aprint_error(						\
+		    "%s: encoding must be [s/u]linear_[le/be]\n",	\
+		    __func__);						\
+		break;							\
+	}								\
+	return 0;							\
 }
+
+LINEARNTOALAW(32, 32)
+LINEARNTOALAW(24, 32)
+LINEARNTOALAW(24, 24)
+LINEARNTOALAW(16, 16)

Index: src/sys/dev/mulaw.h
diff -u src/sys/dev/mulaw.h:1.20 src/sys/dev/mulaw.h:1.21
--- src/sys/dev/mulaw.h:1.20	Mon Apr 28 20:23:47 2008
+++ src/sys/dev/mulaw.h	Tue Jun 20 07:21:50 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mulaw.h,v 1.20 2008/04/28 20:23:47 martin Exp $	*/
+/*	$NetBSD: mulaw.h,v 1.21 2017/06/20 07:21:50 nat Exp $	*/
 
 /*-
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -33,17 +33,36 @@
 #define _SYS_DEV_MULAW_H_
 #include <dev/audio_if.h>
 
+/* Convert 8-bit mu-law to/from 32 bit unsigned/signed linear. */
+extern stream_filter_factory_t mulaw_to_linear32;
+extern stream_filter_factory_t linear32_32_to_mulaw;
+/* Convert 8-bit mu-law to/from 24 bit unsigned/signed linear. */
+extern stream_filter_factory_t mulaw_to_linear24;
+extern stream_filter_factory_t linear24_24_to_mulaw;
+extern stream_filter_factory_t linear24_32_to_mulaw;
 /* Convert 8-bit mu-law to/from 16 bit unsigned/signed linear. */
 extern stream_filter_factory_t mulaw_to_linear16;
-extern stream_filter_factory_t linear16_to_mulaw;
+extern stream_filter_factory_t linear16_16_to_mulaw;
+#define linear16_to_mulaw linear_16_16_to_mulaw;
 /* Convert 8-bit mu-law to/from 8 bit unsigned/signed linear. */
 extern stream_filter_factory_t mulaw_to_linear8;
 extern stream_filter_factory_t linear8_to_mulaw;
-/* Convert 8-bit A-law to/from 16 bit unsigned/signed linear. */
+#define linear8_8_to_mulaw linear8_to_mulaw
+
+/* Convert 8-bit alaw to/from 32 bit unsigned/signed linear. */
+extern stream_filter_factory_t alaw_to_linear32;
+extern stream_filter_factory_t linear32_32_to_alaw;
+/* Convert 8-bit alaw to/from 24 bit unsigned/signed linear. */
+extern stream_filter_factory_t alaw_to_linear24;
+extern stream_filter_factory_t linear24_24_to_alaw;
+extern stream_filter_factory_t linear24_32_to_alaw;
+/* Convert 8-bit alaw to/from 16 bit unsigned/signed linear. */
 extern stream_filter_factory_t alaw_to_linear16;
-extern stream_filter_factory_t linear16_to_alaw;
+extern stream_filter_factory_t linear16_16_to_alaw;
+#define linear16_to_alaw linear_16_16_to_alaw;
 /* Convert 8-bit A-law to/from 8 bit unsigned/signed linear. */
 extern stream_filter_factory_t alaw_to_linear8;
 extern stream_filter_factory_t linear8_to_alaw;
+#define linear8_8_to_alaw linear8_to_alaw
 
 #endif /* _SYS_DEV_MULAW_H_ */

Reply via email to