Finished lfloat plugin.

Added code to plug plugin to handle linear float / integer conversions.
This commit is contained in:
Jaroslav Kysela 2001-11-27 14:24:44 +00:00
parent 4efc53523a
commit 095cbbb467
6 changed files with 339 additions and 119 deletions

View file

@ -194,6 +194,11 @@ snd_pcm_ladspa_write_areas(snd_pcm_t *pcm,
// snd_pcm_ladspa_t *ladspa = pcm->private_data; // snd_pcm_ladspa_t *ladspa = pcm->private_data;
if (size > *slave_sizep) if (size > *slave_sizep)
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; *slave_sizep = size;
return size; return size;
} }
@ -210,6 +215,11 @@ snd_pcm_ladspa_read_areas(snd_pcm_t *pcm,
// snd_pcm_ladspa_t *ladspa = pcm->private_data; // snd_pcm_ladspa_t *ladspa = pcm->private_data;
if (size > *slave_sizep) if (size > *slave_sizep)
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; *slave_sizep = size;
return size; return size;
} }

View file

@ -23,6 +23,9 @@
#include "pcm_local.h" #include "pcm_local.h"
#include "pcm_plugin.h" #include "pcm_plugin.h"
typedef float float_t;
typedef double double_t;
#ifndef PIC #ifndef PIC
/* entry for static linking */ /* entry for static linking */
const char *_snd_module_pcm_float = ""; const char *_snd_module_pcm_float = "";
@ -31,83 +34,65 @@ const char *_snd_module_pcm_float = "";
typedef struct { typedef struct {
/* This field need to be the first */ /* This field need to be the first */
snd_pcm_plugin_t plug; snd_pcm_plugin_t plug;
unsigned int conv_idx; unsigned int int32_idx;
unsigned int float32_idx;
snd_pcm_format_t sformat; snd_pcm_format_t sformat;
} snd_pcm_lfloat_t; void (*func)(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
int snd_pcm_lfloat_convert_index(snd_pcm_format_t src_format,
snd_pcm_format_t dst_format)
{
int src_endian, dst_endian, sign, src_width, dst_width;
sign = (snd_pcm_format_signed(src_format) !=
snd_pcm_format_signed(dst_format));
#ifdef SND_LITTLE_ENDIAN
src_endian = snd_pcm_format_big_endian(src_format);
dst_endian = snd_pcm_format_big_endian(dst_format);
#else
src_endian = snd_pcm_format_little_endian(src_format);
dst_endian = snd_pcm_format_little_endian(dst_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;
}
int snd_pcm_lfloat_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_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;
}
int snd_pcm_lfloat_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
{
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;
}
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, const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
unsigned int channels, snd_pcm_uframes_t frames, unsigned int channels, snd_pcm_uframes_t frames,
unsigned int convidx) unsigned int get32idx, unsigned int put32floatidx);
} snd_pcm_lfloat_t;
int snd_pcm_lfloat_get_s32_index(snd_pcm_format_t format)
{ {
#define CONV_LABELS int width, endian;
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
endian = snd_pcm_format_big_endian(format);
#else
endian = snd_pcm_format_little_endian(format);
#endif
return ((width / 32)-1) * 2 + endian;
}
int snd_pcm_lfloat_put_s32_index(snd_pcm_format_t format)
{
return snd_pcm_lfloat_get_s32_index(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)
{
#define GET32_LABELS
#define PUT32F_LABELS
#include "plugin_ops.h" #include "plugin_ops.h"
#undef CONV_LABELS #undef PUT32F_LABELS
void *conv = conv_labels[convidx]; #undef GET32_LABELS
void *get32 = get32_labels[get32idx];
void *put32float = put32float_labels[put32floatidx];
unsigned int channel; unsigned int channel;
for (channel = 0; channel < channels; ++channel) { for (channel = 0; channel < channels; ++channel) {
const char *src; const char *src;
char *dst; char *dst;
int src_step, dst_step; int src_step, dst_step;
snd_pcm_uframes_t frames1; 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 *src_area = &src_areas[channel];
const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
src = snd_pcm_channel_area_addr(src_area, src_offset); src = snd_pcm_channel_area_addr(src_area, src_offset);
@ -116,11 +101,62 @@ 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); dst_step = snd_pcm_channel_area_step(dst_area);
frames1 = frames; frames1 = frames;
while (frames1-- > 0) { while (frames1-- > 0) {
goto *conv; goto *get32;
#define CONV_END after #define GET32_END sample_loaded
#include "plugin_ops.h" #include "plugin_ops.h"
#undef CONV_END #undef GET32_END
after: 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_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 PUT32_LABELS
#define GET32F_LABELS
#include "plugin_ops.h"
#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);
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 *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 PUT32_END
sample_put:
src += src_step; src += src_step;
dst += dst_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) 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_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, int err = snd_pcm_hw_params_slave(pcm, params,
snd_pcm_lfloat_hw_refine_cchange, snd_pcm_lfloat_hw_refine_cchange,
snd_pcm_lfloat_hw_refine_sprepare, 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); snd_pcm_plugin_hw_params_slave);
if (err < 0) if (err < 0)
return err; return err;
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
lfloat->conv_idx = snd_pcm_lfloat_convert_index(snd_pcm_hw_params_get_format(params), src_format = snd_pcm_hw_params_get_format(params);
lfloat->sformat); dst_format = slave->format;
else } else {
lfloat->conv_idx = snd_pcm_lfloat_convert_index(lfloat->sformat, src_format = slave->format;
snd_pcm_hw_params_get_format(params)); 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; return 0;
} }
@ -239,9 +287,10 @@ snd_pcm_lfloat_write_areas(snd_pcm_t *pcm,
snd_pcm_lfloat_t *lfloat = pcm->private_data; snd_pcm_lfloat_t *lfloat = pcm->private_data;
if (size > *slave_sizep) if (size > *slave_sizep)
size = *slave_sizep; size = *slave_sizep;
snd_pcm_lfloat_convert(slave_areas, slave_offset, lfloat->func(slave_areas, slave_offset,
areas, offset, areas, offset,
pcm->channels, size, lfloat->conv_idx); pcm->channels, size,
lfloat->int32_idx, lfloat->float32_idx);
*slave_sizep = size; *slave_sizep = size;
return size; return size;
} }
@ -258,9 +307,10 @@ snd_pcm_lfloat_read_areas(snd_pcm_t *pcm,
snd_pcm_lfloat_t *lfloat = pcm->private_data; snd_pcm_lfloat_t *lfloat = pcm->private_data;
if (size > *slave_sizep) if (size > *slave_sizep)
size = *slave_sizep; size = *slave_sizep;
snd_pcm_lfloat_convert(areas, offset, lfloat->func(areas, offset,
slave_areas, slave_offset, slave_areas, slave_offset,
pcm->channels, size, lfloat->conv_idx); pcm->channels, size,
lfloat->int32_idx, lfloat->float32_idx);
*slave_sizep = size; *slave_sizep = size;
return size; return size;
} }

