gst/speexresample/: Add missing headers to Makefile.am.

Original commit message from CVS:
* gst/speexresample/Makefile.am:
* gst/speexresample/gstspeexresample.c:
(gst_speex_resample_base_init), (gst_speex_resample_get_funcs),
(gst_speex_resample_convert_buffer), (_benchmark_int_float),
(_benchmark_int_int), (_benchmark_integer_resampling),
(plugin_init):
* gst/speexresample/gstspeexresample.h:
* gst/speexresample/resample.c:
* gst/speexresample/speex_resampler_double.c:
* gst/speexresample/speex_resampler_float.c:
* gst/speexresample/speex_resampler_int.c:
* gst/speexresample/speex_resampler_wrapper.h:
Add missing headers to Makefile.am.
Update copyright, years and my mail address.
Benchmark the integer resampling implementation against the
float implementation and use the faster one for 8/16 bit integer
input. On most recent systems the floating point version is faster.
This commit is contained in:
Sebastian Dröge 2008-11-01 19:38:36 +00:00
parent 89b5a74b86
commit 859034f462
9 changed files with 232 additions and 24 deletions

View file

@ -1,3 +1,25 @@
2008-11-01 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* gst/speexresample/Makefile.am:
* gst/speexresample/gstspeexresample.c:
(gst_speex_resample_base_init), (gst_speex_resample_get_funcs),
(gst_speex_resample_convert_buffer), (_benchmark_int_float),
(_benchmark_int_int), (_benchmark_integer_resampling),
(plugin_init):
* gst/speexresample/gstspeexresample.h:
* gst/speexresample/resample.c:
* gst/speexresample/speex_resampler_double.c:
* gst/speexresample/speex_resampler_float.c:
* gst/speexresample/speex_resampler_int.c:
* gst/speexresample/speex_resampler_wrapper.h:
Add missing headers to Makefile.am.
Update copyright, years and my mail address.
Benchmark the integer resampling implementation against the
float implementation and use the faster one for 8/16 bit integer
input. On most recent systems the floating point version is faster.
2008-10-31 Sebastian Dröge <sebastian.droege@collabora.co.uk> 2008-10-31 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* configure.ac: * configure.ac:

View file

@ -9,24 +9,29 @@ libgstspeexresample_la_SOURCES = \
libgstspeexresample_la_CFLAGS = \ libgstspeexresample_la_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) $(GST_CFLAGS) \
$(LIBOIL_CFLAGS)
libgstspeexresample_la_LIBADD = \ libgstspeexresample_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \ $(GST_PLUGINS_BASE_LIBS) \
$(GST_BASE_LIBS) \ $(GST_BASE_LIBS) \
$(GST_LIBS) \ $(GST_LIBS) \
-lgstaudio-$(GST_MAJORMINOR) \ -lgstaudio-$(GST_MAJORMINOR) \
$(LIBOIL_LIBS) \
$(LIBM) $(LIBM)
libgstspeexresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstspeexresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = \ noinst_HEADERS = \
arch.h \ arch.h \
fixed_arm4.h \
fixed_arm5e.h \
fixed_bfin.h \
fixed_debug.h \
fixed_generic.h \ fixed_generic.h \
gstspeexresample.h \ gstspeexresample.h \
resample.c \
resample_sse.h \
speex_resampler.h \ speex_resampler.h \
speex_resampler_wrapper.h speex_resampler_wrapper.h
EXTRA_DIST = \
resample.c

View file

@ -1,7 +1,7 @@
/* GStreamer /* GStreamer
* Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu> * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2003,2004 David A. Schleef <ds@schleef.org> * Copyright (C) 2003,2004 David A. Schleef <ds@schleef.org>
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -45,6 +45,10 @@
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
#include <gst/base/gstbasetransform.h> #include <gst/base/gstbasetransform.h>
#define OIL_ENABLE_UNSTABLE_API
#include <liboil/liboilprofile.h>
#include <liboil/liboil.h>
GST_DEBUG_CATEGORY (speex_resample_debug); GST_DEBUG_CATEGORY (speex_resample_debug);
#define GST_CAT_DEFAULT speex_resample_debug #define GST_CAT_DEFAULT speex_resample_debug
@ -91,6 +95,9 @@ GST_STATIC_CAPS ( \
"signed = (boolean) true" \ "signed = (boolean) true" \
) )
/* If TRUE integer arithmetic resampling is faster and will be used if appropiate */
static gboolean gst_speex_resample_use_int = FALSE;
static GstStaticPadTemplate gst_speex_resample_sink_template = static GstStaticPadTemplate gst_speex_resample_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS); GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS);
@ -125,11 +132,8 @@ static gboolean gst_speex_resample_stop (GstBaseTransform * base);
static gboolean gst_speex_resample_query (GstPad * pad, GstQuery * query); static gboolean gst_speex_resample_query (GstPad * pad, GstQuery * query);
static const GstQueryType *gst_speex_resample_query_type (GstPad * pad); static const GstQueryType *gst_speex_resample_query_type (GstPad * pad);
#define DEBUG_INIT(bla) \ GST_BOILERPLATE (GstSpeexResample, gst_speex_resample, GstBaseTransform,
GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0, "audio resampling element"); GST_TYPE_BASE_TRANSFORM);
GST_BOILERPLATE_FULL (GstSpeexResample, gst_speex_resample, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void static void
gst_speex_resample_base_init (gpointer g_class) gst_speex_resample_base_init (gpointer g_class)
@ -143,7 +147,7 @@ gst_speex_resample_base_init (gpointer g_class)
gst_element_class_set_details_simple (gstelement_class, "Audio resampler", gst_element_class_set_details_simple (gstelement_class, "Audio resampler",
"Filter/Converter/Audio", "Resamples audio", "Filter/Converter/Audio", "Resamples audio",
"Sebastian Dröge <slomo@circular-chaos.org>"); "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
} }
static void static void
@ -297,9 +301,10 @@ gst_speex_resample_get_funcs (gint width, gboolean fp)
{ {
const SpeexResampleFuncs *funcs = NULL; const SpeexResampleFuncs *funcs = NULL;
if ((width == 8 || width == 16) && !fp) if (gst_speex_resample_use_int && (width == 8 || width == 16) && !fp)
funcs = &int_funcs; funcs = &int_funcs;
else if (width == 32 && fp) else if ((!gst_speex_resample_use_int && (width == 8 || width == 16) && !fp)
|| (width == 32 && fp))
funcs = &float_funcs; funcs = &float_funcs;
else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp)) else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp))
funcs = &double_funcs; funcs = &double_funcs;
@ -572,7 +577,7 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
len *= resample->channels; len *= resample->channels;
if (inverse) { if (inverse) {
if (resample->width == 8 && !resample->fp) { if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
gint8 *o = (gint8 *) out; gint8 *o = (gint8 *) out;
gint16 *i = (gint16 *) in; gint16 *i = (gint16 *) in;
gint32 tmp; gint32 tmp;
@ -584,6 +589,32 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
i++; i++;
len--; len--;
} }
} else if (!gst_speex_resample_use_int && resample->width == 8
&& !resample->fp) {
gint8 *o = (gint8 *) out;
gfloat *i = (gfloat *) in;
gfloat tmp;
while (len) {
tmp = *i;
*o = (gint8) CLAMP (tmp * G_MAXINT8 + 0.5, G_MININT8, G_MAXINT8);
o++;
i++;
len--;
}
} else if (!gst_speex_resample_use_int && resample->width == 16
&& !resample->fp) {
gint16 *o = (gint16 *) out;
gfloat *i = (gfloat *) in;
gfloat tmp;
while (len) {
tmp = *i;
*o = (gint16) CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
o++;
i++;
len--;
}
} else if (resample->width == 24 && !resample->fp) { } else if (resample->width == 24 && !resample->fp) {
guint8 *o = (guint8 *) out; guint8 *o = (guint8 *) out;
gdouble *i = (gdouble *) in; gdouble *i = (gdouble *) in;
@ -591,8 +622,8 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
while (len) { while (len) {
tmp = *i; tmp = *i;
GST_WRITE_UINT24 (o, CLAMP (tmp * GST_MAXINT24 + 0.5, GST_MININT24, GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5,
GST_MAXINT24)); GST_MININT24, GST_MAXINT24));
o += 3; o += 3;
i++; i++;
len--; len--;
@ -604,14 +635,14 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
while (len) { while (len) {
tmp = *i; tmp = *i;
*o = CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32); *o = (gint32) CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32);
o++; o++;
i++; i++;
len--; len--;
} }
} }
} else { } else {
if (resample->width == 8 && !resample->fp) { if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
gint8 *i = (gint8 *) in; gint8 *i = (gint8 *) in;
gint16 *o = (gint16 *) out; gint16 *o = (gint16 *) out;
gint32 tmp; gint32 tmp;
@ -623,6 +654,32 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
i++; i++;
len--; len--;
} }
} else if (!gst_speex_resample_use_int && resample->width == 8
&& !resample->fp) {
gint8 *i = (gint8 *) in;
gfloat *o = (gfloat *) out;
gfloat tmp;
while (len) {
tmp = *i;
*o = tmp / G_MAXINT8;
o++;
i++;
len--;
}
} else if (!gst_speex_resample_use_int && resample->width == 16
&& !resample->fp) {
gint16 *i = (gint16 *) in;
gfloat *o = (gfloat *) out;
gfloat tmp;
while (len) {
tmp = *i;
*o = tmp / G_MAXINT16;
o++;
i++;
len--;
}
} else if (resample->width == 24 && !resample->fp) { } else if (resample->width == 24 && !resample->fp) {
guint8 *i = (guint8 *) in; guint8 *i = (guint8 *) in;
gdouble *o = (gdouble *) out; gdouble *o = (gdouble *) out;
@ -1117,10 +1174,134 @@ gst_speex_resample_get_property (GObject * object, guint prop_id,
} }
} }
#define BENCHMARK_SIZE 512
static gboolean
_benchmark_int_float (SpeexResamplerState * st)
{
gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
gfloat in_tmp[BENCHMARK_SIZE], out_tmp[BENCHMARK_SIZE / 2];
gint i;
guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
for (i = 0; i < BENCHMARK_SIZE; i++) {
gfloat tmp = in[i];
in_tmp[i] = tmp / G_MAXINT16;
}
resample_float_resampler_process_interleaved_float (st,
(const guint8 *) in_tmp, &inlen, (guint8 *) out_tmp, &outlen);
if (outlen == 0) {
GST_ERROR ("Failed to use float resampler");
return FALSE;
}
for (i = 0; i < outlen; i++) {
gfloat tmp = out_tmp[i];
out[i] = CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
}
return TRUE;
}
static gboolean
_benchmark_int_int (SpeexResamplerState * st)
{
gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
resample_int_resampler_process_interleaved_int (st, (const guint8 *) in,
&inlen, (guint8 *) out, &outlen);
if (outlen == 0) {
GST_ERROR ("Failed to use int resampler");
return FALSE;
}
return TRUE;
}
static gboolean
_benchmark_integer_resampling (void)
{
OilProfile a, b;
gdouble av, bv;
SpeexResamplerState *sta, *stb;
oil_profile_init (&a);
oil_profile_init (&b);
sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL);
if (sta == NULL) {
GST_ERROR ("Failed to create float resampler state");
return FALSE;
}
stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL);
if (stb == NULL) {
resample_float_resampler_destroy (sta);
GST_ERROR ("Failed to create int resampler state");
return FALSE;
}
/* Warm up cache */
if (!_benchmark_int_float (sta))
goto error;
if (!_benchmark_int_float (sta))
goto error;
/* Benchmark */
oil_profile_start (&a);
if (!_benchmark_int_float (sta))
goto error;
oil_profile_stop (&a);
/* Warm up cache */
if (!_benchmark_int_int (stb))
goto error;
if (!_benchmark_int_int (stb))
goto error;
/* Benchmark */
oil_profile_start (&b);
if (!_benchmark_int_int (stb))
goto error;
oil_profile_stop (&b);
/* Handle results */
oil_profile_get_ave_std (&a, &av, NULL);
oil_profile_get_ave_std (&b, &bv, NULL);
gst_speex_resample_use_int = (av > bv);
resample_float_resampler_destroy (sta);
resample_float_resampler_destroy (stb);
if (av > bv)
GST_DEBUG ("Using integer resampler if appropiate: %lf < %lf", bv, av);
else
GST_DEBUG ("Using float resampler for everything: %lf <= %lf", av, bv);
return TRUE;
error:
resample_float_resampler_destroy (sta);
resample_float_resampler_destroy (stb);
return FALSE;
}
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0,
"audio resampling element");
oil_init ();
if (!_benchmark_integer_resampling ())
return FALSE;
if (!gst_element_register (plugin, "speexresample", GST_RANK_NONE, if (!gst_element_register (plugin, "speexresample", GST_RANK_NONE,
GST_TYPE_SPEEX_RESAMPLE)) { GST_TYPE_SPEEX_RESAMPLE)) {
return FALSE; return FALSE;

View file

@ -1,6 +1,6 @@
/* GStreamer /* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2007> Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) <2007-2008> Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public

View file

@ -66,7 +66,7 @@
#include <glib.h> #include <glib.h>
#define EXPORT #define EXPORT G_GNUC_INTERNAL
static inline void * static inline void *
speex_alloc (int size) speex_alloc (int size)

View file

@ -1,5 +1,5 @@
/* GStreamer /* GStreamer
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public

View file

@ -1,5 +1,5 @@
/* GStreamer /* GStreamer
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public

View file

@ -1,5 +1,5 @@
/* GStreamer /* GStreamer
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public

View file

@ -1,5 +1,5 @@
/* GStreamer /* GStreamer
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public