OSDN Git Service

Abramo Bagnara <abramo@alsa-project.org>
authorJaroslav Kysela <perex@perex.cz>
Sat, 11 Dec 1999 11:46:05 +0000 (11:46 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sat, 11 Dec 1999 11:46:05 +0000 (11:46 +0000)
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

13 files changed:
include/pcm.h
src/pcm/Makefile.am
src/pcm/pcm_local.h
src/pcm/pcm_misc.c
src/pcm/pcm_plugin.c
src/pcm/pcm_plugin_build.c [new file with mode: 0644]
src/pcm/plugin/adpcm.c
src/pcm/plugin/alaw.c
src/pcm/plugin/interleave.c
src/pcm/plugin/linear.c
src/pcm/plugin/mulaw.c
src/pcm/plugin/rate.c
src/pcm/plugin/voices.c

index b58f5c1..f277a7a 100644 (file)
@@ -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 */
index 0e48026..3ebb991 100644 (file)
@@ -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
 
index bc90db8..306bc78 100644 (file)
@@ -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
index e0f3ae0..e3c7048 100644 (file)
  *
  */
   
+#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)
 {
@@ -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) {
index db2c67e..d79ac7c 100644 (file)
@@ -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 (file)
index 0000000..4029059
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ *  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;
+}
index accc705..acd1e04 100644 (file)
@@ -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) {
index 9bfcea8..5733886 100644 (file)
@@ -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;
index 2038ff3..cd1a17d 100644 (file)
  *   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>
@@ -27,6 +31,7 @@
 #include <endian.h>
 #include <byteswap.h>
 #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
index 23f7dc2..d5173ab 100644 (file)
  *   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>
@@ -27,6 +32,7 @@
 #include <endian.h>
 #include <byteswap.h>
 #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
index cbbe02b..d6a62ce 100644 (file)
  *
  */
   
+#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>
@@ -29,6 +34,7 @@
 #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. */
@@ -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
index 4f27946..1506b6c 100644 (file)
  *
  */
   
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#else
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -27,6 +31,7 @@
 #include <endian.h>
 #include <byteswap.h>
 #include "../pcm_local.h"
+#endif
 
 #define SHIFT  11
 #define BITS   (1<<SHIFT)
@@ -51,9 +56,9 @@ struct rate_private_data {
        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;
@@ -97,9 +102,9 @@ static void mix16_expand(struct rate_private_data *data, int voices,
        }
 }
 
-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;
@@ -140,9 +145,9 @@ static void mix16_shrink(struct rate_private_data *data, int voices,
        }
 }
 
-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;
@@ -186,9 +191,9 @@ static void mix8_expand(struct rate_private_data *data, int voices,
        }
 }
 
-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;
@@ -245,21 +250,21 @@ static ssize_t rate_transfer(snd_pcm_plugin_t *plugin,
                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);
                }
@@ -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
index a5710f5..97c9580 100644 (file)
  *
  */
   
+#ifdef __KERNEL__
+#include "../../include/driver.h"
+#include "../../include/pcm_plugin.h"
+#else
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -27,6 +31,7 @@
 #include <endian.h>
 #include <byteswap.h>
 #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