mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-04 22:48:54 +00:00
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:
parent
841750c80a
commit
00d7c52de8
6 changed files with 180 additions and 74 deletions
13
ChangeLog
13
ChangeLog
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue