mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-04 13:30:08 -05:00
Finished lfloat plugin.
Added code to plug plugin to handle linear float / integer conversions.
This commit is contained in:
parent
4efc53523a
commit
095cbbb467
6 changed files with 339 additions and 119 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,65 @@ 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;
|
||||
} snd_pcm_lfloat_t;
|
||||
|
||||
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,
|
||||
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 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"
|
||||
#undef CONV_LABELS
|
||||
void *conv = conv_labels[convidx];
|
||||
#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);
|
||||
|
|
@ -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);
|
||||
frames1 = frames;
|
||||
while (frames1-- > 0) {
|
||||
goto *conv;
|
||||
#define CONV_END after
|
||||
goto *get32;
|
||||
#define GET32_END sample_loaded
|
||||
#include "plugin_ops.h"
|
||||
#undef CONV_END
|
||||
after:
|
||||
#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_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;
|
||||
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,
|
||||
lfloat->func(slave_areas, slave_offset,
|
||||
areas, offset,
|
||||
pcm->channels, size, lfloat->conv_idx);
|
||||
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,
|
||||
lfloat->func(areas, offset,
|
||||
slave_areas, slave_offset,
|
||||
pcm->channels, size, lfloat->conv_idx);
|
||||
pcm->channels, size,
|
||||
lfloat->int32_idx, lfloat->float32_idx);
|
||||
*slave_sizep = size;
|
||||
return size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,7 +1888,6 @@ 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_pcm_hw_param_dump(params, r->deps[d], log);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
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:
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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] = {
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue