From: Abramo Bagnara Date: Sat, 25 Dec 1999 15:25:46 +0000 (+0000) Subject: Completed linear plugin X-Git-Tag: android-x86-9.0-r1~3424 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=8738da23d853224b0ac949ba28a1e247ca5c4e26;p=android-x86%2Fexternal-alsa-lib.git Completed linear plugin --- diff --git a/src/pcm/pcm_plugin_build.c b/src/pcm/pcm_plugin_build.c index 1fe60402..98c398a8 100644 --- a/src/pcm/pcm_plugin_build.c +++ b/src/pcm/pcm_plugin_build.c @@ -101,112 +101,96 @@ ssize_t snd_pcm_plugin_hardware_size(PLUGIN_BASE *pb, int channel, size_t trf_si unsigned int snd_pcm_plugin_formats(unsigned int formats) { + int linfmts = (SND_PCM_FMT_U8 | SND_PCM_FMT_S8 | + SND_PCM_FMT_U16_LE | SND_PCM_FMT_S16_LE | + SND_PCM_FMT_U16_BE | SND_PCM_FMT_S16_BE | + SND_PCM_FMT_U24_LE | SND_PCM_FMT_S16_LE | + SND_PCM_FMT_U24_BE | SND_PCM_FMT_S16_BE | + SND_PCM_FMT_U32_LE | SND_PCM_FMT_S32_LE | + SND_PCM_FMT_U32_BE | SND_PCM_FMT_S32_BE); formats |= SND_PCM_FMT_MU_LAW; #ifndef __KERNEL__ formats |= SND_PCM_FMT_A_LAW | SND_PCM_FMT_IMA_ADPCM; #endif - if (formats & (SND_PCM_FMT_U8|SND_PCM_FMT_S8| - SND_PCM_FMT_U16_LE|SND_PCM_FMT_S16_LE)) - formats |= SND_PCM_FMT_U8|SND_PCM_FMT_S8| - SND_PCM_FMT_U16_LE|SND_PCM_FMT_S16_LE; + + if (formats & linfmts) + formats |= linfmts; return formats; } +static int preferred_formats[] = { + SND_PCM_SFMT_S16_LE, + SND_PCM_SFMT_S16_BE, + SND_PCM_SFMT_U16_LE, + SND_PCM_SFMT_U16_BE, + SND_PCM_SFMT_S24_LE, + SND_PCM_SFMT_S24_BE, + SND_PCM_SFMT_U24_LE, + SND_PCM_SFMT_U24_BE, + SND_PCM_SFMT_S32_LE, + SND_PCM_SFMT_S32_BE, + SND_PCM_SFMT_U32_LE, + SND_PCM_SFMT_U32_BE, + SND_PCM_SFMT_S8, + SND_PCM_SFMT_U8 +}; + int snd_pcm_plugin_hwparams(snd_pcm_channel_params_t *params, snd_pcm_channel_info_t *hwinfo, snd_pcm_channel_params_t *hwparams) { memcpy(hwparams, params, sizeof(*hwparams)); if ((hwinfo->formats & (1 << params->format.format)) == 0) { - if ((snd_pcm_plugin_formats(hwinfo->formats) & (1 << params->format.format)) == 0) + int format = params->format.format; + if ((snd_pcm_plugin_formats(hwinfo->formats) & (1 << format)) == 0) return -EINVAL; - switch (params->format.format) { - case SND_PCM_SFMT_U8: - if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else { - return -EINVAL; - } - break; - case SND_PCM_SFMT_S8: - if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else { - return -EINVAL; - } - break; - case SND_PCM_SFMT_S16_LE: - if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else { - return -EINVAL; + if (snd_pcm_format_linear(format)) { + int width = snd_pcm_format_width(format); + int unsignd = snd_pcm_format_unsigned(format); + int big = snd_pcm_format_big_endian(format); + int format1; + int wid, width1=width; + for (wid = 0; wid < 4; ++wid) { + int end, big1 = big; + for (end = 0; end < 2; ++end) { + int sgn, unsignd1 = unsignd; + for (sgn = 0; sgn < 2; ++sgn) { + format1 = snd_pcm_build_linear_format(width1, unsignd1, big1); + if (format1 >= 0 && + hwinfo->formats & (1 << format1)) + goto _found; + unsignd1 = !unsignd1; + } + big1 = !big1; + } + width1 += 8; + if (width1 > 32) + width = 8; } - break; - case SND_PCM_SFMT_U16_LE: - if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else { - return -EINVAL; - } - break; - case SND_PCM_SFMT_MU_LAW: - if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else { - return -EINVAL; - } - break; + return -EINVAL; + _found: + hwparams->format.format = format1; + } else { + int i; + switch (format) { + case SND_PCM_SFMT_MU_LAW: #ifndef __KERNEL__ - case SND_PCM_SFMT_A_LAW: - if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else { - return -EINVAL; - } - case SND_PCM_SFMT_IMA_ADPCM: - if (hwinfo->formats & SND_PCM_FMT_S16_LE) { - hwparams->format.format = SND_PCM_SFMT_S16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_U16_LE) { - hwparams->format.format = SND_PCM_SFMT_U16_LE; - } else if (hwinfo->formats & SND_PCM_FMT_S8) { - hwparams->format.format = SND_PCM_SFMT_S8; - } else if (hwinfo->formats & SND_PCM_FMT_U8) { - hwparams->format.format = SND_PCM_SFMT_U8; - } else { + case SND_PCM_SFMT_A_LAW: + case SND_PCM_SFMT_IMA_ADPCM: +#endif + for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) { + int format1 = preferred_formats[i]; + if (hwinfo->formats & (1 << format1)) { + hwparams->format.format = format1; + break; + } + } + if (i == sizeof(preferred_formats)/sizeof(preferred_formats[0])) + return -EINVAL; + break; + default: return -EINVAL; } - break; -#endif - default: - return -EINVAL; } } diff --git a/src/pcm/plugin/linear.c b/src/pcm/plugin/linear.c index d5173ab9..7fbdf6a0 100644 --- a/src/pcm/plugin/linear.c +++ b/src/pcm/plugin/linear.c @@ -23,6 +23,8 @@ #include "../../include/driver.h" #include "../../include/pcm.h" #include "../../include/pcm_plugin.h" +#define bswap_16(x) __swab16((x)) +#define bswap_32(x) __swab32((x)) #else #include #include @@ -38,101 +40,152 @@ * Basic linear conversion plugin */ -typedef enum { - _8BIT_16BIT, - _8BIT_24BIT, - _8BIT_32BIT, - _16BIT_8BIT, - _16BIT_24BIT, - _16BIT_32BIT, - _24BIT_8BIT, - _24BIT_16BIT, - _24BIT_32BIT, - _32BIT_8BIT, - _32BIT_16BIT, - _32BIT_24BIT -} combination_t; - -typedef enum { - NONE = 0, - SOURCE = 1, - DESTINATION = 2, - BOTH = 3, - SIGN = 4, - SIGN_NONE = 4, - SIGN_SOURCE = 5, - SIGN_DESTINATION = 6, - SIGN_BOTH = 7, -} endian_t; - +typedef void (*conv_f)(void *src, void *dst, size_t size); + struct linear_private_data { - combination_t cmd; - endian_t endian; + int src_sample_size, dst_sample_size; + conv_f func; }; -static void linear_conv_8bit_16bit(unsigned char *src_ptr, - unsigned short *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = ((unsigned short)*src_ptr++) << 8; +#define CONV_FUNC(name, srctype, dsttype, val) \ +static void conv_##name(void *src_ptr, void *dst_ptr, size_t size) \ +{ \ + unsigned srctype *srcp = src_ptr; \ + unsigned dsttype *dstp = dst_ptr; \ + while (size--) { \ + unsigned srctype src = *srcp++; \ + *dstp++ = val; \ + } \ } -static void linear_conv_8bit_16bit_swap(unsigned char *src_ptr, - unsigned short *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = (unsigned short)*src_ptr++; -} +CONV_FUNC(8_sign, char, char, src ^ 0x80) -static void linear_conv_sign_8bit_16bit(unsigned char *src_ptr, - unsigned short *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = (((unsigned short)*src_ptr++) << 8) ^ 0x8000; -} +CONV_FUNC(8_16, char, short, (unsigned short)src << 8) +CONV_FUNC(8_16_end, char, short, (unsigned short)src) +CONV_FUNC(8_16_sign, char, short, (unsigned short)(src ^ 0x80) << 8) +CONV_FUNC(8_16_sign_end, char, short, (unsigned short)src ^ 0x80) -static void linear_conv_sign_8bit_16bit_swap(unsigned char *src_ptr, - unsigned short *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = ((unsigned short)*src_ptr++) ^ 0x80; -} +CONV_FUNC(8_32, char, long, (unsigned long)src << 24) +CONV_FUNC(8_32_end, char, long, (unsigned long)src) +CONV_FUNC(8_32_sign, char, long, (unsigned long)(src ^ 0x80) << 24) +CONV_FUNC(8_32_sign_end, char, long, (unsigned long)src ^ 0x80) -static void linear_conv_16bit_8bit(unsigned short *src_ptr, - unsigned char *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = (*src_ptr++) >> 8; -} +CONV_FUNC(16_8, short, char, src >> 8) +CONV_FUNC(16_end_8, short, char, src) +CONV_FUNC(16_8_sign, short, char, (src >> 8) ^ 0x80) +CONV_FUNC(16_end_8_sign, short, char, src ^ 0x80;) -static void linear_conv_16bit_8bit_swap(unsigned short *src_ptr, - unsigned char *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = (unsigned char)*src_ptr++; -} +CONV_FUNC(16_sign, short, short, src ^ 0x8000) +CONV_FUNC(16_end, short, short, bswap_16(src)) +CONV_FUNC(16_end_sign, short, short, bswap_16(src) ^ 0x8000) +CONV_FUNC(16_sign_end, short, short, bswap_16(src ^ 0x8000)) +CONV_FUNC(16_end_sign_end, short, short, src ^ 0x80) -static void linear_conv_sign_16bit_8bit(unsigned short *src_ptr, - unsigned char *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = (((unsigned short)*src_ptr++) >> 8) ^ 0x80; -} +CONV_FUNC(16_32, short, long, (unsigned long)src << 16) +CONV_FUNC(16_32_sign, short, long, (unsigned long)(src ^ 0x8000) << 16) +CONV_FUNC(16_32_end, short, long, (unsigned long)bswap_16(src)) +CONV_FUNC(16_32_sign_end, short, long, (unsigned long)bswap_16(src ^ 0x8000)) +CONV_FUNC(16_end_32, short, long, (unsigned long)bswap_16(src) << 16) +CONV_FUNC(16_end_32_sign, short, long, (unsigned long)(bswap_16(src) ^ 0x8000) << 16) +CONV_FUNC(16_end_32_end, short, long, (unsigned long)src) +CONV_FUNC(16_end_32_sign_end, short, long, (unsigned long)src ^ 0x80) + +CONV_FUNC(32_8, long, char, src >> 24) +CONV_FUNC(32_end_8, long, char, src) +CONV_FUNC(32_8_sign, long, char, (src >> 24) ^ 0x80) +CONV_FUNC(32_end_8_sign, long, char, src ^ 0x80;) + +CONV_FUNC(32_16, long, short, src >> 16) +CONV_FUNC(32_16_sign, long, short, (src >> 16) ^ 0x8000) +CONV_FUNC(32_16_end, long, short, bswap_16(src >> 16)) +CONV_FUNC(32_16_sign_end, long, short, bswap_16((src >> 16) ^ 0x8000)) +CONV_FUNC(32_end_16, long, short, bswap_16(src)) +CONV_FUNC(32_end_16_sign, long, short, bswap_16(src) ^ 0x8000) +CONV_FUNC(32_end_16_end, long, short, src) +CONV_FUNC(32_end_16_sign_end, long, short, src ^ 0x80) + +CONV_FUNC(32_sign, long, long, src ^ 0x80000000) +CONV_FUNC(32_end, long, long, bswap_32(src)) +CONV_FUNC(32_end_sign, long, long, bswap_32(src) ^ 0x80000000) +CONV_FUNC(32_sign_end, long, long, bswap_32(src) ^ 0x80) +CONV_FUNC(32_end_sign_end, long, long, src ^ 0x80) + +/* src_wid dst_wid src_endswap, dst_endswap, sign_swap */ +conv_f convert_functions[3][3][2][2][2] = { + NULL, /* 8->8: Nothing to do */ + conv_8_sign, /* 8->8 sign: conv_8_sign */ + NULL, /* 8->8 dst_end: Nothing to do */ + conv_8_sign, /* 8->8 dst_end sign: conv_8_sign */ + NULL, /* 8->8 src_end: Nothing to do */ + conv_8_sign, /* 8->8 src_end sign: conv_8_sign */ + NULL, /* 8->8 src_end dst_end: Nothing to do */ + conv_8_sign, /* 8->8 src_end dst_end sign: conv_8_sign */ + conv_8_16, /* 8->16: conv_8_16 */ + conv_8_16_sign, /* 8->16 sign: conv_8_16_sign */ + conv_8_16_end, /* 8->16 dst_end: conv_8_16_end */ + conv_8_16_sign_end, /* 8->16 dst_end sign: conv_8_16_sign_end */ + conv_8_16, /* 8->16 src_end: conv_8_16 */ + conv_8_16_sign, /* 8->16 src_end sign: conv_8_16_sign */ + conv_8_16_end, /* 8->16 src_end dst_end: conv_8_16_end */ + conv_8_16_sign_end, /* 8->16 src_end dst_end sign: conv_8_16_sign_end */ + conv_8_32, /* 8->32: conv_8_32 */ + conv_8_32_sign, /* 8->32 sign: conv_8_32_sign */ + conv_8_32_end, /* 8->32 dst_end: conv_8_32_end */ + conv_8_32_sign_end, /* 8->32 dst_end sign: conv_8_32_sign_end */ + conv_8_32, /* 8->32 src_end: conv_8_32 */ + conv_8_32_sign, /* 8->32 src_end sign: conv_8_32_sign */ + conv_8_32_end, /* 8->32 src_end dst_end: conv_8_32_end */ + conv_8_32_sign_end, /* 8->32 src_end dst_end sign: conv_8_32_sign_end */ + conv_16_8, /* 16->8: conv_16_8 */ + conv_16_8_sign, /* 16->8 sign: conv_16_8_sign */ + conv_16_8, /* 16->8 dst_end: conv_16_8 */ + conv_16_8_sign, /* 16->8 dst_end sign: conv_16_8_sign */ + conv_16_end_8, /* 16->8 src_end: conv_16_end_8 */ + conv_16_end_8_sign, /* 16->8 src_end sign: conv_16_end_8_sign */ + conv_16_end_8, /* 16->8 src_end dst_end: conv_16_end_8 */ + conv_16_end_8_sign, /* 16->8 src_end dst_end sign: conv_16_end_8_sign */ + NULL, /* 16->16: Nothing to do */ + conv_16_sign, /* 16->16 sign: conv_16_sign */ + conv_16_end, /* 16->16 dst_end: conv_16_end */ + conv_16_sign_end, /* 16->16 dst_end sign: conv_16_sign_end */ + conv_16_end, /* 16->16 src_end: conv_16_end */ + conv_16_end_sign, /* 16->16 src_end sign: conv_16_end_sign */ + NULL, /* 16->16 src_end dst_end: Nothing to do */ + conv_16_end_sign_end, /* 16->16 src_end dst_end sign: conv_16_end_sign_end */ + conv_16_32, /* 16->32: conv_16_32 */ + conv_16_32_sign, /* 16->32 sign: conv_16_32_sign */ + conv_16_32_end, /* 16->32 dst_end: conv_16_32_end */ + conv_16_32_sign_end, /* 16->32 dst_end sign: conv_16_32_sign_end */ + conv_16_end_32, /* 16->32 src_end: conv_16_end_32 */ + conv_16_end_32_sign, /* 16->32 src_end sign: conv_16_end_32_sign */ + conv_16_end_32_end, /* 16->32 src_end dst_end: conv_16_end_32_end */ + conv_16_end_32_sign_end,/* 16->32 src_end dst_end sign: conv_16_end_32_sign_end */ + conv_32_8, /* 32->8: conv_32_8 */ + conv_32_8_sign, /* 32->8 sign: conv_32_8_sign */ + conv_32_8, /* 32->8 dst_end: conv_32_8 */ + conv_32_8_sign, /* 32->8 dst_end sign: conv_32_8_sign */ + conv_32_end_8, /* 32->8 src_end: conv_32_end_8 */ + conv_32_end_8_sign, /* 32->8 src_end sign: conv_32_end_8_sign */ + conv_32_end_8, /* 32->8 src_end dst_end: conv_32_end_8 */ + conv_32_end_8_sign, /* 32->8 src_end dst_end sign: conv_32_end_8_sign */ + conv_32_16, /* 32->16: conv_32_16 */ + conv_32_16_sign, /* 32->16 sign: conv_32_16_sign */ + conv_32_16_end, /* 32->16 dst_end: conv_32_16_end */ + conv_32_16_sign_end, /* 32->16 dst_end sign: conv_32_16_sign_end */ + conv_32_end_16, /* 32->16 src_end: conv_32_end_16 */ + conv_32_end_16_sign, /* 32->16 src_end sign: conv_32_end_16_sign */ + conv_32_end_16_end, /* 32->16 src_end dst_end: conv_32_end_16_end */ + conv_32_end_16_sign_end,/* 32->16 src_end dst_end sign: conv_32_end_16_sign_end */ + NULL, /* 32->32: Nothing to do */ + conv_32_sign, /* 32->32 sign: conv_32_sign */ + conv_32_end, /* 32->32 dst_end: conv_32_end */ + conv_32_sign_end, /* 32->32 dst_end sign: conv_32_sign_end */ + conv_32_end, /* 32->32 src_end: conv_32_end */ + conv_32_end_sign, /* 32->32 src_end sign: conv_32_end_sign */ + NULL, /* 32->32 src_end dst_end: Nothing to do */ + conv_32_end_sign_end /* 32->32 src_end dst_end sign: conv_32_end_sign_end */ +}; -static void linear_conv_sign_16bit_8bit_swap(unsigned short *src_ptr, - unsigned char *dst_ptr, - size_t size) -{ - while (size--) - *dst_ptr++ = ((unsigned char)*src_ptr++) ^ 0x80; -} static ssize_t linear_transfer(snd_pcm_plugin_t *plugin, char *src_ptr, size_t src_size, @@ -148,51 +201,12 @@ static ssize_t linear_transfer(snd_pcm_plugin_t *plugin, data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); if (data == NULL) return -EINVAL; - switch (data->cmd) { - case _8BIT_16BIT: - if ((dst_size >> 1) < src_size) - return -EINVAL; - switch (data->endian) { - case NONE: - linear_conv_8bit_16bit(src_ptr, (short *)dst_ptr, src_size); - break; - case DESTINATION: - linear_conv_8bit_16bit_swap(src_ptr, (short *)dst_ptr, src_size); - break; - case SIGN_NONE: - linear_conv_sign_8bit_16bit(src_ptr, (short *)dst_ptr, src_size); - break; - case SIGN_DESTINATION: - linear_conv_sign_8bit_16bit_swap(src_ptr, (short *)dst_ptr, src_size); - break; - default: - return -EINVAL; - } - return src_size << 1; - case _16BIT_8BIT: - if (dst_size < (src_size >> 1)) - return -EINVAL; - src_size >>= 1; - switch (data->endian) { - case NONE: - linear_conv_16bit_8bit((short *)src_ptr, dst_ptr, src_size); - break; - case SOURCE: - linear_conv_16bit_8bit_swap((short *)src_ptr, dst_ptr, src_size); - break; - case SIGN_NONE: - linear_conv_sign_16bit_8bit((short *)src_ptr, dst_ptr, src_size); - break; - case SIGN_SOURCE: - linear_conv_sign_16bit_8bit_swap((short *)src_ptr, dst_ptr, src_size); - break; - default: - return -EINVAL; - } - return src_size; - default: - return -EIO; - } + if (src_size % data->src_sample_size != 0) + return -EINVAL; + if (dst_size < src_size*data->dst_sample_size/data->src_sample_size) + return -EINVAL; + data->func(src_ptr, dst_ptr, src_size / data->src_sample_size); + return src_size*data->dst_sample_size/data->src_sample_size; } static ssize_t linear_src_size(snd_pcm_plugin_t *plugin, size_t size) @@ -202,27 +216,9 @@ static ssize_t linear_src_size(snd_pcm_plugin_t *plugin, size_t size) if (!plugin || size <= 0) return -EINVAL; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); - switch (data->cmd) { - case _8BIT_16BIT: - case _16BIT_24BIT: - case _16BIT_32BIT: - return size / 2; - case _8BIT_24BIT: - case _8BIT_32BIT: - return size / 4; - case _16BIT_8BIT: - case _24BIT_16BIT: - case _32BIT_16BIT: - return size * 2; - case _24BIT_8BIT: - case _32BIT_8BIT: - return size * 4; - case _24BIT_32BIT: - case _32BIT_24BIT: - return size; - default: - return -EIO; - } + if (data == NULL) + return -EINVAL; + return size*data->src_sample_size/data->dst_sample_size; } static ssize_t linear_dst_size(snd_pcm_plugin_t *plugin, size_t size) @@ -232,27 +228,9 @@ static ssize_t linear_dst_size(snd_pcm_plugin_t *plugin, size_t size) if (!plugin || size <= 0) return -EINVAL; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); - switch (data->cmd) { - case _8BIT_16BIT: - case _16BIT_24BIT: - case _16BIT_32BIT: - return size * 2; - case _8BIT_24BIT: - case _8BIT_32BIT: - return size * 4; - case _16BIT_8BIT: - case _24BIT_16BIT: - case _32BIT_16BIT: - return size / 2; - case _24BIT_8BIT: - case _32BIT_8BIT: - return size / 4; - case _24BIT_32BIT: - case _32BIT_24BIT: - return size; - default: - return -EIO; - } + if (data == NULL) + return -EINVAL; + return size*data->dst_sample_size/data->src_sample_size; } int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, @@ -261,8 +239,8 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, { struct linear_private_data *data; snd_pcm_plugin_t *plugin; - combination_t cmd; - int width1, width2, endian1, endian2, sign1, sign2; + conv_f func; + int src_endian, dst_endian, sign, src_width, dst_width; if (!r_plugin) return -EINVAL; @@ -279,69 +257,66 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, snd_pcm_format_linear(dst_format->format))) return -EINVAL; - width1 = snd_pcm_format_width(src_format->format); - sign1 = snd_pcm_format_signed(src_format->format); - width2 = snd_pcm_format_width(dst_format->format); - sign2 = snd_pcm_format_signed(dst_format->format); + sign = (snd_pcm_format_signed(src_format->format) != + snd_pcm_format_signed(dst_format->format)); + src_width = snd_pcm_format_width(src_format->format); + dst_width = snd_pcm_format_width(dst_format->format); #if __BYTE_ORDER == __LITTLE_ENDIAN - endian1 = snd_pcm_format_little_endian(src_format->format); - endian2 = snd_pcm_format_little_endian(dst_format->format); + src_endian = snd_pcm_format_big_endian(src_format->format); + dst_endian = snd_pcm_format_big_endian(dst_format->format); #elif __BYTE_ORDER == __BIG_ENDIAN - endian1 = snd_pcm_format_big_endian(src_format->format); - endian2 = snd_pcm_format_big_endian(dst_format->format); + src_endian = snd_pcm_format_little_endian(src_format->format); + dst_endian = snd_pcm_format_little_endian(dst_format->format); #else #error "Unsupported endian..." #endif - cmd = _8BIT_16BIT; - switch (width1) { + + switch (src_width) { case 8: - switch (width2) { - case 16: cmd = _8BIT_16BIT; break; - case 24: cmd = _8BIT_24BIT; break; - case 32: cmd = _8BIT_32BIT; break; - default: return -EINVAL; - } + src_width = 0; break; case 16: - switch (width2) { - case 8: cmd = _16BIT_8BIT; break; - case 24: cmd = _16BIT_24BIT; break; - case 32: cmd = _16BIT_32BIT; break; - default: return -EINVAL; - } + src_width = 1; break; - case 24: - switch (width2) { - case 8: cmd = _24BIT_8BIT; break; - case 16: cmd = _24BIT_16BIT; break; - case 32: cmd = _24BIT_32BIT; break; - default: return -EINVAL; - } + case 32: + src_width = 2; + break; + default: + return -EINVAL; + } + switch (dst_width) { + case 8: + dst_width = 0; + break; + case 16: + dst_width = 1; break; case 32: - switch (width2) { - case 8: cmd = _32BIT_8BIT; break; - case 16: cmd = _32BIT_16BIT; break; - case 24: cmd = _32BIT_24BIT; break; - default: return -EINVAL; - } + dst_width = 2; break; default: return -EINVAL; } + + if (src_endian < 0) + src_endian = 0; + if (dst_endian < 0) + src_endian = 0; + + func = convert_functions[src_width][dst_width][src_endian][dst_endian][sign]; + + if (func == NULL) + return -EINVAL; + plugin = snd_pcm_plugin_build("linear format conversion", sizeof(struct linear_private_data)); if (plugin == NULL) return -ENOMEM; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); - data->cmd = cmd; - data->endian = NONE; - if (endian1 == 0) - data->endian |= SOURCE; - if (endian2 == 0) - data->endian |= DESTINATION; - if (sign1 != sign2) - data->endian |= SIGN; + data->func = func; + data->src_sample_size = 1 << src_width; + data->dst_sample_size = 1 << dst_width; + plugin->transfer = linear_transfer; plugin->src_size = linear_src_size; plugin->dst_size = linear_dst_size;