Add support for more formats. At present 24 bit formats do not work and

have been disabled.

Ok christos@.
This commit is contained in:
nat 2017-06-20 07:21:50 +00:00
parent 81cb5fdd19
commit 53adadbf58
4 changed files with 648 additions and 326 deletions

View File

@ -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 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; \
}
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;
}
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_format *formats, int nformats,
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 encoding, u_int precision, u_int validbits)
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;

View File

@ -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_sign16;
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;

View File

@ -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;
#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; \
}
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;
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)

View File

@ -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_ */