From 095cbbb467f9d2f2fd27b0e7d60eb62ca6bea288 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 27 Nov 2001 14:24:44 +0000 Subject: [PATCH] Finished lfloat plugin. Added code to plug plugin to handle linear float / integer conversions. --- src/pcm/pcm_ladspa.c | 10 +++ src/pcm/pcm_lfloat.c | 190 +++++++++++++++++++++++++++---------------- src/pcm/pcm_params.c | 5 +- src/pcm/pcm_plug.c | 134 ++++++++++++++++++++++++------ src/pcm/pcm_plugin.h | 1 + src/pcm/plugin_ops.h | 112 +++++++++++++++++++++---- 6 files changed, 336 insertions(+), 116 deletions(-) diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c index 0cfc34da..75e6802a 100644 --- a/src/pcm/pcm_ladspa.c +++ b/src/pcm/pcm_ladspa.c @@ -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; } diff --git a/src/pcm/pcm_lfloat.c b/src/pcm/pcm_lfloat.c index b2ecadec..dfecb396 100644 --- a/src/pcm/pcm_lfloat.c +++ b/src/pcm/pcm_lfloat.c @@ -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; } diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c index d7b168b6..235db645 100644 --- a/src/pcm/pcm_params.c +++ b/src/pcm/pcm_params.c @@ -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'); diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 2f910c38..0ceb94b2 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -99,17 +99,6 @@ static snd_pcm_format_t linear_preferred_formats[] = { SND_PCM_FORMAT_S16_LE, 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, @@ -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) diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h index 3abe7d34..ba8d52c7 100644 --- a/src/pcm/pcm_plugin.h +++ b/src/pcm/pcm_plugin.h @@ -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); diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h index b7814c76..545c0b4f 100644 --- a/src/pcm/plugin_ops.h +++ b/src/pcm/plugin_ops.h @@ -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 -- 2.47.1