Commit 00d7c52d authored by Stefan Kost's avatar Stefan Kost
Browse files

Add float as an intermediate format, as well as float mixing. Enable test that...

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
parent 841750c8
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):
......@@ -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;
}
......
......@@ -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);
......
......@@ -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);
}
}
......@@ -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__ */
......@@ -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
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment