gst/audioconvert/: Support for 64-bit float audio in audioconvert (#339837)

Original commit message from CVS:
* gst/audioconvert/audioconvert.c: (float), (double),
(audio_convert_get_func_index):
* gst/audioconvert/gstaudioconvert.c: (set_structure_widths),
(make_lossless_changes):
Support for 64-bit float audio in audioconvert (#339837)
This commit is contained in:
Stefan Kost 2007-02-02 09:48:53 +00:00
parent 6f25185e75
commit 36180a5f3d
3 changed files with 73 additions and 30 deletions

View file

@ -1,3 +1,11 @@
2007-02-02 Stefan Kost <ensonic@users.sf.net>
* gst/audioconvert/audioconvert.c: (float), (double),
(audio_convert_get_func_index):
* gst/audioconvert/gstaudioconvert.c: (set_structure_widths),
(make_lossless_changes):
Support for 64-bit float audio in audioconvert (#339837)
2007-02-01 Tim-Philipp Müller <tim at centricular dot net>
Patch by: Holger Wansing <linux wansing-online de>

View file

@ -28,8 +28,9 @@
#include "gstchannelmix.h"
#include "audioconvert.h"
/* int to float conversion: int2float(i) = 1 / (2^31-1) * i */
/* int to float/double conversion: int2xxx(i) = 1 / (2^31-1) * i */
#define INT2FLOAT(i) (4.6566128752457969e-10 * ((gfloat)i))
#define INT2DOUBLE(i) (4.6566128752457969e-10 * ((gdouble)i))
/* sign bit in the intermediate format */
#define SIGNED (1U<<31)
@ -52,7 +53,7 @@ MAKE_UNPACK_FUNC_NAME (name) (gpointer src, gint32 *dst, \
} \
}
/* special unpack code for float */
/* special unpack code for float/double */
static void
MAKE_UNPACK_FUNC_NAME (float) (gpointer src, gint32 * dst,
gint scale, gint count)
@ -61,6 +62,21 @@ MAKE_UNPACK_FUNC_NAME (float) (gpointer src, gint32 * dst,
gdouble temp;
for (; count; count--) {
/* blow up to 32 bit */
temp = (*p++ * 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)
{
gdouble *p = (gdouble *) src;
gdouble temp;
for (; count; count--) {
/* blow up to 32 bit */
temp = (*p++ * 2147483647.0) + 0.5;
*dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32);
}
@ -109,7 +125,7 @@ MAKE_PACK_FUNC_NAME (name) (gint32 *src, gpointer dst, \
} \
}
/* special float pack function */
/* special pack code for float/double */
static void
MAKE_PACK_FUNC_NAME (float) (gint32 * src, gpointer dst, gint scale, gint count)
{
@ -120,6 +136,17 @@ MAKE_PACK_FUNC_NAME (float) (gint32 * src, gpointer dst, gint scale, gint count)
}
}
static void
MAKE_PACK_FUNC_NAME (double) (gint32 * src, gpointer dst, gint scale,
gint count)
{
gdouble *p = (gdouble *) dst;
for (; count; count--) {
*p++ = INT2DOUBLE (*src++);
}
}
#define WRITE8(p, v) GST_WRITE_UINT8 (p, v)
#define WRITE16_TO_LE(p,v) GST_WRITE_UINT16_LE (p, (guint16)(v))
#define WRITE16_TO_BE(p,v) GST_WRITE_UINT16_BE (p, (guint16)(v))
@ -161,6 +188,7 @@ static AudioConvertUnpack unpack_funcs[] = {
MAKE_UNPACK_FUNC_NAME (u32_be),
MAKE_UNPACK_FUNC_NAME (s32_be),
MAKE_UNPACK_FUNC_NAME (float),
MAKE_UNPACK_FUNC_NAME (double),
};
static AudioConvertPack pack_funcs[] = {
@ -181,6 +209,7 @@ static AudioConvertPack pack_funcs[] = {
MAKE_PACK_FUNC_NAME (u32_be),
MAKE_PACK_FUNC_NAME (s32_be),
MAKE_PACK_FUNC_NAME (float),
MAKE_PACK_FUNC_NAME (double),
};
static gint
@ -193,7 +222,8 @@ audio_convert_get_func_index (AudioConvertFmt * fmt)
index += fmt->endianness == G_LITTLE_ENDIAN ? 0 : 2;
index += fmt->sign ? 1 : 0;
} else {
index = 16;
/* this is float/double */
index = (fmt->width == 32) ? 16 : 17;
}
return index;
}

View file

@ -120,6 +120,11 @@ GST_BOILERPLATE_FULL (GstAudioConvert, gst_audio_convert, GstBaseTransform,
#define STATIC_CAPS \
GST_STATIC_CAPS ( \
"audio/x-raw-float, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 8 ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 64;" \
"audio/x-raw-float, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 8 ], " \
@ -316,6 +321,30 @@ parse_error:
}
}
/* Set widths (a list); multiples of 8 between min and max */
static void
set_structure_widths (GstStructure * s, int min, int max)
{
GValue list = { 0 };
GValue val = { 0 };
int width;
if (min == max) {
gst_structure_set (s, "width", G_TYPE_INT, min, NULL);
return;
}
g_value_init (&list, GST_TYPE_LIST);
g_value_init (&val, G_TYPE_INT);
for (width = min; width <= max; width += 8) {
g_value_set_int (&val, width);
gst_value_list_append_value (&list, &val);
}
gst_structure_set_value (s, "width", &list);
g_value_unset (&val);
g_value_unset (&list);
}
/* Modify the structure so that things that must always have a single
* value (for float), or can always be losslessly converted (for int), have
* appropriate values.
@ -325,10 +354,10 @@ make_lossless_changes (GstStructure * s, gboolean isfloat)
{
if (isfloat) {
/* float doesn't have a depth or signedness field and only supports a
* width of 32 and native endianness */
* widths of 32/64 and native endianness */
gst_structure_remove_field (s, "depth");
gst_structure_remove_field (s, "signed");
gst_structure_set (s, "width", G_TYPE_INT, 32, NULL);
set_structure_widths (s, 32, 64);
gst_structure_set (s, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
} else {
/* int supports either endian, and signed or unsigned. GValues are a pain */
@ -381,30 +410,6 @@ append_with_other_format (GstCaps * caps, GstStructure * s, gboolean isfloat)
}
}
/* Set widths (a list); multiples of 8 between min and max */
static void
set_structure_widths (GstStructure * s, int min, int max)
{
GValue list = { 0 };
GValue val = { 0 };
int width;
if (min == max) {
gst_structure_set (s, "width", G_TYPE_INT, min, NULL);
return;
}
g_value_init (&list, GST_TYPE_LIST);
g_value_init (&val, G_TYPE_INT);
for (width = min; width <= max; width += 8) {
g_value_set_int (&val, width);
gst_value_list_append_value (&list, &val);
}
gst_structure_set_value (s, "width", &list);
g_value_unset (&val);
g_value_unset (&list);
}
/* Audioconvert can perform all conversions on audio except for resampling.
* However, there are some conversions we _prefer_ not to do. For example, it's
* better to convert format (float<->int, endianness, etc) than the number of