From: Jaroslav Kysela Date: Sat, 11 Dec 1999 11:46:05 +0000 (+0000) Subject: Abramo Bagnara X-Git-Tag: v1.0.3~1386 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=20ebae20a78232ee35761b7f7b433e104dfaad2d;p=alsa-lib.git Abramo Bagnara Sat, 11 Dec 1999 08:45:24 +0100 - changed lowlevel drivers to use pcm_misc.c functions - fixed some bugs in pcm_plugin_build - the plugin code is shared between alsa-lib and alsa-driver --- diff --git a/include/pcm.h b/include/pcm.h index b58f5c1b..f277a7a8 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -52,6 +52,7 @@ int snd_pcm_munmap(snd_pcm_t *handle, int channel); int snd_pcm_format_signed(int format); int snd_pcm_format_unsigned(int format); +int snd_pcm_format_linear(int format); int snd_pcm_format_little_endian(int format); int snd_pcm_format_big_endian(int format); int snd_pcm_format_width(int format); /* in bits */ diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am index 0e480262..3ebb9915 100644 --- a/src/pcm/Makefile.am +++ b/src/pcm/Makefile.am @@ -2,7 +2,8 @@ SUBDIRS = plugin EXTRA_LTLIBRARIES = libpcm.la -libpcm_la_SOURCES = pcm.c pcm_plugin.c pcm_misc.c pcm_loopback.c +libpcm_la_SOURCES = pcm.c pcm_plugin.c pcm_plugin_build.c pcm_misc.c \ + pcm_loopback.c libpcm_la_LIBADD = plugin/libpcmplugin.la all: libpcm.la diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index bc90db8b..306bc78e 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -39,3 +39,19 @@ struct snd_pcm { void *plugin_alloc_xptr[2]; long plugin_alloc_xsize[2]; }; + +unsigned int snd_pcm_plugin_formats(unsigned int formats); +int snd_pcm_plugin_hwparams(snd_pcm_channel_params_t *params, + snd_pcm_channel_info_t *hwinfo, + snd_pcm_channel_params_t *hwparams); +int snd_pcm_plugin_format(snd_pcm_t *pcm, + snd_pcm_channel_params_t *params, + snd_pcm_channel_params_t *hwparams, + snd_pcm_channel_info_t *hwinfo); + +#if 0 +#define PLUGIN_DEBUG +#define pdprintf( args... ) printf( "plugin: " ##args) +#else +#define pdprintf( args... ) { ; } +#endif diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c index e0f3ae07..e3c70485 100644 --- a/src/pcm/pcm_misc.c +++ b/src/pcm/pcm_misc.c @@ -19,15 +19,18 @@ * */ +#ifdef ALSA_BUILD +#include "../include/driver.h" +#else #include #include #include #include #include -#include -#include -#include +#include +#include #include "pcm_local.h" +#endif int snd_pcm_format_signed(int format) { @@ -63,6 +66,11 @@ int snd_pcm_format_unsigned(int format) return val; } +int snd_pcm_format_linear(int format) +{ + return snd_pcm_format_signed(format) >= 0; +} + int snd_pcm_format_little_endian(int format) { switch (format) { diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index db2c67e0..d79ac7cd 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -162,65 +162,6 @@ snd_pcm_plugin_t *snd_pcm_plugin_last(snd_pcm_t *pcm, int channel) return pcm->plugin_last[channel]; } -ssize_t snd_pcm_plugin_transfer_size(snd_pcm_t *pcm, int channel, size_t drv_size) -{ - snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; - - if (!pcm || channel < 0 || channel > 1) - return -EINVAL; - if (drv_size == 0) - return 0; - if (drv_size < 0) - return -EINVAL; - if (channel == SND_PCM_CHANNEL_PLAYBACK) { - plugin = snd_pcm_plugin_last(pcm, channel); - while (plugin) { - plugin_prev = plugin->prev; - if (plugin->src_size) - drv_size = plugin->src_size(plugin, drv_size); - plugin = plugin_prev; - } - } else if (channel == SND_PCM_CHANNEL_CAPTURE) { - plugin = snd_pcm_plugin_first(pcm, channel); - while (plugin) { - plugin_next = plugin->next; - if (plugin->dst_size) - drv_size = plugin->dst_size(plugin, drv_size); - plugin = plugin_next; - } - } - return drv_size; -} - -ssize_t snd_pcm_plugin_hardware_size(snd_pcm_t *pcm, int channel, size_t trf_size) -{ - snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; - - if (!pcm || channel < 0 || channel > 1) - return -EINVAL; - if (trf_size == 0) - return 0; - if (trf_size < 0) - return -EINVAL; - if (channel == SND_PCM_CHANNEL_PLAYBACK) { - plugin = snd_pcm_plugin_first(pcm, channel); - while (plugin) { - plugin_next = plugin->next; - if (plugin->dst_size) - trf_size = plugin->dst_size(plugin, trf_size); - plugin = plugin_next; - } - } else if (channel == SND_PCM_CHANNEL_CAPTURE) { - plugin = snd_pcm_plugin_last(pcm, channel); - while (plugin) { - plugin_prev = plugin->prev; - if (plugin->src_size) - trf_size = plugin->src_size(plugin, trf_size); - plugin = plugin_prev; - } - } - return trf_size; -} double snd_pcm_plugin_transfer_ratio(snd_pcm_t *pcm, int channel) { @@ -246,23 +187,13 @@ double snd_pcm_plugin_hardware_ratio(snd_pcm_t *pcm, int channel) * */ -static unsigned int snd_pcm_plugin_formats(snd_pcm_t *pcm, unsigned int formats) -{ - formats |= SND_PCM_FMT_MU_LAW | SND_PCM_FMT_A_LAW | SND_PCM_FMT_IMA_ADPCM; - 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; - return formats; -} - int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) { int err; if ((err = snd_pcm_channel_info(pcm, info)) < 0) return err; - info->formats = snd_pcm_plugin_formats(pcm, info->formats); + info->formats = snd_pcm_plugin_formats(info->formats); info->min_rate = 4000; info->max_rate = 192000; info->rates = SND_PCM_RATE_8000_48000; @@ -285,28 +216,16 @@ static int snd_pcm_plugin_action(snd_pcm_t *pcm, int channel, int action) return 0; } -#if 0 -#define PLUGIN_DEBUG -#define pdprintf( args... ) printf( "plugin: " ##args) -#else -#define pdprintf( args... ) { ; } -#endif - int snd_pcm_plugin_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *params) { snd_pcm_channel_params_t hwparams; - snd_pcm_channel_params_t srcparams, tmpparams; - snd_pcm_channel_params_t *dstparams; snd_pcm_channel_info_t hwinfo; snd_pcm_plugin_t *plugin; int err; if (!pcm || !params || params->channel < 0 || params->channel > 1) return -EINVAL; - memcpy(&hwparams, params, sizeof(hwparams)); - pdprintf("params begin\n"); - /* * try to decide, if a conversion is required */ @@ -317,302 +236,16 @@ int snd_pcm_plugin_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *params) snd_pcm_plugin_clear(pcm, params->channel); return err; } - if ((hwinfo.formats & (1 << params->format.format)) == 0) { - if ((snd_pcm_plugin_formats(pcm, hwinfo.formats) & (1 << params->format.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; - } - 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; - 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 { - return -EINVAL; - } - break; - default: - return -EINVAL; - } - } - - /* voices */ - if (params->format.voices < hwinfo.min_voices || - params->format.voices > hwinfo.max_voices) { - int dst_voices = params->format.voices < hwinfo.min_voices ? - hwinfo.min_voices : hwinfo.max_voices; - if ((params->format.rate < hwinfo.min_rate || - params->format.rate > hwinfo.max_rate) && - dst_voices > 2) - dst_voices = 2; - hwparams.format.voices = dst_voices; - pdprintf("params voice correction: dst_voices=%i\n", dst_voices); - } - /* rate */ - if (params->format.rate < hwinfo.min_rate || - params->format.rate > hwinfo.max_rate) { - int dst_rate = params->format.rate < hwinfo.min_rate ? - hwinfo.min_rate : hwinfo.max_rate; - hwparams.format.rate = dst_rate; - pdprintf("params rate correction: dst_rate=%i\n", dst_rate); - } + if ((err = snd_pcm_plugin_hwparams(params, &hwinfo, &hwparams)) < 0) + return err; - /* interleave */ - hwparams.format.interleave = params->format.interleave; - if (!(hwinfo.flags & SND_PCM_CHNINFO_INTERLEAVE)) - hwparams.format.interleave = 0; - if (!(hwinfo.flags & SND_PCM_CHNINFO_NONINTERLEAVE)) - hwparams.format.interleave = 1; - - /* - * add necessary plugins - */ snd_pcm_plugin_clear(pcm, params->channel); - if (params->channel == SND_PCM_CHANNEL_PLAYBACK) { - memcpy(&srcparams, params, sizeof(srcparams)); - memcpy(&tmpparams, params, sizeof(tmpparams)); - dstparams = &hwparams; - } else { - memcpy(&srcparams, &hwparams, sizeof(srcparams)); - memcpy(&tmpparams, &hwparams, sizeof(tmpparams)); - dstparams = params; - } - - /* Convert to interleaved format if needed */ - if (!srcparams.format.interleave && - (srcparams.format.voices != dstparams->format.voices || - (srcparams.format.rate != dstparams->format.rate && - srcparams.format.voices > 1))) { - tmpparams.format.interleave = 1; - pdprintf("params interleave plugin: src=%i, dst=%i\n", srcparams.format.interleave, tmpparams.format.interleave); - err = snd_pcm_plugin_build_interleave(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.interleave = 1; - /* Avoid useless interleave revert */ - if (params->channel == SND_PCM_CHANNEL_PLAYBACK && - (hwinfo.flags & SND_PCM_CHNINFO_INTERLEAVE)) - dstparams->format.interleave = 1; - } - - /* voices reduction */ - if (srcparams.format.voices > dstparams->format.voices) { - tmpparams.format.voices = dstparams->format.voices; - pdprintf("params voices reduction: src=%i, dst=%i\n", srcparams.format.voices, tmpparams.format.voices); - err = snd_pcm_plugin_build_voices(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.voices = dstparams->format.voices; - } - - /* rate resampling (when the source format has a highter resolution) */ - if (srcparams.format.format > dstparams->format.format && - srcparams.format.format <= SND_PCM_SFMT_FLOAT64_BE && - srcparams.format.rate != dstparams->format.rate) { - tmpparams.format.rate = dstparams->format.rate; - pdprintf("params rate resampling (1): src=%i, dst=%i\n", srcparams.format.rate, tmpparams.format.rate); - err = snd_pcm_plugin_build_rate(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.rate = dstparams->format.rate; - } - - /* format change */ - if (srcparams.format.format != dstparams->format.format) { - tmpparams.format.format = dstparams->format.format; - pdprintf("params format change: src=%i, dst=%i\n", srcparams.format.format, tmpparams.format.format); - switch (params->format.format) { - case SND_PCM_SFMT_MU_LAW: - err = snd_pcm_plugin_build_mulaw(&srcparams.format, - &tmpparams.format, - &plugin); - break; - case SND_PCM_SFMT_A_LAW: - err = snd_pcm_plugin_build_alaw(&srcparams.format, - &tmpparams.format, - &plugin); - break; - case SND_PCM_SFMT_IMA_ADPCM: - err = snd_pcm_plugin_build_adpcm(&srcparams.format, - &tmpparams.format, - &plugin); - break; - default: - err = snd_pcm_plugin_build_linear(&srcparams.format, - &tmpparams.format, - &plugin); - } - if (err < 0) - return err; - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.format = dstparams->format.format; - } - - /* rate resampling (when the destonation format has an equal or highter resolution) */ - if (srcparams.format.format <= dstparams->format.format && - srcparams.format.rate != dstparams->format.rate) { - tmpparams.format.rate = dstparams->format.rate; - pdprintf("params rate resampling (2): src=%i, dst=%i\n", srcparams.format.rate, tmpparams.format.rate); - err = snd_pcm_plugin_build_rate(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.rate = dstparams->format.rate; - } - - /* voices extension */ - if (srcparams.format.voices < dstparams->format.voices) { - tmpparams.format.voices = dstparams->format.voices; - pdprintf("params voices extension: src=%i, dst=%i\n", srcparams.format.voices, tmpparams.format.voices); - err = snd_pcm_plugin_build_voices(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.voices = dstparams->format.voices; - } - - /* interleave change */ - if (params->format.voices > 1 && - hwinfo.mode == SND_PCM_MODE_BLOCK && - srcparams.format.interleave != dstparams->format.interleave) { - tmpparams.format.interleave = dstparams->format.interleave; - pdprintf("params interleave change: src=%i, dst=%i\n", srcparams.format.interleave, tmpparams.format.interleave); - err = snd_pcm_plugin_build_interleave(&srcparams.format, - &tmpparams.format, - &plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - err = snd_pcm_plugin_append(pcm, params->channel, plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcparams.format.interleave = dstparams->format.interleave; - } + /* add necessary plugins */ + if ((err = snd_pcm_plugin_format(pcm, params, &hwparams, &hwinfo)) < 0) + return err; /* * I/O plugins diff --git a/src/pcm/pcm_plugin_build.c b/src/pcm/pcm_plugin_build.c new file mode 100644 index 00000000..40290592 --- /dev/null +++ b/src/pcm/pcm_plugin_build.c @@ -0,0 +1,439 @@ +/* + * PCM Plug-In shared (kernel/library) code + * Copyright (c) 1999 by Jaroslav Kysela + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef __KERNEL__ +#define PLUGIN_DEBUG +#include "../include/driver.h" +#include "../include/pcm.h" +typedef snd_pcm_runtime_t PLUGIN_BASE; +#define snd_pcm_plugin_first(pb, channel) ((pb)->oss.plugin_first) +#define snd_pcm_plugin_last(pb, channel) ((pb)->oss.plugin_last) +#define snd_pcm_plugin_append(pb, channel, plugin) snd_pcm_oss_plugin_append(pb, plugin) +#else +#include +#include "pcm_local.h" +typedef snd_pcm_t PLUGIN_BASE; +#endif + + +ssize_t snd_pcm_plugin_transfer_size(PLUGIN_BASE *pb, int channel, size_t drv_size) +{ + snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; + + if (!pb || (channel != SND_PCM_CHANNEL_PLAYBACK && + channel != SND_PCM_CHANNEL_CAPTURE)) + return -EINVAL; + if (drv_size == 0) + return 0; + if (drv_size < 0) + return -EINVAL; + if (channel == SND_PCM_CHANNEL_PLAYBACK) { + plugin = snd_pcm_plugin_last(pb, channel); + while (plugin) { + plugin_prev = plugin->prev; + if (plugin->src_size) + drv_size = plugin->src_size(plugin, drv_size); + plugin = plugin_prev; + } + } else if (channel == SND_PCM_CHANNEL_CAPTURE) { + plugin = snd_pcm_plugin_first(pb, channel); + while (plugin) { + plugin_next = plugin->next; + if (plugin->dst_size) + drv_size = plugin->dst_size(plugin, drv_size); + plugin = plugin_next; + } + } + return drv_size; +} + +ssize_t snd_pcm_plugin_hardware_size(PLUGIN_BASE *pb, int channel, size_t trf_size) +{ + snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; + + if (!pb || (channel != SND_PCM_CHANNEL_PLAYBACK && + channel != SND_PCM_CHANNEL_CAPTURE)) + return -EINVAL; + if (trf_size == 0) + return 0; + if (trf_size < 0) + return -EINVAL; + if (channel == SND_PCM_CHANNEL_PLAYBACK) { + plugin = snd_pcm_plugin_first(pb, channel); + while (plugin) { + plugin_next = plugin->next; + if (plugin->dst_size) + trf_size = plugin->dst_size(plugin, trf_size); + plugin = plugin_next; + } + } else if (channel == SND_PCM_CHANNEL_CAPTURE) { + plugin = snd_pcm_plugin_last(pb, channel); + while (plugin) { + plugin_prev = plugin->prev; + if (plugin->src_size) + trf_size = plugin->src_size(plugin, trf_size); + plugin = plugin_prev; + } + } + return trf_size; +} + + +unsigned int snd_pcm_plugin_formats(unsigned int formats) +{ + formats |= SND_PCM_FMT_MU_LAW | SND_PCM_FMT_A_LAW | SND_PCM_FMT_IMA_ADPCM; + 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; + return formats; +} + +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) + 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; + } + 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; +#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 { + return -EINVAL; + } + break; +#endif + default: + return -EINVAL; + } + } + + /* voices */ + if (params->format.voices < hwinfo->min_voices || + params->format.voices > hwinfo->max_voices) { + int dst_voices = params->format.voices < hwinfo->min_voices ? + hwinfo->min_voices : hwinfo->max_voices; + if ((params->format.rate < hwinfo->min_rate || + params->format.rate > hwinfo->max_rate) && + dst_voices > 2) + dst_voices = 2; + hwparams->format.voices = dst_voices; + } + + /* rate */ + if (params->format.rate < hwinfo->min_rate || + params->format.rate > hwinfo->max_rate) { + int dst_rate = params->format.rate < hwinfo->min_rate ? + hwinfo->min_rate : hwinfo->max_rate; + hwparams->format.rate = dst_rate; + } + + /* interleave */ + if (!(hwinfo->flags & SND_PCM_CHNINFO_INTERLEAVE)) + hwparams->format.interleave = 0; + if (!(hwinfo->flags & SND_PCM_CHNINFO_NONINTERLEAVE)) + hwparams->format.interleave = 1; + return 0; +} + + +int snd_pcm_plugin_format(PLUGIN_BASE *pb, + snd_pcm_channel_params_t *params, + snd_pcm_channel_params_t *hwparams, + snd_pcm_channel_info_t *hwinfo) +{ + snd_pcm_channel_params_t srcparams, tmpparams; + snd_pcm_channel_params_t *dstparams; + snd_pcm_plugin_t *plugin; + int err; + + if (params->channel == SND_PCM_CHANNEL_PLAYBACK) { + memcpy(&srcparams, params, sizeof(srcparams)); + memcpy(&tmpparams, params, sizeof(tmpparams)); + dstparams = hwparams; + } else { + memcpy(&srcparams, &hwparams, sizeof(srcparams)); + memcpy(&tmpparams, &hwparams, sizeof(tmpparams)); + dstparams = params; + } + + pdprintf("srcparams: interleave=%i, format=%i, rate=%i, voices=%i\n", + srcparams.format.interleave, + srcparams.format.format, + srcparams.format.rate, + srcparams.format.voices); + pdprintf("dstparams: interleave=%i, format=%i, rate=%i, voices=%i\n", + dstparams->format.interleave, + dstparams->format.format, + dstparams->format.rate, + dstparams->format.voices); + /* Convert to interleaved format if needed */ + if (!srcparams.format.interleave && + (srcparams.format.voices != dstparams->format.voices || + (srcparams.format.rate != dstparams->format.rate && + srcparams.format.voices > 1))) { + tmpparams.format.interleave = 1; + err = snd_pcm_plugin_build_interleave(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params interleave change: src=%i, dst=%i returns %i\n", srcparams.format.interleave, tmpparams.format.interleave, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.interleave = 1; + /* Avoid useless interleave revert */ + if (params->channel == SND_PCM_CHANNEL_PLAYBACK && + (hwinfo->flags & SND_PCM_CHNINFO_INTERLEAVE)) + dstparams->format.interleave = 1; + } + + /* voices reduction */ + if (srcparams.format.voices > dstparams->format.voices) { + tmpparams.format.voices = dstparams->format.voices; + err = snd_pcm_plugin_build_voices(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params voices reduction: src=%i, dst=%i returns %i\n", srcparams.format.voices, tmpparams.format.voices, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.voices = dstparams->format.voices; + } + + /* rate down resampling */ + if (srcparams.format.rate > dstparams->format.rate && + snd_pcm_format_linear(srcparams.format.format) && + snd_pcm_format_width(srcparams.format.format) <= 16 && + snd_pcm_format_width(srcparams.format.format) >= snd_pcm_format_width(srcparams.format.format)) { + tmpparams.format.rate = dstparams->format.rate; + err = snd_pcm_plugin_build_rate(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params rate down resampling: src=%i, dst=%i\n returns %i", srcparams.format.rate, tmpparams.format.rate, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.rate = dstparams->format.rate; + } + + /* format change */ + if (srcparams.format.format != dstparams->format.format) { + tmpparams.format.format = dstparams->format.format; + switch (srcparams.format.format) { + case SND_PCM_SFMT_MU_LAW: + err = snd_pcm_plugin_build_mulaw(&srcparams.format, + &tmpparams.format, + &plugin); + break; +#ifndef __KERNEL__ + case SND_PCM_SFMT_A_LAW: + err = snd_pcm_plugin_build_alaw(&srcparams.format, + &tmpparams.format, + &plugin); + break; + case SND_PCM_SFMT_IMA_ADPCM: + err = snd_pcm_plugin_build_adpcm(&srcparams.format, + &tmpparams.format, + &plugin); + break; +#endif + default: + err = snd_pcm_plugin_build_linear(&srcparams.format, + &tmpparams.format, + &plugin); + } + pdprintf("params format change: src=%i, dst=%i returns %i\n", srcparams.format.format, tmpparams.format.format, err); + if (err < 0) + return err; + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.format = dstparams->format.format; + } + + /* rate resampling */ + if (srcparams.format.rate != dstparams->format.rate) { + tmpparams.format.rate = dstparams->format.rate; + err = snd_pcm_plugin_build_rate(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params rate resampling: src=%i, dst=%i return %i\n", srcparams.format.rate, tmpparams.format.rate, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.rate = dstparams->format.rate; + } + + /* voices extension */ + if (srcparams.format.voices != dstparams->format.voices) { + tmpparams.format.voices = dstparams->format.voices; + err = snd_pcm_plugin_build_voices(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params voices extension: src=%i, dst=%i returns %i\n", srcparams.format.voices, tmpparams.format.voices, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.voices = dstparams->format.voices; + } + + /* interleave change */ + if (dstparams->format.voices > 1 && + hwinfo->mode == SND_PCM_MODE_BLOCK && + srcparams.format.interleave != dstparams->format.interleave) { + tmpparams.format.interleave = dstparams->format.interleave; + err = snd_pcm_plugin_build_interleave(&srcparams.format, + &tmpparams.format, + &plugin); + pdprintf("params interleave change: src=%i, dst=%i return %i\n", srcparams.format.interleave, tmpparams.format.interleave, err); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + err = snd_pcm_plugin_append(pb, params->channel, plugin); + if (err < 0) { + snd_pcm_plugin_free(plugin); + return err; + } + srcparams.format.interleave = dstparams->format.interleave; + } + if (srcparams.format.interleave != dstparams->format.interleave && + srcparams.format.voices > 1) + return -EINVAL; + if (srcparams.format.format != dstparams->format.format) + return -EINVAL; + if (srcparams.format.rate != dstparams->format.rate) + return -EINVAL; + if (srcparams.format.voices != dstparams->format.voices) + return -EINVAL; + return 0; +} diff --git a/src/pcm/plugin/adpcm.c b/src/pcm/plugin/adpcm.c index accc705c..acd1e04b 100644 --- a/src/pcm/plugin/adpcm.c +++ b/src/pcm/plugin/adpcm.c @@ -892,9 +892,12 @@ int snd_pcm_plugin_build_adpcm(snd_pcm_format_t *src_format, return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave || - src_format->voices != dst_format->voices || - src_format->rate != dst_format->rate) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) + return -EINVAL; + if (src_format->rate != dst_format->rate) + return -EINVAL; + if (src_format->voices != dst_format->voices) return -EINVAL; if (dst_format->format == SND_PCM_SFMT_IMA_ADPCM) { diff --git a/src/pcm/plugin/alaw.c b/src/pcm/plugin/alaw.c index 9bfcea8c..5733886d 100644 --- a/src/pcm/plugin/alaw.c +++ b/src/pcm/plugin/alaw.c @@ -426,7 +426,8 @@ int snd_pcm_plugin_build_alaw(snd_pcm_format_t *src_format, return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) return -EINVAL; if (src_format->rate != dst_format->rate) return -EINVAL; diff --git a/src/pcm/plugin/interleave.c b/src/pcm/plugin/interleave.c index 2038ff36..cd1a17d8 100644 --- a/src/pcm/plugin/interleave.c +++ b/src/pcm/plugin/interleave.c @@ -18,7 +18,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ - + +#ifdef __KERNEL__ +#include "../../include/driver.h" +#include "../../include/pcm_plugin.h" +#else #include #include #include @@ -27,6 +31,7 @@ #include #include #include "../pcm_local.h" +#endif /* * Basic interleave / non-interleave conversion plugin @@ -188,6 +193,8 @@ int snd_pcm_plugin_build_interleave(snd_pcm_format_t *src_format, if (!r_plugin) return -EINVAL; + *r_plugin = NULL; + if (src_format->interleave && !dst_format->interleave) { cmd = _INTERLEAVE_NON; } else if (!src_format->interleave && dst_format->interleave) { @@ -236,3 +243,7 @@ int snd_pcm_plugin_build_interleave(snd_pcm_format_t *src_format, *r_plugin = plugin; return 0; } + +#ifdef __KERNEL__ +EXPORT_SYMBOL(snd_pcm_plugin_build_interleave); +#endif diff --git a/src/pcm/plugin/linear.c b/src/pcm/plugin/linear.c index 23f7dc22..d5173ab9 100644 --- a/src/pcm/plugin/linear.c +++ b/src/pcm/plugin/linear.c @@ -18,7 +18,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ - + +#ifdef __KERNEL__ +#include "../../include/driver.h" +#include "../../include/pcm.h" +#include "../../include/pcm_plugin.h" +#else #include #include #include @@ -27,6 +32,7 @@ #include #include #include "../pcm_local.h" +#endif /* * Basic linear conversion plugin @@ -48,14 +54,15 @@ typedef enum { } combination_t; typedef enum { - NONE, - SOURCE, - DESTINATION, - BOTH, - SIGN_NONE, - SIGN_SOURCE, - SIGN_DESTINATION, - SIGN_BOTH, + NONE = 0, + SOURCE = 1, + DESTINATION = 2, + BOTH = 3, + SIGN = 4, + SIGN_NONE = 4, + SIGN_SOURCE = 5, + SIGN_DESTINATION = 6, + SIGN_BOTH = 7, } endian_t; struct linear_private_data { @@ -128,8 +135,8 @@ static void linear_conv_sign_16bit_8bit_swap(unsigned short *src_ptr, } static ssize_t linear_transfer(snd_pcm_plugin_t *plugin, - char *src_ptr, size_t src_size, - char *dst_ptr, size_t dst_size) + char *src_ptr, size_t src_size, + char *dst_ptr, size_t dst_size) { struct linear_private_data *data; @@ -170,13 +177,13 @@ static ssize_t linear_transfer(snd_pcm_plugin_t *plugin, case NONE: linear_conv_16bit_8bit((short *)src_ptr, dst_ptr, src_size); break; - case DESTINATION: + 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_DESTINATION: + case SIGN_SOURCE: linear_conv_sign_16bit_8bit_swap((short *)src_ptr, dst_ptr, src_size); break; default: @@ -248,68 +255,6 @@ static ssize_t linear_dst_size(snd_pcm_plugin_t *plugin, size_t size) } } -static int linear_wide(int format) -{ - if (format >= 0 && format <= 1) - return 8; - if (format >= 2 && format <= 5) - return 16; - if (format >= 6 && format <= 9) - return 24; - if (format >= 10 && format <= 13) - return 32; - return -1; -} - -static int linear_endian(int format) -{ - switch (format) { - case SND_PCM_SFMT_S8: - case SND_PCM_SFMT_U8: - return 0; - case SND_PCM_SFMT_S16_LE: - case SND_PCM_SFMT_U16_LE: - case SND_PCM_SFMT_S24_LE: - case SND_PCM_SFMT_U24_LE: - case SND_PCM_SFMT_S32_LE: - case SND_PCM_SFMT_U32_LE: - return __LITTLE_ENDIAN; - case SND_PCM_SFMT_S16_BE: - case SND_PCM_SFMT_U16_BE: - case SND_PCM_SFMT_S24_BE: - case SND_PCM_SFMT_U24_BE: - case SND_PCM_SFMT_S32_BE: - case SND_PCM_SFMT_U32_BE: - return __BIG_ENDIAN; - default: - return -1; - } -} - -static int linear_sign(int format) -{ - switch (format) { - case SND_PCM_SFMT_S8: - case SND_PCM_SFMT_S16_LE: - case SND_PCM_SFMT_S16_BE: - case SND_PCM_SFMT_S24_LE: - case SND_PCM_SFMT_S24_BE: - case SND_PCM_SFMT_S32_LE: - case SND_PCM_SFMT_S32_BE: - return 1; - case SND_PCM_SFMT_U8: - case SND_PCM_SFMT_U16_LE: - case SND_PCM_SFMT_U24_LE: - case SND_PCM_SFMT_U32_LE: - case SND_PCM_SFMT_U16_BE: - case SND_PCM_SFMT_U24_BE: - case SND_PCM_SFMT_U32_BE: - return 0; - default: - return -1; - } -} - int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -317,40 +262,40 @@ 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 wide1, wide2, endian1, endian2, sign1, sign2; + int width1, width2, endian1, endian2, sign1, sign2; if (!r_plugin) return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) return -EINVAL; if (src_format->rate != dst_format->rate) return -EINVAL; if (src_format->voices != dst_format->voices) return -EINVAL; - - wide1 = linear_wide(src_format->format); - endian1 = linear_endian(src_format->format); - sign1 = linear_sign(src_format->format); - wide2 = linear_wide(dst_format->format); - endian2 = linear_endian(dst_format->format); - sign2 = linear_sign(dst_format->format); - if (wide1 < 0 || wide2 < 0 || endian1 < 0 || endian2 < 0 || sign1 < 0 || sign2 < 0) + if (!(snd_pcm_format_linear(src_format->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); #if __BYTE_ORDER == __LITTLE_ENDIAN - endian1 = endian1 == __BIG_ENDIAN ? 1 : 0; - endian2 = endian2 == __BIG_ENDIAN ? 1 : 0; + endian1 = snd_pcm_format_little_endian(src_format->format); + endian2 = snd_pcm_format_little_endian(dst_format->format); #elif __BYTE_ORDER == __BIG_ENDIAN - endian1 = endian1 == __LITTLE_ENDIAN ? 1 : 0; - endian2 = endian2 == __LITTLE_ENDIAN ? 1 : 0; + endian1 = snd_pcm_format_big_endian(src_format->format); + endian2 = snd_pcm_format_big_endian(dst_format->format); #else #error "Unsupported endian..." #endif cmd = _8BIT_16BIT; - switch (wide1) { + switch (width1) { case 8: - switch (wide2) { + switch (width2) { case 16: cmd = _8BIT_16BIT; break; case 24: cmd = _8BIT_24BIT; break; case 32: cmd = _8BIT_32BIT; break; @@ -358,7 +303,7 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, } break; case 16: - switch (wide2) { + switch (width2) { case 8: cmd = _16BIT_8BIT; break; case 24: cmd = _16BIT_24BIT; break; case 32: cmd = _16BIT_32BIT; break; @@ -366,7 +311,7 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, } break; case 24: - switch (wide2) { + switch (width2) { case 8: cmd = _24BIT_8BIT; break; case 16: cmd = _24BIT_16BIT; break; case 32: cmd = _24BIT_32BIT; break; @@ -374,7 +319,7 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, } break; case 32: - switch (wide2) { + switch (width2) { case 8: cmd = _32BIT_8BIT; break; case 16: cmd = _32BIT_16BIT; break; case 24: cmd = _32BIT_24BIT; break; @@ -390,20 +335,20 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, return -ENOMEM; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); data->cmd = cmd; - if (!endian1 && !endian2) { - data->endian = NONE; - } else if (endian1 && !endian2) { - data->endian = SOURCE; - } else if (!endian1 && endian2) { - data->endian = DESTINATION; - } else { - data->endian = BOTH; - } + data->endian = NONE; + if (endian1 == 0) + data->endian |= SOURCE; + if (endian2 == 0) + data->endian |= DESTINATION; if (sign1 != sign2) - data->endian += 4; + data->endian |= SIGN; plugin->transfer = linear_transfer; plugin->src_size = linear_src_size; plugin->dst_size = linear_dst_size; *r_plugin = plugin; return 0; } + +#ifdef __KERNEL__ +EXPORT_SYMBOL(snd_pcm_plugin_build_linear); +#endif diff --git a/src/pcm/plugin/mulaw.c b/src/pcm/plugin/mulaw.c index cbbe02bb..d6a62ce0 100644 --- a/src/pcm/plugin/mulaw.c +++ b/src/pcm/plugin/mulaw.c @@ -21,6 +21,11 @@ * */ +#ifdef __KERNEL__ +#include "../../include/driver.h" +#include "../../include/pcm_plugin.h" +#define bswap_16(x) __swab16((x)) +#else #include #include #include @@ -29,6 +34,7 @@ #include #include #include "../pcm_local.h" +#endif #define SIGN_BIT (0x80) /* Sign bit for a u-law byte. */ #define QUANT_MASK (0xf) /* Quantization field mask. */ @@ -241,8 +247,8 @@ static void mulaw_conv_mulaw_swap_u16bit(unsigned char *src_ptr, unsigned short } static ssize_t mulaw_transfer(snd_pcm_plugin_t *plugin, - char *src_ptr, size_t src_size, - char *dst_ptr, size_t dst_size) + char *src_ptr, size_t src_size, + char *dst_ptr, size_t dst_size) { struct mulaw_private_data *data; @@ -436,7 +442,8 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_format_t *src_format, return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) return -EINVAL; if (src_format->rate != dst_format->rate) return -EINVAL; @@ -480,3 +487,7 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_format_t *src_format, *r_plugin = plugin; return 0; } + +#ifdef __KERNEL__ +EXPORT_SYMBOL(snd_pcm_plugin_build_mulaw); +#endif diff --git a/src/pcm/plugin/rate.c b/src/pcm/plugin/rate.c index 4f27946f..1506b6c4 100644 --- a/src/pcm/plugin/rate.c +++ b/src/pcm/plugin/rate.c @@ -19,6 +19,10 @@ * */ +#ifdef __KERNEL__ +#include "../../include/driver.h" +#include "../../include/pcm_plugin.h" +#else #include #include #include @@ -27,6 +31,7 @@ #include #include #include "../pcm_local.h" +#endif #define SHIFT 11 #define BITS (1<sample_size == 2) { if (data->src_rate < data->dst_rate) { - mix16_expand(data, data->src_voices, + resample16_expand(data, data->src_voices, (signed short *)src_ptr, src_size / (data->src_voices * 2), (signed short *)dst_ptr, dst_size / (data->dst_voices * 2)); } else { - mix16_shrink(data, data->src_voices, + resample16_shrink(data, data->src_voices, (signed short *)src_ptr, src_size / (data->src_voices * 2), (signed short *)dst_ptr, dst_size / (data->dst_voices * 2)); } } else { if (data->src_rate < data->dst_rate) { - mix8_expand(data, data->src_voices, + resample8_expand(data, data->src_voices, src_ptr, src_size / data->src_voices, dst_ptr, dst_size / data->dst_voices); } else { - mix8_shrink(data, data->src_voices, + resample8_shrink(data, data->src_voices, src_ptr, src_size / data->src_voices, dst_ptr, dst_size / data->dst_voices); } @@ -365,7 +370,8 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format, return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) return -EINVAL; if (src_format->format != dst_format->format) return -EINVAL; @@ -410,3 +416,7 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format, *r_plugin = plugin; return 0; } + +#ifdef __KERNEL__ +EXPORT_SYMBOL(snd_pcm_plugin_build_rate); +#endif diff --git a/src/pcm/plugin/voices.c b/src/pcm/plugin/voices.c index a5710f52..97c9580b 100644 --- a/src/pcm/plugin/voices.c +++ b/src/pcm/plugin/voices.c @@ -19,6 +19,10 @@ * */ +#ifdef __KERNEL__ +#include "../../include/driver.h" +#include "../../include/pcm_plugin.h" +#else #include #include #include @@ -27,6 +31,7 @@ #include #include #include "../pcm_local.h" +#endif /* * Basic voices conversion plugin @@ -59,7 +64,6 @@ static void merge_8bit_unsigned(unsigned char *src_ptr, unsigned char *dst_ptr, int size) { - printf("unsigned!!\n"); while (size-- > 0) { *dst_ptr++ = ((int)*src_ptr + (int)*(src_ptr + 1)) / 2; src_ptr += 2; @@ -170,7 +174,8 @@ int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format, return -EINVAL; *r_plugin = NULL; - if (src_format->interleave != dst_format->interleave) + if (src_format->interleave != dst_format->interleave && + src_format->voices > 1) return -EINVAL; if (!dst_format->interleave) return -EINVAL; @@ -202,3 +207,7 @@ int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format, *r_plugin = plugin; return 0; } + +#ifdef __KERNEL__ +EXPORT_SYMBOL(snd_pcm_plugin_build_voices); +#endif