OSDN Git Service

Finished lfloat plugin.
authorJaroslav Kysela <perex@perex.cz>
Tue, 27 Nov 2001 14:24:44 +0000 (14:24 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 27 Nov 2001 14:24:44 +0000 (14:24 +0000)
Added code to plug plugin to handle linear float / integer conversions.

src/pcm/pcm_ladspa.c
src/pcm/pcm_lfloat.c
src/pcm/pcm_params.c
src/pcm/pcm_plug.c
src/pcm/pcm_plugin.h
src/pcm/plugin_ops.h

index 0cfc34d..75e6802 100644 (file)
@@ -194,6 +194,11 @@ snd_pcm_ladspa_write_areas(snd_pcm_t *pcm,
        // snd_pcm_ladspa_t *ladspa = pcm->private_data;
        if (size > *slave_sizep)
                size = *slave_sizep;
+#if 1  // no processing - for testing purposes only
+       snd_pcm_areas_copy(slave_areas, slave_offset,
+                          areas, offset,
+                          pcm->channels, size, pcm->format);
+#endif
        *slave_sizep = size;
        return size;
 }
@@ -210,6 +215,11 @@ snd_pcm_ladspa_read_areas(snd_pcm_t *pcm,
        // snd_pcm_ladspa_t *ladspa = pcm->private_data;
        if (size > *slave_sizep)
                size = *slave_sizep;
+#if 1  // no processing - for testing purposes only
+       snd_pcm_areas_copy(areas, offset,
+                          slave_areas, slave_offset,
+                          pcm->channels, size, pcm->format);
+#endif
        *slave_sizep = size;
        return size;
 }
index b2ecade..dfecb39 100644 (file)
@@ -23,6 +23,9 @@
 #include "pcm_local.h"
 #include "pcm_plugin.h"
 
+typedef float float_t;
+typedef double double_t;
+
 #ifndef PIC
 /* entry for static linking */
 const char *_snd_module_pcm_float = "";
@@ -31,83 +34,111 @@ const char *_snd_module_pcm_float = "";
 typedef struct {
        /* This field need to be the first */
        snd_pcm_plugin_t plug;
-       unsigned int conv_idx;
+       unsigned int int32_idx;
+       unsigned int float32_idx;
        snd_pcm_format_t sformat;
+       void (*func)(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
+                    const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
+                    unsigned int channels, snd_pcm_uframes_t frames,
+                    unsigned int get32idx, unsigned int put32floatidx);
 } snd_pcm_lfloat_t;
 
-int snd_pcm_lfloat_convert_index(snd_pcm_format_t src_format,
-                                snd_pcm_format_t dst_format)
+int snd_pcm_lfloat_get_s32_index(snd_pcm_format_t format)
 {
-       int src_endian, dst_endian, sign, src_width, dst_width;
+       int width, endian;
 
-       sign = (snd_pcm_format_signed(src_format) !=
-               snd_pcm_format_signed(dst_format));
+       switch (format) {
+       case SND_PCM_FORMAT_FLOAT_LE:
+       case SND_PCM_FORMAT_FLOAT_BE:
+               width = 32;
+               break;
+       case SND_PCM_FORMAT_FLOAT64_LE:
+       case SND_PCM_FORMAT_FLOAT64_BE:
+               width = 64;
+               break;
+       default:
+               return -EINVAL;
+       }
 #ifdef SND_LITTLE_ENDIAN
-       src_endian = snd_pcm_format_big_endian(src_format);
-       dst_endian = snd_pcm_format_big_endian(dst_format);
+       endian = snd_pcm_format_big_endian(format);
 #else
-       src_endian = snd_pcm_format_little_endian(src_format);
-       dst_endian = snd_pcm_format_little_endian(dst_format);
+       endian = snd_pcm_format_little_endian(format);
 #endif
-
-       if (src_endian < 0)
-               src_endian = 0;
-       if (dst_endian < 0)
-               dst_endian = 0;
-
-       src_width = snd_pcm_format_width(src_format) / 8 - 1;
-       dst_width = snd_pcm_format_width(dst_format) / 8 - 1;
-
-       return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
+       return ((width / 32)-1) * 2 + endian;
 }
 
-int snd_pcm_lfloat_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
+int snd_pcm_lfloat_put_s32_index(snd_pcm_format_t format)
 {
-       int sign, width, endian;
-       sign = (snd_pcm_format_signed(src_format) != 
-               snd_pcm_format_signed(dst_format));
-       width = snd_pcm_format_width(src_format) / 8 - 1;
-#ifdef SND_LITTLE_ENDIAN
-       endian = snd_pcm_format_big_endian(src_format);
-#else
-       endian = snd_pcm_format_little_endian(src_format);
-#endif
-       if (endian < 0)
-               endian = 0;
-       return width * 4 + endian * 2 + sign;
+       return snd_pcm_lfloat_get_s32_index(format);
 }
 
-int snd_pcm_lfloat_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
+void snd_pcm_lfloat_convert_integer_float(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
+                                         const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
+                                         unsigned int channels, snd_pcm_uframes_t frames,
+                                         unsigned int get32idx, unsigned int put32floatidx)
 {
-       int sign, width, endian;
-       sign = (snd_pcm_format_signed(src_format) != 
-               snd_pcm_format_signed(dst_format));
-       width = snd_pcm_format_width(dst_format) / 8 - 1;
-#ifdef SND_LITTLE_ENDIAN
-       endian = snd_pcm_format_big_endian(dst_format);
-#else
-       endian = snd_pcm_format_little_endian(dst_format);
-#endif
-       if (endian < 0)
-               endian = 0;
-       return width * 4 + endian * 2 + sign;
+#define GET32_LABELS
+#define PUT32F_LABELS
+#include "plugin_ops.h"
+#undef PUT32F_LABELS
+#undef GET32_LABELS
+       void *get32 = get32_labels[get32idx];
+       void *put32float = put32float_labels[put32floatidx];
+       unsigned int channel;
+       for (channel = 0; channel < channels; ++channel) {
+               const char *src;
+               char *dst;
+               int src_step, dst_step;
+               snd_pcm_uframes_t frames1;
+               int32_t sample = 0;
+               float tmp_float;
+               double tmp_double;
+               const snd_pcm_channel_area_t *src_area = &src_areas[channel];
+               const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
+               src = snd_pcm_channel_area_addr(src_area, src_offset);
+               dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
+               src_step = snd_pcm_channel_area_step(src_area);
+               dst_step = snd_pcm_channel_area_step(dst_area);
+               frames1 = frames;
+               while (frames1-- > 0) {
+                       goto *get32;
+#define GET32_END sample_loaded
+#include "plugin_ops.h"
+#undef GET32_END
+               sample_loaded:
+                       goto *put32float;
+#define PUT32F_END sample_put
+#include "plugin_ops.h"
+#undef PUT32F_END
+               sample_put:
+                       src += src_step;
+                       dst += dst_step;
+               }
+       }
 }
 
-void snd_pcm_lfloat_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
-                           const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
-                           unsigned int channels, snd_pcm_uframes_t frames,
-                           unsigned int convidx)
+void snd_pcm_lfloat_convert_float_integer(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
+                                         const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
+                                         unsigned int channels, snd_pcm_uframes_t frames,
+                                         unsigned int put32idx, unsigned int get32floatidx)
 {
-#define CONV_LABELS
+#define PUT32_LABELS
+#define GET32F_LABELS
 #include "plugin_ops.h"
-#undef CONV_LABELS
-       void *conv = conv_labels[convidx];
+#undef GET32F_LABELS
+#undef PUT32_LABELS
+       void *put32 = put32_labels[put32idx];
+       void *get32float = get32float_labels[get32floatidx];
        unsigned int channel;
        for (channel = 0; channel < channels; ++channel) {
                const char *src;
                char *dst;
                int src_step, dst_step;
                snd_pcm_uframes_t frames1;
+               int32_t sample;
+               int64_t sample64;
+               float tmp_float;
+               double tmp_double;
                const snd_pcm_channel_area_t *src_area = &src_areas[channel];
                const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
                src = snd_pcm_channel_area_addr(src_area, src_offset);
@@ -116,11 +147,16 @@ void snd_pcm_lfloat_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_ufr
                dst_step = snd_pcm_channel_area_step(dst_area);
                frames1 = frames;
                while (frames1-- > 0) {
-                       goto *conv;
-#define CONV_END after
+                       goto *get32float;
+#define GET32F_END sample_loaded
+#include "plugin_ops.h"
+#undef GET32F_END
+               sample_loaded:
+                       goto *put32;
+#define PUT32_END sample_put
 #include "plugin_ops.h"
-#undef CONV_END
-               after:
+#undef PUT32_END
+               sample_put:
                        src += src_step;
                        dst += dst_step;
                }
@@ -211,6 +247,8 @@ static int snd_pcm_lfloat_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 static int snd_pcm_lfloat_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 {
        snd_pcm_lfloat_t *lfloat = pcm->private_data;
+       snd_pcm_t *slave = lfloat->plug.slave;
+       snd_pcm_format_t src_format, dst_format;
        int err = snd_pcm_hw_params_slave(pcm, params,
                                          snd_pcm_lfloat_hw_refine_cchange,
                                          snd_pcm_lfloat_hw_refine_sprepare,
@@ -218,12 +256,22 @@ static int snd_pcm_lfloat_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
                                          snd_pcm_plugin_hw_params_slave);
        if (err < 0)
                return err;
-       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-               lfloat->conv_idx = snd_pcm_lfloat_convert_index(snd_pcm_hw_params_get_format(params),
-                                                               lfloat->sformat);
-       else
-               lfloat->conv_idx = snd_pcm_lfloat_convert_index(lfloat->sformat,
-                                                               snd_pcm_hw_params_get_format(params));
+       if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
+               src_format = snd_pcm_hw_params_get_format(params);
+               dst_format = slave->format;
+       } else {
+               src_format = slave->format;
+               dst_format = snd_pcm_hw_params_get_format(params);
+       }
+       if (snd_pcm_format_linear(src_format)) {
+               lfloat->int32_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S32);
+               lfloat->float32_idx = snd_pcm_lfloat_put_s32_index(dst_format);
+               lfloat->func = snd_pcm_lfloat_convert_integer_float;
+       } else {
+               lfloat->int32_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S32, dst_format);
+               lfloat->float32_idx = snd_pcm_lfloat_get_s32_index(src_format);
+               lfloat->func = snd_pcm_lfloat_convert_float_integer;
+       }
        return 0;
 }
 
@@ -239,9 +287,10 @@ snd_pcm_lfloat_write_areas(snd_pcm_t *pcm,
        snd_pcm_lfloat_t *lfloat = pcm->private_data;
        if (size > *slave_sizep)
                size = *slave_sizep;
-       snd_pcm_lfloat_convert(slave_areas, slave_offset,
-                              areas, offset, 
-                              pcm->channels, size, lfloat->conv_idx);
+       lfloat->func(slave_areas, slave_offset,
+                    areas, offset, 
+                    pcm->channels, size,
+                    lfloat->int32_idx, lfloat->float32_idx);
        *slave_sizep = size;
        return size;
 }
@@ -258,9 +307,10 @@ snd_pcm_lfloat_read_areas(snd_pcm_t *pcm,
        snd_pcm_lfloat_t *lfloat = pcm->private_data;
        if (size > *slave_sizep)
                size = *slave_sizep;
-       snd_pcm_lfloat_convert(areas, offset, 
-                              slave_areas, slave_offset,
-                              pcm->channels, size, lfloat->conv_idx);
+       lfloat->func(areas, offset, 
+                    slave_areas, slave_offset,
+                    pcm->channels, size,
+                    lfloat->int32_idx, lfloat->float32_idx);
        *slave_sizep = size;
        return size;
 }
