Add float as an intermediate format, as well as float mixing. Enable test that was failing before. Fixes #339837

Original commit message from CVS:
* gst/audioconvert/audioconvert.c: (float), (double), (float_hq),
(double_hq), (audio_convert_get_func_index),
(audio_convert_prepare_context), (audio_convert_convert):
* gst/audioconvert/audioconvert.h:
* gst/audioconvert/gstchannelmix.c: (gst_channel_mix_setup_matrix),
(gst_channel_mix_mix_int), (gst_channel_mix_mix_float):
* gst/audioconvert/gstchannelmix.h:
* tests/check/elements/audioconvert.c: (GST_START_TEST):
Add float as an intermediate format, as well as float mixing. Enable
test that was failing before. Fixes #339837
This commit is contained in:
Stefan Kost 2007-02-22 09:04:37 +00:00
parent 841750c80a
commit 00d7c52de8
6 changed files with 180 additions and 74 deletions

View file

@ -1,3 +1,16 @@
2007-02-22 Stefan Kost <ensonic@users.sf.net>
* gst/audioconvert/audioconvert.c: (float), (double), (float_hq),
(double_hq), (audio_convert_get_func_index),
(audio_convert_prepare_context), (audio_convert_convert):
* gst/audioconvert/audioconvert.h:
* gst/audioconvert/gstchannelmix.c: (gst_channel_mix_setup_matrix),
(gst_channel_mix_mix_int), (gst_channel_mix_mix_float):
* gst/audioconvert/gstchannelmix.h:
* tests/check/elements/audioconvert.c: (GST_START_TEST):
Add float as an intermediate format, as well as float mixing. Enable
test that was failing before. Fixes #339837
2007-02-21 Jan Schmidt <thaytan@mad.scientist.com>
* tests/examples/seek/seek.c: (do_seek):

View file

@ -55,33 +55,46 @@ MAKE_UNPACK_FUNC_NAME (name) (gpointer src, gint32 *dst, \
/* special unpack code for float/double */
static void
MAKE_UNPACK_FUNC_NAME (float) (gpointer src, gint32 * dst,
gint scale, gint count)
MAKE_UNPACK_FUNC_NAME (float) (gfloat * src, gint32 * dst, gint s, gint count)
{
gfloat *p = (gfloat *) src;
gdouble temp;
for (; count; count--) {
/* blow up to 32 bit */
temp = (*p++ * 2147483647.0) + 0.5;
temp = (*src++ * 2147483647.0) + 0.5;
*dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32);
}
}
static void
MAKE_UNPACK_FUNC_NAME (double) (gpointer src, gint32 * dst,
gint scale, gint count)
MAKE_UNPACK_FUNC_NAME (double) (gdouble * src, gint32 * dst, gint s, gint count)
{
gdouble *p = (gdouble *) src;
gdouble temp;
for (; count; count--) {
/* blow up to 32 bit */
temp = (*p++ * 2147483647.0) + 0.5;
temp = (*src++ * 2147483647.0) + 0.5;
*dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32);
}
}
static void
MAKE_UNPACK_FUNC_NAME (float_hq) (gfloat * src, gdouble * dst, gint s,
gint count)
{
for (; count; count--)
*dst++ = (gdouble) * src++;
}
static void
MAKE_UNPACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s,
gint count)
{
/* FIXME: memcpy */
for (; count; count--)
*dst++ = *src++;
}
#define READ8(p) GST_READ_UINT8(p)
#define READ16_FROM_LE(p) GST_READ_UINT16_LE (p)
#define READ16_FROM_BE(p) GST_READ_UINT16_BE (p)
@ -127,24 +140,34 @@ MAKE_PACK_FUNC_NAME (name) (gint32 *src, gpointer dst, \
/* special pack code for float/double */
static void
MAKE_PACK_FUNC_NAME (float) (gint32 * src, gpointer dst, gint scale, gint count)
MAKE_PACK_FUNC_NAME (float) (gint32 * src, gfloat * dst, gint scale, gint count)
{
gfloat *p = (gfloat *) dst;
for (; count; count--) {
*p++ = INT2FLOAT (*src++);
}
for (; count; count--)
*dst++ = INT2FLOAT (*src++);
}
static void
MAKE_PACK_FUNC_NAME (double) (gint32 * src, gpointer dst, gint scale,
MAKE_PACK_FUNC_NAME (double) (gint32 * src, gdouble * dst, gint scale,
gint count)
{
gdouble *p = (gdouble *) dst;
for (; count; count--)
*dst++ = INT2DOUBLE (*src++);
}
for (; count; count--) {
*p++ = INT2DOUBLE (*src++);
}
static void
MAKE_PACK_FUNC_NAME (float_hq) (gdouble * src, gfloat * dst, gint s, gint count)
{
for (; count; count--)
*dst++ = (gfloat) (*src++);
}
static void
MAKE_PACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s,
gint count)
{
/* FIXME: memcpy */
for (; count; count--)
*dst++ = *src++;
}
#define WRITE8(p, v) GST_WRITE_UINT8 (p, v)
@ -171,45 +194,49 @@ MAKE_PACK_FUNC (u32_be, 4, SIGNED, WRITE32_TO_BE);
MAKE_PACK_FUNC (s32_be, 4, 0, WRITE32_TO_BE);
static AudioConvertUnpack unpack_funcs[] = {
MAKE_UNPACK_FUNC_NAME (u8),
MAKE_UNPACK_FUNC_NAME (s8),
MAKE_UNPACK_FUNC_NAME (u8),
MAKE_UNPACK_FUNC_NAME (s8),
MAKE_UNPACK_FUNC_NAME (u16_le),
MAKE_UNPACK_FUNC_NAME (s16_le),
MAKE_UNPACK_FUNC_NAME (u16_be),
MAKE_UNPACK_FUNC_NAME (s16_be),
MAKE_UNPACK_FUNC_NAME (u24_le),
MAKE_UNPACK_FUNC_NAME (s24_le),
MAKE_UNPACK_FUNC_NAME (u24_be),
MAKE_UNPACK_FUNC_NAME (s24_be),
MAKE_UNPACK_FUNC_NAME (u32_le),
MAKE_UNPACK_FUNC_NAME (s32_le),
MAKE_UNPACK_FUNC_NAME (u32_be),
MAKE_UNPACK_FUNC_NAME (s32_be),
MAKE_UNPACK_FUNC_NAME (float),
MAKE_UNPACK_FUNC_NAME (double),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq),
(AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq),
};
static AudioConvertPack pack_funcs[] = {
MAKE_PACK_FUNC_NAME (u8),
MAKE_PACK_FUNC_NAME (s8),
MAKE_PACK_FUNC_NAME (u8),
MAKE_PACK_FUNC_NAME (s8),
MAKE_PACK_FUNC_NAME (u16_le),
MAKE_PACK_FUNC_NAME (s16_le),
MAKE_PACK_FUNC_NAME (u16_be),
MAKE_PACK_FUNC_NAME (s16_be),
MAKE_PACK_FUNC_NAME (u24_le),
MAKE_PACK_FUNC_NAME (s24_le),
MAKE_PACK_FUNC_NAME (u24_be),
MAKE_PACK_FUNC_NAME (s24_be),
MAKE_PACK_FUNC_NAME (u32_le),
MAKE_PACK_FUNC_NAME (s32_le),
MAKE_PACK_FUNC_NAME (u32_be),
MAKE_PACK_FUNC_NAME (s32_be),
MAKE_PACK_FUNC_NAME (float),
MAKE_PACK_FUNC_NAME (double),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u8),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s8),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u8),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s8),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (float),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (double),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq),
(AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq),
};
static gint
@ -251,7 +278,7 @@ gboolean
audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
AudioConvertFmt * out)
{
gint idx;
gint idx_in, idx_out;
g_return_val_if_fail (ctx != NULL, FALSE);
g_return_val_if_fail (in != NULL, FALSE);
@ -265,14 +292,28 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
gst_channel_mix_setup_matrix (ctx);
idx = audio_convert_get_func_index (in);
if (!(ctx->unpack = unpack_funcs[idx]))
idx_in = audio_convert_get_func_index (in);
if (!(ctx->unpack = unpack_funcs[idx_in]))
goto not_supported;
idx = audio_convert_get_func_index (out);
if (!(ctx->pack = pack_funcs[idx]))
idx_out = audio_convert_get_func_index (out);
if (!(ctx->pack = pack_funcs[idx_out]))
goto not_supported;
/* if both formats are float/double use double as intermediate format and
* and switch mixing */
if (in->is_int || out->is_int) {
GST_DEBUG ("use int mixing");
ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int;
} else {
GST_DEBUG ("use float mixing");
ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float;
if (!(ctx->unpack = unpack_funcs[idx_in + 2]))
goto not_supported;
if (!(ctx->pack = pack_funcs[idx_out + 2]))
goto not_supported;
}
/* check if input is in default format */
ctx->in_default = check_default (in);
/* check if channel mixer is passthrough */
@ -287,6 +328,7 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
not_supported:
{
GST_INFO ("missing pack/unpack function");
return FALSE;
}
}
@ -325,7 +367,7 @@ gboolean
audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
gpointer dst, gint samples, gboolean src_writable)
{
gint insize, outsize;
gint insize, outsize, size;
gpointer outbuf, tmpbuf;
gint biggest = 0;
@ -341,10 +383,11 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
outsize = ctx->out.unit_size * samples;
/* find biggest temp buffer size */
size = (ctx->in.is_int || ctx->out.is_int) ? 32 : 64;
if (!ctx->in_default)
biggest = insize * 32 / ctx->in.width;
biggest = insize * size / ctx->in.width;
if (!ctx->mix_passthrough)
biggest = MAX (biggest, outsize * 32 / ctx->out.width);
biggest = MAX (biggest, outsize * size / ctx->out.width);
/* see if one of the buffers can be used as temp */
if (outsize >= biggest)
@ -381,7 +424,7 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
outbuf = dst;
/* convert channels */
gst_channel_mix_mix (ctx, src, outbuf, samples);
ctx->channel_mix (ctx, src, outbuf, samples);
src = outbuf;
}

View file

@ -45,8 +45,10 @@ struct _AudioConvertFmt
gint unit_size;
};
typedef void (*AudioConvertUnpack) (gpointer src, gint32 *dst, gint scale, gint count);
typedef void (*AudioConvertPack) (gint32 *src, gpointer dst, gint scale, gint count);
typedef void (*AudioConvertUnpack) (gpointer src, gpointer dst, gint scale, gint count);
typedef void (*AudioConvertPack) (gpointer src, gpointer dst, gint scale, gint count);
typedef void (*AudioConvertMix) (AudioConvertCtx *, gpointer, gpointer, gint);
struct _AudioConvertCtx
{
@ -60,7 +62,7 @@ struct _AudioConvertCtx
* If identity matrix, passthrough applies. */
gfloat **matrix;
/* temp storage for channelmix */
gint32 *tmp;
gpointer tmp;
gboolean in_default;
gboolean mix_passthrough;
@ -71,6 +73,8 @@ struct _AudioConvertCtx
gint in_scale;
gint out_scale;
AudioConvertMix channel_mix;
};
gboolean audio_convert_clean_fmt (AudioConvertFmt *fmt);

View file

@ -480,7 +480,11 @@ gst_channel_mix_setup_matrix (AudioConvertCtx * this)
gst_channel_mix_unset_matrix (this);
/* temp storage */
this->tmp = g_new (gint32, this->out.channels);
if (this->in.is_int || this->out.is_int) {
this->tmp = (gpointer) g_new (gint32, this->out.channels);
} else {
this->tmp = (gpointer) g_new (gdouble, this->out.channels);
}
/* allocate */
this->matrix = g_new0 (gfloat *, this->in.channels);
@ -534,13 +538,14 @@ gst_channel_mix_passthrough (AudioConvertCtx * this)
/* IMPORTANT: out_data == in_data is possible, make sure to not overwrite data
* you might need later on! */
void
gst_channel_mix_mix (AudioConvertCtx * this,
gst_channel_mix_mix_int (AudioConvertCtx * this,
gint32 * in_data, gint32 * out_data, gint samples)
{
gint in, out, n;
gint64 res;
gboolean backwards;
gint inchannels, outchannels;
gint32 *tmp = (gint32 *) this->tmp;
g_return_if_fail (this->matrix != NULL);
g_return_if_fail (this->tmp != NULL);
@ -564,9 +569,48 @@ gst_channel_mix_mix (AudioConvertCtx * this,
res = G_MININT32;
else if (res > G_MAXINT32)
res = G_MAXINT32;
this->tmp[out] = res;
tmp[out] = res;
}
memcpy (&out_data[n * outchannels], this->tmp,
sizeof (gint32) * outchannels);
}
}
void
gst_channel_mix_mix_float (AudioConvertCtx * this,
gdouble * in_data, gdouble * out_data, gint samples)
{
gint in, out, n;
gdouble res;
gboolean backwards;
gint inchannels, outchannels;
gdouble *tmp = (gdouble *) this->tmp;
g_return_if_fail (this->matrix != NULL);
g_return_if_fail (this->tmp != NULL);
inchannels = this->in.channels;
outchannels = this->out.channels;
backwards = outchannels > inchannels;
/* FIXME: use liboil here? */
for (n = (backwards ? samples - 1 : 0); n < samples && n >= 0;
backwards ? n-- : n++) {
for (out = 0; out < outchannels; out++) {
/* convert */
res = 0.0;
for (in = 0; in < inchannels; in++) {
res += in_data[n * inchannels + in] * this->matrix[in][out];
}
/* clip (shouldn't we use doubles instead as intermediate format?) */
if (res < -1.0)
res = -1.0;
else if (res > 1.0)
res = 1.0;
tmp[out] = res;
}
memcpy (&out_data[n * outchannels], this->tmp,
sizeof (gdouble) * outchannels);
}
}

View file

@ -46,9 +46,14 @@ gboolean gst_channel_mix_passthrough (AudioConvertCtx * this);
/*
* Do actual mixing.
*/
void gst_channel_mix_mix (AudioConvertCtx * this,
void gst_channel_mix_mix_int (AudioConvertCtx * this,
gint32 * in_data,
gint32 * out_data,
gint samples);
void gst_channel_mix_mix_float (AudioConvertCtx * this,
gdouble * in_data,
gdouble * out_data,
gint samples);
#endif /* __GST_CHANNEL_MIX_H__ */

View file

@ -473,12 +473,9 @@ GST_START_TEST (test_float_conversion)
in, get_float_caps (1, "BYTE_ORDER", 64),
out, get_float_caps (1, "BYTE_ORDER", 32));
/* FIXME: this fails */
#if 0
RUN_CONVERSION ("32 float to 64 float",
out, get_float_caps (1, "BYTE_ORDER", 32),
in, get_float_caps (1, "BYTE_ORDER", 64));
#endif
}
}