View file

@ -1877,7 +1877,7 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
if (!doit) if (!doit)
continue; continue;
#ifdef RULES_DEBUG #ifdef RULES_DEBUG
snd_output_printf(log, "Rule %d: ", k); snd_output_printf(log, "Rule %d (%p): ", k, r->func);
if (r->var >= 0) { if (r->var >= 0) {
snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var)); snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
snd_pcm_hw_param_dump(params, r->var, log); snd_pcm_hw_param_dump(params, r->var, log);
@ -1888,7 +1888,6 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
#ifdef RULES_DEBUG #ifdef RULES_DEBUG
if (r->var >= 0) if (r->var >= 0)
snd_pcm_hw_param_dump(params, r->var, log); snd_pcm_hw_param_dump(params, r->var, log);
snd_output_putc(log, ' ');
for (d = 0; r->deps[d] >= 0; d++) { 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_pcm_hw_param_dump(params, r->deps[d], log);

View file

@ -99,17 +99,6 @@ static snd_pcm_format_t linear_preferred_formats[] = {
SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_LE,
#endif #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 #ifdef SND_LITTLE_ENDIAN
SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_LE,
SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_LE,
@ -122,7 +111,29 @@ static snd_pcm_format_t linear_preferred_formats[] = {
SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_LE,
#endif #endif
SND_PCM_FORMAT_S8, 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[] = { 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, 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) 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; int w, u, e, wid, w1, dw;
snd_pcm_format_mask_t lin = { SND_PCM_FMTBIT_LINEAR }; 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)) if (snd_pcm_format_mask_test(format_mask, format))
return 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; unsigned int i;
switch (format) { switch (format) {
case SND_PCM_FORMAT_MU_LAW: 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); 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; unsigned int i;
for (i = 0; i < sizeof(nonlinear_preferred_formats) / sizeof(nonlinear_preferred_formats[0]); ++i) { for (i = 0; i < sizeof(nonlinear_preferred_formats) / sizeof(nonlinear_preferred_formats[0]); ++i) {
snd_pcm_format_t f = nonlinear_preferred_formats[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; return SND_PCM_FORMAT_UNKNOWN;
} }
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); w = snd_pcm_format_width(format);
u = snd_pcm_format_unsigned(format); u = snd_pcm_format_unsigned(format);
e = snd_pcm_format_big_endian(format); e = snd_pcm_format_big_endian(format);
}
w1 = w; w1 = w;
dw = 8; dw = 8;
for (wid = 0; wid < 4; ++wid) { 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; 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) static void snd_pcm_plug_clear(snd_pcm_t *pcm)
{ {
snd_pcm_plug_t *plug = pcm->private_data; 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; f = snd_pcm_adpcm_open;
break; break;
default: default:
if (snd_pcm_format_float(clt->format)) {
f = snd_pcm_lfloat_open;
} else {
assert(snd_pcm_format_linear(clt->format)); assert(snd_pcm_format_linear(clt->format));
f = snd_pcm_linear_open; f = snd_pcm_linear_open;
}
break; 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 { } else {
/* No conversion is needed */ /* No conversion is needed */
if (clt->format == slv->format && 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) 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 */ /* HACK: to avoid overflow in PARTBIT_RATE code */
rate_min = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, NULL); rate_min = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, NULL);
if (rate_min < 4000) 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; 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); 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, err = _snd_pcm_hw_param_set_mask(params,
SND_PCM_HW_PARAM_FORMAT, &fmt_mask); SND_PCM_HW_PARAM_FORMAT, &fmt_mask);
if (err < 0) if (err < 0)