@@ -324,7 +374,7 @@ int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
        pcm->hw_ptr = &lfloat->plug.hw_ptr;
        pcm->appl_ptr = &lfloat->plug.appl_ptr;
        *pcmp = pcm;
-
+       
        return 0;
 }
 
index d7b168b..235db64 100644 (file)
@@ -1877,7 +1877,7 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
                        if (!doit)
                                continue;
 #ifdef RULES_DEBUG
-                       snd_output_printf(log, "Rule %d: ", k);
+                       snd_output_printf(log, "Rule %d (%p): ", k, r->func);
                        if (r->var >= 0) {
                                snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
                                snd_pcm_hw_param_dump(params, r->var, log);
@@ -1888,9 +1888,8 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
 #ifdef RULES_DEBUG
                        if (r->var >= 0)
                                snd_pcm_hw_param_dump(params, r->var, log);
-                       snd_output_putc(log, ' ');
                        for (d = 0; r->deps[d] >= 0; d++) {
-                               snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->deps[d]));
+                               snd_output_printf(log, " %s=", snd_pcm_hw_param_name(r->deps[d]));
                                snd_pcm_hw_param_dump(params, r->deps[d], log);
                        }
                        snd_output_putc(log, '\n');
index 2f910c3..0ceb94b 100644 (file)
@@ -100,17 +100,6 @@ static snd_pcm_format_t linear_preferred_formats[] = {
        SND_PCM_FORMAT_U16_LE,
 #endif
 #ifdef SND_LITTLE_ENDIAN
-       SND_PCM_FORMAT_S24_LE,
-       SND_PCM_FORMAT_U24_LE,
-       SND_PCM_FORMAT_S24_BE,
-       SND_PCM_FORMAT_U24_BE,
-#else
-       SND_PCM_FORMAT_S24_BE,
-       SND_PCM_FORMAT_U24_BE,
-       SND_PCM_FORMAT_S24_LE,
-       SND_PCM_FORMAT_U24_LE,
-#endif
-#ifdef SND_LITTLE_ENDIAN
        SND_PCM_FORMAT_S32_LE,
        SND_PCM_FORMAT_U32_LE,
        SND_PCM_FORMAT_S32_BE,
@@ -122,7 +111,29 @@ static snd_pcm_format_t linear_preferred_formats[] = {
        SND_PCM_FORMAT_U32_LE,
 #endif
        SND_PCM_FORMAT_S8,
-       SND_PCM_FORMAT_U8
+       SND_PCM_FORMAT_U8,
+#ifdef SND_LITTLE_ENDIAN
+       SND_PCM_FORMAT_FLOAT_LE,
+       SND_PCM_FORMAT_FLOAT64_LE,
+       SND_PCM_FORMAT_FLOAT_BE,
+       SND_PCM_FORMAT_FLOAT64_BE,
+#else
+       SND_PCM_FORMAT_FLOAT_BE,
+       SND_PCM_FORMAT_FLOAT64_BE,
+       SND_PCM_FORMAT_FLOAT_LE,
+       SND_PCM_FORMAT_FLOAT64_LE,
+#endif
+#ifdef SND_LITTLE_ENDIAN
+       SND_PCM_FORMAT_S24_LE,
+       SND_PCM_FORMAT_U24_LE,
+       SND_PCM_FORMAT_S24_BE,
+       SND_PCM_FORMAT_U24_BE,
+#else
+       SND_PCM_FORMAT_S24_BE,
+       SND_PCM_FORMAT_U24_BE,
+       SND_PCM_FORMAT_S24_LE,
+       SND_PCM_FORMAT_U24_LE,
+#endif
 };
 
 static snd_pcm_format_t nonlinear_preferred_formats[] = {
@@ -131,13 +142,29 @@ static snd_pcm_format_t nonlinear_preferred_formats[] = {
        SND_PCM_FORMAT_IMA_ADPCM,
 };
 
+static snd_pcm_format_t float_preferred_formats[] = {
+#ifdef SND_LITTLE_ENDIAN
+       SND_PCM_FORMAT_FLOAT_LE,
+       SND_PCM_FORMAT_FLOAT64_LE,
+       SND_PCM_FORMAT_FLOAT_BE,
+       SND_PCM_FORMAT_FLOAT64_BE,
+#else
+       SND_PCM_FORMAT_FLOAT_BE,
+       SND_PCM_FORMAT_FLOAT64_BE,
+       SND_PCM_FORMAT_FLOAT_LE,
+       SND_PCM_FORMAT_FLOAT64_LE,
+#endif
+};
+
 static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const snd_pcm_format_mask_t *format_mask)
 {
        int w, u, e, wid, w1, dw;
        snd_pcm_format_mask_t lin = { SND_PCM_FMTBIT_LINEAR };
+       snd_pcm_format_mask_t fl = { SND_PCM_FMTBIT_FLOAT };
        if (snd_pcm_format_mask_test(format_mask, format))
                return format;
-       if (!snd_pcm_format_mask_test(&lin, format)) {
+       if (!snd_pcm_format_mask_test(&lin, format) &&
+           !snd_pcm_format_mask_test(&fl, format)) {
                unsigned int i;
                switch (format) {
                case SND_PCM_FORMAT_MU_LAW:
@@ -155,7 +182,8 @@ static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const
 
        }
        snd_mask_intersect(&lin, format_mask);
-       if (snd_mask_empty(&lin)) {
+       snd_mask_intersect(&fl, format_mask);
+       if (snd_mask_empty(&lin) && snd_mask_empty(&fl)) {
                unsigned int i;
                for (i = 0; i < sizeof(nonlinear_preferred_formats) / sizeof(nonlinear_preferred_formats[0]); ++i) {
                        snd_pcm_format_t f = nonlinear_preferred_formats[i];
@@ -164,9 +192,31 @@ static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const
                }
                return SND_PCM_FORMAT_UNKNOWN;
        }
-       w = snd_pcm_format_width(format);
-       u = snd_pcm_format_unsigned(format);
-       e = snd_pcm_format_big_endian(format);
+       if (snd_pcm_format_float(format)) {
+               if (snd_pcm_format_mask_test(&fl, format)) {
+                       unsigned int i;
+                       for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
+                               snd_pcm_format_t f = float_preferred_formats[i];
+                               if (snd_pcm_format_mask_test(format_mask, f))
+                                       return f;
+                       }
+               }
+               w = 32;
+               u = 0;
+               e = snd_pcm_format_big_endian(format);
+       } else if (snd_mask_empty(&lin)) {
+               unsigned int i;
+               for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
+                       snd_pcm_format_t f = float_preferred_formats[i];
+                       if (snd_pcm_format_mask_test(format_mask, f))
+                               return f;
+               }
+               return SND_PCM_FORMAT_UNKNOWN;
+       } else {
+               w = snd_pcm_format_width(format);
+               u = snd_pcm_format_unsigned(format);
+               e = snd_pcm_format_big_endian(format);
+       }
        w1 = w;
        dw = 8;
        for (wid = 0; wid < 4; ++wid) {
@@ -193,12 +243,6 @@ static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const
        return SND_PCM_FORMAT_UNKNOWN;
 }
 
-#define SND_PCM_FMTBIT_PLUG (SND_PCM_FMTBIT_LINEAR | \
-                            (1 << SND_PCM_FORMAT_MU_LAW) | \
-                            (1 << SND_PCM_FORMAT_A_LAW) | \
-                            (1 << SND_PCM_FORMAT_IMA_ADPCM))
-
-
 static void snd_pcm_plug_clear(snd_pcm_t *pcm)
 {
        snd_pcm_plug_t *plug = pcm->private_data;
@@ -361,10 +405,27 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
                        f = snd_pcm_adpcm_open;
                        break;
                default:
-                       assert(snd_pcm_format_linear(clt->format));
-                       f = snd_pcm_linear_open;
+                       if (snd_pcm_format_float(clt->format)) {
+                               f = snd_pcm_lfloat_open;
+                       } else {
+                               assert(snd_pcm_format_linear(clt->format));
+                               f = snd_pcm_linear_open;
+                       }
                        break;
                }
+       } else if (snd_pcm_format_float(slv->format)) {
+               /* Conversion is done in another plugin */
+               if (clt->format == slv->format &&
+                   clt->rate == slv->rate &&
+                   clt->channels == slv->channels)
+                       return 0;
+               cfmt = clt->format;
+               if (snd_pcm_format_linear(clt->format))
+                       f = snd_pcm_lfloat_open;
+               else {
+                       assert(0);      /* TODO */
+                       return -EINVAL;
+               }
        } else {
                /* No conversion is needed */
                if (clt->format == slv->format &&
@@ -466,12 +527,16 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
 
 static int snd_pcm_plug_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
 {
-       unsigned int rate_min;
+       unsigned int rate_min, channels_max;
 
        /* HACK: to avoid overflow in PARTBIT_RATE code */
        rate_min = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, NULL);
        if (rate_min < 4000)
-               _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_RATE, 4000, 1);
+               _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_RATE, 4000, 0);
+       /* HACK: to avoid overflow in PERIOD_SIZE code */
+       channels_max = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_CHANNELS, NULL);
+       if (channels_max > 10000)
+               _snd_pcm_hw_param_set_max(params, SND_PCM_HW_PARAM_CHANNELS, 10000, 0);
        return 0;
 }
 
@@ -633,6 +698,21 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
                        snd_pcm_format_mask_set(&fmt_mask, format);
                }
 
+               if (snd_pcm_format_mask_empty(&fmt_mask)) {
+                       SNDERR("Unable to find an useable client format");
+                       for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
+                               if (!snd_pcm_format_mask_test(format_mask, format))
+                                       continue;
+                               SNDERR("Format: %s", snd_pcm_format_name(format));
+                       }
+                       for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
+                               if (!snd_pcm_format_mask_test(sformat_mask, format))
+                                       continue;
+                               SNDERR("Slave format: %s", snd_pcm_format_name(format));
+                       }
+                       return -EINVAL;
+               }
+               
                err = _snd_pcm_hw_param_set_mask(params, 
                                                 SND_PCM_HW_PARAM_FORMAT, &fmt_mask);
                if (err < 0)
index 3abe7d3..ba8d52c 100644 (file)
@@ -87,6 +87,7 @@ int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_f
 int snd_pcm_linear_convert_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format);
 int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int close_slave);
 int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);
+int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);
 int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);
 int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);
 int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);
index b7814c7..545c0b4 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-
 #define as_u8(ptr) (*(u_int8_t*)(ptr))
 #define as_u16(ptr) (*(u_int16_t*)(ptr))
 #define as_u32(ptr) (*(u_int32_t*)(ptr))
