New plugin interface with readv/writev support.

Initial code.
This commit is contained in:
Jaroslav Kysela 2000-03-29 20:26:06 +00:00
parent e7d099089c
commit 098b4b6a96
15 changed files with 1820 additions and 1742 deletions

View file

@ -86,7 +86,7 @@ static void adpcm_init_state(adpcm_state_t * state_ptr)
state_ptr->io_shift = 4;
}
static inline char adpcm_encoder(int sl, adpcm_state_t * state)
static char adpcm_encoder(int sl, adpcm_state_t * state)
{
short diff; /* Difference between sl and predicted sample */
short pred_diff; /* Predicted difference to next sample */
@ -147,7 +147,7 @@ static inline char adpcm_encoder(int sl, adpcm_state_t * state)
}
static inline int adpcm_decoder(unsigned char code, adpcm_state_t * state)
static int adpcm_decoder(unsigned char code, adpcm_state_t * state)
{
short pred_diff; /* Predicted difference to next sample */
short step; /* holds previous StepSize value */
@ -197,397 +197,174 @@ static inline int adpcm_decoder(unsigned char code, adpcm_state_t * state)
* Basic Ima-ADPCM plugin
*/
typedef enum {
_S8_ADPCM,
_U8_ADPCM,
_S16LE_ADPCM,
_U16LE_ADPCM,
_S16BE_ADPCM,
_U16BE_ADPCM,
_ADPCM_S8,
_ADPCM_U8,
_ADPCM_S16LE,
_ADPCM_U16LE,
_ADPCM_S16BE,
_ADPCM_U16BE
} combination_t;
typedef void (*adpcm_f)(adpcm_state_t *state, void *src_ptr, void *dst_ptr, int samples);
struct adpcm_private_data {
combination_t cmd;
typedef struct adpcm_private_data {
adpcm_f func;
adpcm_state_t state;
} adpcm_t;
#define ADPCM_FUNC_DECODE(name, dsttype, val) \
static void adpcm_decode_##name(adpcm_state_t *state, \
void *src_ptr, void *dst_ptr, int samples) \
{ \
unsigned char *src = src_ptr; \
dsttype *dst = dst_ptr; \
unsigned int s; \
samples <<= 1; \
while (samples--) { \
if (state->io_shift) \
state->io_buffer = *src++; \
s = adpcm_decoder((state->io_buffer >> state->io_shift) & 0x0f, state); \
*dst++ = val; \
state->io_shift ^= 4; \
} \
}
#define ADPCM_FUNC_ENCODE(name, srctype, val) \
static void adpcm_encode_##name(adpcm_state_t *state, \
void *src_ptr, void *dst_ptr, int samples) \
{ \
srctype *src = src_ptr; \
unsigned char *dst = dst_ptr; \
unsigned int s; \
samples <<= 1; \
while (samples--) { \
s = *src++; \
state->io_buffer |= adpcm_encoder((signed short)(val), state) << state->io_shift; \
if (state->io_shift == 0) { \
*dst++ = state->io_buffer & 0xff; \
state->io_buffer = 0; \
} \
state->io_shift ^= 4; \
} \
}
ADPCM_FUNC_DECODE(u8, u_int8_t, (s >> 8) ^ 0x80)
ADPCM_FUNC_DECODE(s8, u_int8_t, s >> 8)
ADPCM_FUNC_DECODE(u16n, u_int16_t, s ^ 0x8000)
ADPCM_FUNC_DECODE(u16s, u_int16_t, bswap_16(s ^ 0x8000))
ADPCM_FUNC_DECODE(s16n, u_int16_t, s)
ADPCM_FUNC_DECODE(s16s, u_int16_t, bswap_16(s))
ADPCM_FUNC_DECODE(u24n, u_int32_t, (s << 8) ^ 0x800000)
ADPCM_FUNC_DECODE(u24s, u_int32_t, bswap_32((s << 8) ^ 0x800000))
ADPCM_FUNC_DECODE(s24n, u_int32_t, s << 8)
ADPCM_FUNC_DECODE(s24s, u_int32_t, bswap_32(s << 8))
ADPCM_FUNC_DECODE(u32n, u_int32_t, (s << 16) ^ 0x80000000)
ADPCM_FUNC_DECODE(u32s, u_int32_t, bswap_32((s << 16) ^ 0x80000000))
ADPCM_FUNC_DECODE(s32n, u_int32_t, s << 16)
ADPCM_FUNC_DECODE(s32s, u_int32_t, bswap_32(s << 16))
ADPCM_FUNC_ENCODE(u8, u_int8_t, s << 8)
ADPCM_FUNC_ENCODE(s8, u_int8_t, (s << 8) ^ 0x8000)
ADPCM_FUNC_ENCODE(u16n, u_int16_t, s ^ 0x8000)
ADPCM_FUNC_ENCODE(u16s, u_int16_t, bswap_16(s ^ 0x8000))
ADPCM_FUNC_ENCODE(s16n, u_int16_t, s)
ADPCM_FUNC_ENCODE(s16s, u_int16_t, bswap_16(s))
ADPCM_FUNC_ENCODE(u24n, u_int32_t, (s ^ 0x800000) >> 8)
ADPCM_FUNC_ENCODE(u24s, u_int32_t, bswap_32((s ^ 0x800000) >> 8))
ADPCM_FUNC_ENCODE(s24n, u_int32_t, s >> 8)
ADPCM_FUNC_ENCODE(s24s, u_int32_t, bswap_32(s >> 8))
ADPCM_FUNC_ENCODE(u32n, u_int32_t, (s ^ 0x80000000) >> 16)
ADPCM_FUNC_ENCODE(u32s, u_int32_t, bswap_32((s ^ 0x80000000) >> 16))
ADPCM_FUNC_ENCODE(s32n, u_int32_t, s >> 16)
ADPCM_FUNC_ENCODE(s32s, u_int32_t, bswap_32(s >> 16))
/* wide, sign, swap endian */
static adpcm_f adpcm_functions_decode[4 * 4 * 2 * 2] = {
adpcm_decode_u8, /* decode:8-bit:unsigned:none */
adpcm_decode_u8, /* decode:8-bit:unsigned:swap */
adpcm_decode_s8, /* decode:8-bit:signed:none */
adpcm_decode_s8, /* decode:8-bit:signed:swap */
adpcm_decode_u16n, /* decode:16-bit:unsigned:none */
adpcm_decode_u16s, /* decode:16-bit:unsigned:swap */
adpcm_decode_s16n, /* decode:16-bit:signed:none */
adpcm_decode_s16s, /* decode:16-bit:signed:swap */
adpcm_decode_u24n, /* decode:24-bit:unsigned:none */
adpcm_decode_u24s, /* decode:24-bit:unsigned:swap */
adpcm_decode_s24n, /* decode:24-bit:signed:none */
adpcm_decode_s24s, /* decode:24-bit:signed:swap */
adpcm_decode_u32n, /* decode:32-bit:unsigned:none */
adpcm_decode_u32s, /* decode:32-bit:unsigned:swap */
adpcm_decode_s32n, /* decode:32-bit:signed:none */
adpcm_decode_s32s, /* decode:32-bit:signed:swap */
};
static void adpcm_conv_u8bit_adpcm(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned char *dst_ptr, size_t size)
/* wide, sign, swap endian */
static adpcm_f adpcm_functions_encode[4 * 2 * 2] = {
adpcm_encode_u8, /* encode:8-bit:unsigned:none */
adpcm_encode_u8, /* encode:8-bit:unsigned:swap */
adpcm_encode_s8, /* encode:8-bit:signed:none */
adpcm_encode_s8, /* encode:8-bit:signed:swap */
adpcm_encode_u16n, /* encode:16-bit:unsigned:none */
adpcm_encode_u16s, /* encode:16-bit:unsigned:swap */
adpcm_encode_s16n, /* encode:16-bit:signed:none */
adpcm_encode_s16s, /* encode:16-bit:signed:swap */
adpcm_encode_u24n, /* encode:24-bit:unsigned:none */
adpcm_encode_u24s, /* encode:24-bit:unsigned:swap */
adpcm_encode_s24n, /* encode:24-bit:signed:none */
adpcm_encode_s24s, /* encode:24-bit:signed:swap */
adpcm_encode_u32n, /* encode:32-bit:unsigned:none */
adpcm_encode_u32s, /* encode:32-bit:unsigned:swap */
adpcm_encode_s32n, /* encode:32-bit:signed:none */
adpcm_encode_s32s, /* encode:32-bit:signed:swap */
};
static ssize_t adpcm_transfer(snd_pcm_plugin_t *plugin,
const snd_pcm_plugin_voice_t *src_voices,
const snd_pcm_plugin_voice_t *dst_voices,
size_t samples)
{
unsigned int pcm;
adpcm_t *data;
int voice;
while (size-- > 0) {
pcm = ((*src_ptr++) ^ 0x80) << 8;
state_ptr->io_buffer |= adpcm_encoder((signed short)(pcm), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_s8bit_adpcm(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned char *dst_ptr, size_t size)
{
unsigned int pcm;
while (size-- > 0) {
pcm = *src_ptr++ << 8;
state_ptr->io_buffer |= adpcm_encoder((signed short)(pcm), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_s16bit_adpcm(adpcm_state_t * state_ptr, unsigned short *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
state_ptr->io_buffer |= adpcm_encoder((signed short)(*src_ptr++), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_s16bit_swap_adpcm(adpcm_state_t * state_ptr, unsigned short *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
state_ptr->io_buffer |= adpcm_encoder((signed short)(bswap_16(*src_ptr++)), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_u16bit_adpcm(adpcm_state_t * state_ptr, unsigned short *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
state_ptr->io_buffer |= adpcm_encoder((signed short)((*src_ptr++) ^ 0x8000), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_u16bit_swap_adpcm(adpcm_state_t * state_ptr, unsigned short *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
state_ptr->io_buffer |= adpcm_encoder((signed short)(bswap_16(*src_ptr++) ^ 0x8000), state_ptr) << state_ptr->io_shift;
if (!(state_ptr->io_shift)) {
*dst_ptr++ = state_ptr->io_buffer & 0xff;
state_ptr->io_buffer = 0;
}
state_ptr->io_shift ^= 4;
}
if (!(state_ptr->io_shift)) {
*dst_ptr = state_ptr->io_buffer & 0xf0;
}
}
static void adpcm_conv_adpcm_u8bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = (adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr) >> 8) ^ 0x80;
state_ptr->io_shift ^= 4;
}
}
static void adpcm_conv_adpcm_s8bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned char *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr) >> 8;
state_ptr->io_shift ^= 4;
}
}
static void adpcm_conv_adpcm_s16bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned short *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr);
state_ptr->io_shift ^= 4;
}
}
static void adpcm_conv_adpcm_swap_s16bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned short *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = bswap_16(adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr));
state_ptr->io_shift ^= 4;
}
}
static void adpcm_conv_adpcm_u16bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned short *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr) ^ 0x8000;
state_ptr->io_shift ^= 4;
}
}
static void adpcm_conv_adpcm_swap_u16bit(adpcm_state_t * state_ptr, unsigned char *src_ptr, unsigned short *dst_ptr, size_t size)
{
while (size-- > 0) {
if (state_ptr->io_shift) {
state_ptr->io_buffer = *src_ptr++;
}
*dst_ptr++ = bswap_16(adpcm_decoder((state_ptr->io_buffer >> state_ptr->io_shift) & 0xf, state_ptr) ^ 0x8000);
state_ptr->io_shift ^= 4;
}
}
static ssize_t adpcm_transfer(snd_pcm_plugin_t * plugin,
char *src_ptr, size_t src_size,
char *dst_ptr, size_t dst_size)
{
struct adpcm_private_data *data;
if (plugin == NULL || src_ptr == NULL || src_size < 0 ||
dst_ptr == NULL || dst_size < 0)
if (plugin == NULL || src_voices == NULL || dst_voices == NULL || samples < 0)
return -EINVAL;
if (src_size == 0)
if (samples == 0)
return 0;
data = (struct adpcm_private_data *)snd_pcm_plugin_extra_data(plugin);
if (data == NULL)
return -EINVAL;
switch (data->cmd) {
case _U8_ADPCM:
if ((dst_size << 1) < src_size)
return -EINVAL;
adpcm_conv_u8bit_adpcm(&data->state, src_ptr, dst_ptr, src_size);
return src_size >> 1;
case _S8_ADPCM:
if ((dst_size << 1) < src_size)
return -EINVAL;
adpcm_conv_s8bit_adpcm(&data->state, src_ptr, dst_ptr, src_size);
return src_size >> 1;
case _S16LE_ADPCM:
if ((dst_size << 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_s16bit_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_s16bit_swap_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#else
#error "Have to be coded..."
#endif
return src_size >> 2;
case _U16LE_ADPCM:
if ((dst_size << 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_u16bit_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_u16bit_swap_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#else
#error "Have to be coded..."
#endif
return src_size >> 2;
case _S16BE_ADPCM:
if ((dst_size << 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_s16bit_swap_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_s16bit_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#else
#error "Have to be coded..."
#endif
return src_size >> 2;
case _U16BE_ADPCM:
if ((dst_size << 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_u16bit_swap_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_u16bit_adpcm(&data->state, (short *) src_ptr, dst_ptr, src_size >> 1);
#else
#error "Have to be coded..."
#endif
return src_size >> 2;
case _ADPCM_U8:
if ((dst_size >> 1) < src_size)
return -EINVAL;
adpcm_conv_adpcm_u8bit(&data->state, src_ptr, dst_ptr, src_size << 1);
return src_size << 1;
case _ADPCM_S8:
if ((dst_size >> 1) < src_size)
return -EINVAL;
adpcm_conv_adpcm_s8bit(&data->state, src_ptr, dst_ptr, src_size << 1);
return src_size << 1;
case _ADPCM_S16LE:
if ((dst_size >> 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_adpcm_s16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_adpcm_swap_s16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#else
#error "Have to be coded..."
#endif
return src_size << 2;
case _ADPCM_U16LE:
if ((dst_size >> 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_adpcm_u16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_adpcm_swap_u16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#else
#error "Have to be coded..."
#endif
return src_size << 2;
case _ADPCM_S16BE:
if ((dst_size >> 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_adpcm_swap_s16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_adpcm_s16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#else
#error "Have to be coded..."
#endif
return src_size << 2;
case _ADPCM_U16BE:
if ((dst_size << 2) < src_size)
return -EINVAL;
#if __BYTE_ORDER == __LITTLE_ENDIAN
adpcm_conv_adpcm_swap_u16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#elif __BYTE_ORDER == __BIG_ENDIAN
adpcm_conv_adpcm_u16bit(&data->state, src_ptr, (short *) dst_ptr, src_size << 1);
#else
#error "Have to be coded..."
#endif
return src_size << 2;
default:
return -EIO;
data = (adpcm_t *)plugin->extra_data;
/* FIXME */
if (plugin->src_format.interleave) {
data->func(&data->state,
src_voices[0].addr,
dst_voices[0].addr,
samples * plugin->src_format.voices);
} else {
for (voice = 0; voice < plugin->src_format.voices; voice++) {
if (src_voices[voice].addr == NULL)
continue;
data->func(&data->state,
src_voices[voice].addr,
dst_voices[voice].addr,
samples);
}
}
return samples;
}
static int adpcm_action(snd_pcm_plugin_t * plugin,
snd_pcm_plugin_action_t action,
unsigned long udata)
{
struct adpcm_private_data *data;
adpcm_t *data;
if (plugin == NULL)
return -EINVAL;
data = (struct adpcm_private_data *)snd_pcm_plugin_extra_data(plugin);
data = (adpcm_t *)plugin->extra_data;
if (action == PREPARE)
adpcm_init_state(&data->state);
return 0; /* silenty ignore other actions */
}
static ssize_t adpcm_src_size(snd_pcm_plugin_t * plugin, size_t size)
{
struct adpcm_private_data *data;
if (!plugin || size <= 0)
return -EINVAL;
data = (struct adpcm_private_data *)snd_pcm_plugin_extra_data(plugin);
switch (data->cmd) {
case _U8_ADPCM:
case _S8_ADPCM:
return size * 2;
case _ADPCM_U8:
case _ADPCM_S8:
return size / 2;
case _U16LE_ADPCM:
case _S16LE_ADPCM:
case _U16BE_ADPCM:
case _S16BE_ADPCM:
return size * 4;
case _ADPCM_U16LE:
case _ADPCM_S16LE:
case _ADPCM_U16BE:
case _ADPCM_S16BE:
return size / 4;
default:
return -EIO;
}
}
static ssize_t adpcm_dst_size(snd_pcm_plugin_t * plugin, size_t size)
{
struct adpcm_private_data *data;
if (!plugin || size <= 0)
return -EINVAL;
data = (struct adpcm_private_data *)snd_pcm_plugin_extra_data(plugin);
switch (data->cmd) {
case _U8_ADPCM:
case _S8_ADPCM:
return size / 2;
case _ADPCM_U8:
case _ADPCM_S8:
return size * 2;
case _U16LE_ADPCM:
case _S16LE_ADPCM:
case _U16BE_ADPCM:
case _S16BE_ADPCM:
return size / 4;
case _ADPCM_U16LE:
case _ADPCM_S16LE:
case _ADPCM_U16BE:
case _ADPCM_S16BE:
return size * 4;
default:
return -EIO;
}
}
int snd_pcm_plugin_build_adpcm(snd_pcm_format_t * src_format,
snd_pcm_format_t * dst_format,
snd_pcm_plugin_t ** r_plugin)
int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle,
snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin)
{
struct adpcm_private_data *data;
snd_pcm_plugin_t *plugin;
combination_t cmd;
int endian, src_width, dst_width, sign;
adpcm_f func;
if (!r_plugin || !src_format || !dst_format)
return -EINVAL;
@ -602,39 +379,49 @@ int snd_pcm_plugin_build_adpcm(snd_pcm_format_t * src_format,
return -EINVAL;
if (dst_format->format == SND_PCM_SFMT_IMA_ADPCM) {
switch (src_format->format) {
case SND_PCM_SFMT_U8: cmd = _U8_ADPCM; break;
case SND_PCM_SFMT_S8: cmd = _S8_ADPCM; break;
case SND_PCM_SFMT_U16_LE: cmd = _U16LE_ADPCM; break;
case SND_PCM_SFMT_S16_LE: cmd = _S16LE_ADPCM; break;
case SND_PCM_SFMT_U16_BE: cmd = _U16BE_ADPCM; break;
case SND_PCM_SFMT_S16_BE: cmd = _S16BE_ADPCM; break;
default:
if (!snd_pcm_format_linear(src_format->format))
return -EINVAL;
}
sign = snd_pcm_format_signed(src_format->format);
src_width = snd_pcm_format_width(src_format->format);
if ((src_width % 8) != 0 || src_width < 8 || src_width > 32)
return -EINVAL;
dst_width = 8;
#if __BYTE_ORDER == __LITTLE_ENDIAN
endian = snd_pcm_format_big_endian(src_format->format);
#elif __BYTE_ORDER == __BIG_ENDIAN
endian = snd_pcm_format_little_endian(src_format->format);
#else
#error "Unsupported endian..."
#endif
func = ((adpcm_f(*)[2][2])adpcm_functions_encode)[src_width/8][sign][endian];
} else if (src_format->format == SND_PCM_SFMT_IMA_ADPCM) {
switch (dst_format->format) {
case SND_PCM_SFMT_U8: cmd = _ADPCM_U8; break;
case SND_PCM_SFMT_S8: cmd = _ADPCM_S8; break;
case SND_PCM_SFMT_U16_LE: cmd = _ADPCM_U16LE; break;
case SND_PCM_SFMT_S16_LE: cmd = _ADPCM_S16LE; break;
case SND_PCM_SFMT_U16_BE: cmd = _ADPCM_U16BE; break;
case SND_PCM_SFMT_S16_BE: cmd = _ADPCM_S16BE; break;
default:
if (!snd_pcm_format_linear(dst_format->format))
return -EINVAL;
}
sign = snd_pcm_format_signed(dst_format->format);
dst_width = snd_pcm_format_width(dst_format->format);
if ((dst_width % 8) != 0 || dst_width < 8 || dst_width > 32)
return -EINVAL;
src_width = 8;
#if __BYTE_ORDER == __LITTLE_ENDIAN
endian = snd_pcm_format_big_endian(dst_format->format);
#elif __BYTE_ORDER == __BIG_ENDIAN
endian = snd_pcm_format_little_endian(dst_format->format);
#else
#error "Unsupported endian..."
#endif
func = ((adpcm_f(*)[2][2])adpcm_functions_decode)[dst_width/8][sign][endian];
} else {
return -EINVAL;
}
plugin = snd_pcm_plugin_build("Ima-ADPCM<->linear conversion",
plugin = snd_pcm_plugin_build(handle,
"Ima-ADPCM<->linear conversion",
src_format,
dst_format,
sizeof(struct adpcm_private_data));
if (plugin == NULL)
return -ENOMEM;
data = (struct adpcm_private_data *)snd_pcm_plugin_extra_data(plugin);
data->cmd = cmd;
data = (adpcm_t *)plugin->extra_data;
plugin->transfer = adpcm_transfer;
plugin->src_size = adpcm_src_size;
plugin->dst_size = adpcm_dst_size;
plugin->action = adpcm_action;
*r_plugin = plugin;
return 0;