View 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_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_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_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_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_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); int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave);

View file

@ -19,7 +19,6 @@
* *
*/ */
#define as_u8(ptr) (*(u_int8_t*)(ptr)) #define as_u8(ptr) (*(u_int8_t*)(ptr))
#define as_u16(ptr) (*(u_int16_t*)(ptr)) #define as_u16(ptr) (*(u_int16_t*)(ptr))
#define as_u32(ptr) (*(u_int32_t*)(ptr)) #define as_u32(ptr) (*(u_int32_t*)(ptr))
@ -28,6 +27,8 @@
#define as_s16(ptr) (*(int16_t*)(ptr)) #define as_s16(ptr) (*(int16_t*)(ptr))
#define as_s32(ptr) (*(int32_t*)(ptr)) #define as_s32(ptr) (*(int32_t*)(ptr))
#define as_s64(ptr) (*(int64_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_u8c(ptr) (*(const u_int8_t*)(ptr))
#define as_u16c(ptr) (*(const u_int16_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_s16c(ptr) (*(const int16_t*)(ptr))
#define as_s32c(ptr) (*(const int32_t*)(ptr)) #define as_s32c(ptr) (*(const int32_t*)(ptr))
#define as_s64c(ptr) (*(const int64_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 #ifdef COPY_LABELS
static void *copy_labels[4] = { static void *copy_labels[4] = {
@ -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; put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
#endif #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 #ifdef NORMS_LABELS
static inline void _norms(const void *src, void *dst, static inline void _norms(const void *src, void *dst,
int src_wid, 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_s8
#undef as_s16 #undef as_s16
#undef as_s32 #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