gst/speexresample/: Add missing headers to Makefile.am.
authorSebastian Dröge <slomo@circular-chaos.org>
Sat, 1 Nov 2008 19:38:36 +0000 (19:38 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Sat, 1 Nov 2008 19:38:36 +0000 (19:38 +0000)
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.

gst/speexresample/Makefile.am
gst/speexresample/gstspeexresample.c
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

index f4d1534d57904a37b0a02d8f880645d8577e5b70..161de6211b597e372cfef690d7e7ed26d1bf8f1c 100644 (file)
@@ -9,24 +9,29 @@ libgstspeexresample_la_SOURCES = \
 libgstspeexresample_la_CFLAGS = \
        $(GST_PLUGINS_BASE_CFLAGS) \
        $(GST_BASE_CFLAGS) \
-       $(GST_CFLAGS)
+       $(GST_CFLAGS) \
+       $(LIBOIL_CFLAGS)
 
 libgstspeexresample_la_LIBADD = \
        $(GST_PLUGINS_BASE_LIBS) \
        $(GST_BASE_LIBS) \
        $(GST_LIBS) \
        -lgstaudio-$(GST_MAJORMINOR) \
+       $(LIBOIL_LIBS) \
        $(LIBM)
 
 libgstspeexresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = \
        arch.h \
+       fixed_arm4.h \
+       fixed_arm5e.h \
+       fixed_bfin.h \
+       fixed_debug.h \
        fixed_generic.h \
        gstspeexresample.h \
+       resample.c \
+       resample_sse.h \
        speex_resampler.h \
        speex_resampler_wrapper.h
 
-EXTRA_DIST = \
-       resample.c
-
index 7d04257a37ba56fb6a35a4939792d8cdaf22d05d..f2fa485938a5d0f1505ac01584910042dea83535 100644 (file)
@@ -1,7 +1,7 @@
 /* GStreamer
  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
  * 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
  * modify it under the terms of the GNU Library General Public
 #include <gst/audio/audio.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);
 #define GST_CAT_DEFAULT speex_resample_debug
 
@@ -91,6 +95,9 @@ GST_STATIC_CAPS ( \
       "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 =
 GST_STATIC_PAD_TEMPLATE ("sink",
     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 const GstQueryType *gst_speex_resample_query_type (GstPad * pad);
 
-#define DEBUG_INIT(bla) \
-  GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0, "audio resampling element");
-
-GST_BOILERPLATE_FULL (GstSpeexResample, gst_speex_resample, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
+GST_BOILERPLATE (GstSpeexResample, gst_speex_resample, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM);
 
 static void
 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",
       "Filter/Converter/Audio", "Resamples audio",
-      "Sebastian Dröge <slomo@circular-chaos.org>");
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 }
 
 static void
@@ -297,9 +301,10 @@ gst_speex_resample_get_funcs (gint width, gboolean fp)
 {
   const SpeexResampleFuncs *funcs = NULL;
 
-  if ((width == 8 || width == 16) && !fp)
+  if (gst_speex_resample_use_int && (width == 8 || width == 16) && !fp)
     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;
   else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp))
     funcs = &double_funcs;
@@ -572,7 +577,7 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
   len *= resample->channels;
 
   if (inverse) {
-    if (resample->width == 8 && !resample->fp) {
+    if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
       gint8 *o = (gint8 *) out;
       gint16 *i = (gint16 *) in;
       gint32 tmp;
@@ -584,6 +589,32 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
         i++;
         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) {
       guint8 *o = (guint8 *) out;
       gdouble *i = (gdouble *) in;
@@ -591,8 +622,8 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
 
       while (len) {
         tmp = *i;
-        GST_WRITE_UINT24 (o, CLAMP (tmp * GST_MAXINT24 + 0.5, GST_MININT24,
-                GST_MAXINT24));
+        GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5,
+                GST_MININT24, GST_MAXINT24));
         o += 3;
         i++;
         len--;
@@ -604,14 +635,14 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
 
       while (len) {
         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++;
         i++;
         len--;
       }
     }
   } else {
-    if (resample->width == 8 && !resample->fp) {
+    if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
       gint8 *i = (gint8 *) in;
       gint16 *o = (gint16 *) out;
       gint32 tmp;
@@ -623,6 +654,32 @@ gst_speex_resample_convert_buffer (GstSpeexResample * resample,
         i++;
         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) {
       guint8 *i = (guint8 *) in;
       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
 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,
           GST_TYPE_SPEEX_RESAMPLE)) {
     return FALSE;
index 1cf2196c8d07ab27685fe644f039d04517fe7695..e39148a0d7fdd57de2f4872ad2b74c2f7c1d662d 100644 (file)
@@ -1,6 +1,6 @@
 /* GStreamer
  * 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
  * modify it under the terms of the GNU Library General Public
index 6f172509e7acb9717ae8c99d5dc90e29891330fa..f29e6144ff9e4a3a9acd56d3c660689b71679b6f 100644 (file)
@@ -66,7 +66,7 @@
 
 #include <glib.h>
 
-#define EXPORT
+#define EXPORT G_GNUC_INTERNAL
 
 static inline void *
 speex_alloc (int size)
index 39e242d81ca981fc5e9f9260b097b0af9097aed3..e5a25714ca162e1ba5fa6bf7152837f3a7375de8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
  * modify it under the terms of the GNU Library General Public
index 281e52d3a312d9644ea90123e740ecfce9367aa4..f13f60c5b0b69e8090d45bd3a6c357ecf67023f0 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
  * modify it under the terms of the GNU Library General Public
index c992f0a64c04e7f410cea5daaa7bc3fbbcfdef6e..6b85860471c2d088c4b82cec84058122b5761807 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
  * modify it under the terms of the GNU Library General Public
index 2cf79b0e7e5b6ff077094e5e2499c91e4ffdfb06..36d444f8796c1ba4fd312b22da324cf958588b32 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
  * modify it under the terms of the GNU Library General Public