@@ -28,6 +27,8 @@
 #define as_s16(ptr) (*(int16_t*)(ptr))
 #define as_s32(ptr) (*(int32_t*)(ptr))
 #define as_s64(ptr) (*(int64_t*)(ptr))
+#define as_float(ptr) (*(float_t*)(ptr))
+#define as_double(ptr) (*(double_t*)(ptr))
 
 #define as_u8c(ptr) (*(const u_int8_t*)(ptr))
 #define as_u16c(ptr) (*(const u_int16_t*)(ptr))
@@ -37,6 +38,8 @@
 #define as_s16c(ptr) (*(const int16_t*)(ptr))
 #define as_s32c(ptr) (*(const int32_t*)(ptr))
 #define as_s64c(ptr) (*(const int64_t*)(ptr))
+#define as_floatc(ptr) (*(const float_t*)(ptr))
+#define as_doublec(ptr) (*(const double_t*)(ptr))
 
 #ifdef COPY_LABELS
 static void *copy_labels[4] = {
@@ -333,14 +336,14 @@ get16_1234_C3: sample = bswap_16(as_u32c(src) ^ 0x80); goto GET16_END;
 #ifdef PUT16_LABELS
 /* dst_wid dst_endswap sign_toggle */
 static void *put16_labels[4 * 2 * 2 * 4 * 2] = {
-       &&put16_12_1,    /* 16h ->  8h */
-       &&put16_12_9,    /* 16h ^>  8h */
-       &&put16_12_1,    /* 16h ->  8s */
-       &&put16_12_9,    /* 16h ^>  8s */
-       &&put16_12_12,   /* 16h -> 16h */
-       &&put16_12_92,   /* 16h ^> 16h */
-       &&put16_12_21,   /* 16h -> 16s */
-       &&put16_12_29,   /* 16h ^> 16s */
+       &&put16_12_1,            /* 16h ->  8h */
+       &&put16_12_9,            /* 16h ^>  8h */
+       &&put16_12_1,            /* 16h ->  8s */
+       &&put16_12_9,            /* 16h ^>  8s */
+       &&put16_12_12,           /* 16h -> 16h */
+       &&put16_12_92,           /* 16h ^> 16h */
+       &&put16_12_21,           /* 16h -> 16s */
+       &&put16_12_29,           /* 16h ^> 16s */
        &&put16_12_0120,         /* 16h -> 24h */
        &&put16_12_0920,         /* 16h ^> 24h */
        &&put16_12_0210,         /* 16h -> 24s */
@@ -374,9 +377,9 @@ put16_12_0029: as_u32(dst) = (u_int32_t)bswap_16(sample) ^ 0x80; goto PUT16_END;
 #ifdef GET32_LABELS
 /* src_wid src_endswap sign_toggle */
 static void *get32_labels[4 * 2 * 2] = {
-       &&get32_1_1000,         /*  8h -> 32h */
-       &&get32_1_9000,         /*  8h ^> 32h */
-       &&get32_1_1000,         /*  8s -> 32h */
+       &&get32_1_1000,          /*  8h -> 32h */
+       &&get32_1_9000,          /*  8h ^> 32h */
+       &&get32_1_1000,          /*  8s -> 32h */
        &&get32_1_9000,          /*  8s ^> 32h */
        &&get32_12_1200,         /* 16h -> 32h */
        &&get32_12_9200,         /* 16h ^> 32h */
@@ -415,10 +418,10 @@ get32_1234_C321: sample = bswap_32(as_u32c(src) ^ 0x80); goto GET32_END;
 #ifdef PUT32_LABELS
 /* dst_wid dst_endswap sign_toggle */
 static void *put32_labels[4 * 2 * 2] = {
-       &&put32_1234_1,         /* 32h ->  8h */
-       &&put32_1234_9,         /* 32h ^>  8h */
-       &&put32_1234_1,         /* 32h ->  8s */
-       &&put32_1234_9,         /* 32h ^>  8s */
+       &&put32_1234_1,          /* 32h ->  8h */
+       &&put32_1234_9,          /* 32h ^>  8h */
+       &&put32_1234_1,          /* 32h ->  8s */
+       &&put32_1234_9,          /* 32h ^>  8s */
        &&put32_1234_12,         /* 32h -> 16h */
        &&put32_1234_92,         /* 32h ^> 16h */
        &&put32_1234_21,         /* 32h -> 16s */
@@ -574,6 +577,72 @@ put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END;
 put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
 #endif
 
+#ifdef PUT32F_LABELS
+/* type (0 = float, 1 = float64), endswap */
+static void *put32float_labels[2 * 2] = {
+       &&put32f_1234_1234F,    /* 32h -> (float)h */
+       &&put32f_1234_4321F,    /* 32h -> (float)s */
+       &&put32f_1234_1234D,    /* 32h -> (float64)h */
+       &&put32f_1234_4321D,    /* 32h -> (float64)s */
+};
+#endif
+
+#ifdef PUT32F_END
+put32f_1234_1234F: as_float(dst) = (float_t)((int32_t)sample) / (float_t)0x80000000UL; goto PUT32F_END;
+put32f_1234_4321F: tmp_float = (float_t)((int32_t)sample) / (float_t)0x80000000UL;
+                  as_u32(dst) = bswap_32(as_u32c(&tmp_float)); goto PUT32F_END;
+put32f_1234_1234D: as_double(dst) = (double_t)((int32_t)sample) / (double_t)0x80000000UL; goto PUT32F_END;
+put32f_1234_4321D: tmp_double = (double_t)((int32_t)sample) / (double_t)0x80000000UL;
+                  as_u64(dst) = bswap_64(as_u64c(&tmp_double)); goto PUT32F_END;
+#endif
+
+#ifdef GET32F_LABELS
+/* type (0 = float, 1 = float64), endswap */
+static void *get32float_labels[2 * 2] = {
+       &&get32f_1234F_1234,    /* (float)h -> 32h */
+       &&get32f_4321F_1234,    /* (float)s -> 32h */
+       &&get32f_1234D_1234,    /* (float64)h -> 32h */
+       &&get32f_4321D_1234,    /* (float64)s -> 32h */
+};
+#endif
+
+#ifdef GET32F_END
+get32f_1234F_1234: tmp_float = as_floatc(src);
+                  if (tmp_float >= 1.0)
+                       sample = 0x7fffffff;
+                  else if (tmp_float <= -1.0)
+                       sample = 0x80000000;
+                  else
+                       sample = (int32_t)(tmp_float * (float_t)0x80000000UL);
+                  goto GET32F_END;
+get32f_4321F_1234: sample = bswap_32(as_u32c(src));
+                  tmp_float = as_floatc(&sample);
+                  if (tmp_float >= 1.0)
+                       sample = 0x7fffffff;
+                  else if (tmp_float <= -1.0)
+                       sample = 0x80000000;
+                  else
+                       sample = (int32_t)(tmp_float * (float_t)0x80000000UL);
+                  goto GET32F_END;
+get32f_1234D_1234: tmp_double = as_doublec(src);
+                  if (tmp_double >= 1.0)
+                       sample = 0x7fffffff;
+                  else if (tmp_double <= -1.0)
+                       sample = 0x80000000;
+                  else
+                       sample = (int32_t)(tmp_double * (double_t)0x80000000UL);
+                  goto GET32F_END;
+get32f_4321D_1234: sample64 = bswap_64(as_u64c(src));
+                  tmp_double = as_doublec(&sample);
+                  if (tmp_double >= 1.0)
+                       sample = 0x7fffffff;
+                  else if (tmp_double <= -1.0)
+                       sample = 0x80000000;
+                  else
+                       sample = (int32_t)(tmp_double * (double_t)0x80000000UL);
+                  goto GET32F_END;
+#endif
+
 #ifdef NORMS_LABELS
 static inline void _norms(const void *src, void *dst,
                          int src_wid,
@@ -844,3 +913,14 @@ norms_32_s32s:     _norms(src, dst, 32, 1,  32, 1); goto NORMS_END;
 #undef as_s8
 #undef as_s16
 #undef as_s32
+#undef as_float
+#undef as_double
+
+#undef as_u8c
+#undef as_u16c
+#undef as_u32c
+#undef as_s8c
+#undef as_s16c
+#undef as_s32c
+#undef as_floatc
+#undef as_doublec