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 */
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
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
*
*/
+#ifdef ALSA_BUILD
+#include "../include/driver.h"
+#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
+#include <endian.h>
+#include <byteswap.h>
#include "pcm_local.h"
+#endif
int snd_pcm_format_signed(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) {
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)
{
*
*/
-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;
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
*/
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
--- /dev/null
+/*
+ * PCM Plug-In shared (kernel/library) code
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ * 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 <errno.h>
+#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;
+}
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) {
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;
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-
+
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include "../pcm_local.h"
+#endif
/*
* Basic interleave / non-interleave conversion plugin
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) {
*r_plugin = plugin;
return 0;
}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(snd_pcm_plugin_build_interleave);
+#endif
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include "../pcm_local.h"
+#endif
/*
* Basic linear conversion plugin
} 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 {
}
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;
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:
}
}
-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)
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;
}
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;
}
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;
}
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;
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
*
*/
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#define bswap_16(x) __swab16((x))
+#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include "../pcm_local.h"
+#endif
#define SIGN_BIT (0x80) /* Sign bit for a u-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
}
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;
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;
*r_plugin = plugin;
return 0;
}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(snd_pcm_plugin_build_mulaw);
+#endif
*
*/
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include "../pcm_local.h"
+#endif
#define SHIFT 11
#define BITS (1<<SHIFT)
ssize_t old_src_size, old_dst_size;
};
-static void mix16_expand(struct rate_private_data *data, int voices,
- signed short *src_ptr, int src_size,
- signed short *dst_ptr, int dst_size)
+static void resample16_expand(struct rate_private_data *data, int voices,
+ signed short *src_ptr, int src_size,
+ signed short *dst_ptr, int dst_size)
{
unsigned int pos;
signed int val;
}
}
-static void mix16_shrink(struct rate_private_data *data, int voices,
- signed short *src_ptr, int src_size,
- signed short *dst_ptr, int dst_size)
+static void resample16_shrink(struct rate_private_data *data, int voices,
+ signed short *src_ptr, int src_size,
+ signed short *dst_ptr, int dst_size)
{
unsigned int pos;
signed int val;
}
}
-static void mix8_expand(struct rate_private_data *data, int voices,
- unsigned char *src_ptr, int src_size,
- unsigned char *dst_ptr, int dst_size)
+static void resample8_expand(struct rate_private_data *data, int voices,
+ unsigned char *src_ptr, int src_size,
+ unsigned char *dst_ptr, int dst_size)
{
unsigned int pos;
signed int val;
}
}
-static void mix8_shrink(struct rate_private_data *data, int voices,
- unsigned char *src_ptr, int src_size,
- unsigned char *dst_ptr, int dst_size)
+static void resample8_shrink(struct rate_private_data *data, int voices,
+ unsigned char *src_ptr, int src_size,
+ unsigned char *dst_ptr, int dst_size)
{
unsigned int pos;
signed int val;
return -EINVAL;
if (data->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);
}
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;
*r_plugin = plugin;
return 0;
}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(snd_pcm_plugin_build_rate);
+#endif
*
*/
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include "../pcm_local.h"
+#endif
/*
* Basic voices conversion plugin
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;
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;
*r_plugin = plugin;
return 0;
}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(snd_pcm_plugin_build_voices);
+#endif