vorbis: have a copy_sample func as a func pointer
authorStefan Kost <ensonic@users.sf.net>
Thu, 6 May 2010 05:20:10 +0000 (08:20 +0300)
committerStefan Kost <ensonic@users.sf.net>
Thu, 6 May 2010 05:22:36 +0000 (08:22 +0300)
Make some more variants for copy_sample funcs and use them via function pointer.

ext/vorbis/gstvorbisdec.c
ext/vorbis/gstvorbisdec.h
ext/vorbis/gstvorbisdeclib.c
ext/vorbis/gstvorbisdeclib.h

index 1e4b50b..56f7b84 100644 (file)
@@ -588,11 +588,18 @@ vorbis_handle_identification_packet (GstVorbisDec * vd)
       s = gst_caps_get_structure (caps, 0);
       /* template ensures 16 or 32 */
       gst_structure_get_int (s, "width", &width);
+
+      GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth",
+          gst_structure_get_name (s), vd->vi.channels, width);
     }
     gst_caps_unref (caps);
   }
   vd->width = width >> 3;
 
+  /* select a copy_samples function, this way we can have specialized versions
+   * for mono/stereo and avoid the depth switch in tremor case */
+  vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width);
+
   caps = gst_caps_copy (gst_pad_get_pad_template_caps (vd->srcpad));
   gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate,
       "channels", G_TYPE_INT, vd->vi.channels,
@@ -881,8 +888,8 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
     goto wrong_samples;
 
   /* copy samples in buffer */
-  copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm, sample_count,
-      vd->vi.channels, vd->width);
+  vd->copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm,
+      sample_count, vd->vi.channels, vd->width);
 
   GST_LOG_OBJECT (vd, "setting output size to %d", size);
   GST_BUFFER_SIZE (out) = size;
index 65c73ae..0f4b3dd 100644 (file)
@@ -75,6 +75,8 @@ struct _GstVorbisDec {
 
   GList            *pendingevents;
   GstTagList       *taglist;
+  
+  CopySampleFunc    copy_samples;
 };
 
 struct _GstVorbisDecClass {
index 9f3331c..1ddce38 100644 (file)
 #include "config.h"
 #endif
 
+#include <string.h>
 #include "gstvorbisdeclib.h"
 
 #ifndef TREMOR
 /* These samples can be outside of the float -1.0 -- 1.0 range, this
  * is allowed, downstream elements are supposed to clip */
-void
-copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
+static void
+copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
     gint channels, gint width)
 {
-  gint i, j;
+  memcpy (out, in[0], samples * sizeof (float));
+}
 
-  g_assert (width == 4);
+static void
+copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
+    gint channels, gint width)
+{
+#ifdef GST_VORBIS_DEC_SEQUENTIAL
+  memcpy (out, in[0], samples * sizeof (float));
+  out += samples;
+  memcpy (out, in[1], samples * sizeof (float));
+#else
+  gint j;
+
+  for (j = 0; j < samples; j++) {
+    *out++ = in[0][j];
+    *out++ = in[1][j];
+  }
+#endif
+}
 
+static void
+copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
+    gint channels, gint width)
+{
 #ifdef GST_VORBIS_DEC_SEQUENTIAL
+  gint i;
+
   for (i = 0; i < channels; i++) {
     memcpy (out, in[i], samples * sizeof (float));
     out += samples;
   }
 #else
+  gint i, j;
+
   for (j = 0; j < samples; j++) {
     for (i = 0; i < channels; i++) {
       *out++ = in[i][j];
@@ -53,6 +79,28 @@ copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
 #endif
 }
 
+CopySampleFunc
+get_copy_sample_func (gint channels, gint width)
+{
+  CopySampleFunc f = NULL;
+
+  g_assert (width == 4);
+
+  switch (channels) {
+    case 1:
+      f = copy_samples_m;
+      break;
+    case 2:
+      f = copy_samples_s;
+      break;
+    default:
+      f = copy_samples;
+      break;
+  }
+
+  return f;
+}
+
 #else
 
 /* Taken from Tremor, misc.h */
@@ -83,8 +131,38 @@ CLIP_TO_15 (ogg_int32_t x)
 #endif
 
 static void
-copy_samples_32 (gint32 * out, ogg_int32_t ** in, guint samples, gint channels)
+copy_samples_32_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
+    guint samples, gint channels, gint width)
 {
+  gint32 *out = (gint32 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
+  gint j;
+
+  for (j = 0; j < samples; j++) {
+    *out++ = CLIP_TO_15 (in[0][j] >> 9);
+  }
+}
+
+static void
+copy_samples_32_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
+    guint samples, gint channels, gint width)
+{
+  gint32 *out = (gint32 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
+  gint j;
+
+  for (j = 0; j < samples; j++) {
+    *out++ = CLIP_TO_15 (in[0][j] >> 9);
+    *out++ = CLIP_TO_15 (in[1][j] >> 9);
+  }
+}
+
+static void
+copy_samples_32 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
+    gint channels, gint width)
+{
+  gint32 *out = (gint32 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
   gint i, j;
 
   for (j = 0; j < samples; j++) {
@@ -95,8 +173,38 @@ copy_samples_32 (gint32 * out, ogg_int32_t ** in, guint samples, gint channels)
 }
 
 static void
-copy_samples_16 (gint16 * out, ogg_int32_t ** in, guint samples, gint channels)
+copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
+    guint samples, gint channels, gint width)
+{
+  gint16 *out = (gint16 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
+  gint j;
+
+  for (j = 0; j < samples; j++) {
+    *out++ = CLIP_TO_15 (in[0][j] >> 9);
+  }
+}
+
+static void
+copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
+    guint samples, gint channels, gint width)
+{
+  gint16 *out = (gint16 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
+  gint j;
+
+  for (j = 0; j < samples; j++) {
+    *out++ = CLIP_TO_15 (in[0][j] >> 9);
+    *out++ = CLIP_TO_15 (in[1][j] >> 9);
+  }
+}
+
+static void
+copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
+    gint channels, gint width)
 {
+  gint16 *out = (gint16 *) _out;
+  ogg_int32_t **in = (ogg_int32_t **) _in;
   gint i, j;
 
   for (j = 0; j < samples; j++) {
@@ -106,17 +214,39 @@ copy_samples_16 (gint16 * out, ogg_int32_t ** in, guint samples, gint channels)
   }
 }
 
-void
-copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
-    gint channels, gint width)
+CopySampleFunc
+get_copy_sample_func (gint channels, gint width)
 {
+  CopySampleFunc f = NULL;
+
   if (width == 4) {
-    copy_samples_32 ((gint32 *) out, in, samples, channels);
+    switch (channels) {
+      case 1:
+        f = copy_samples_32_m;
+        break;
+      case 2:
+        f = copy_samples_32_s;
+        break;
+      default:
+        f = copy_samples_32;
+        break;
+    }
   } else if (width == 2) {
-    copy_samples_16 ((gint16 *) out, in, samples, channels);
+    switch (channels) {
+      case 1:
+        f = copy_samples_16_m;
+        break;
+      case 2:
+        f = copy_samples_16_s;
+        break;
+      default:
+        f = copy_samples_16;
+        break;
+    }
   } else {
     g_assert_not_reached ();
   }
+  return f;
 }
 
 #endif
index df9093f..c82f0c8 100644 (file)
@@ -37,8 +37,10 @@ typedef ogg_packet                     ogg_packet_wrapper;
 #define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to float audio"
 
 #define GST_VORBIS_DEC_SRC_CAPS \
-    GST_STATIC_CAPS ("audio/x-raw-float, " "rate = (int) [ 1, MAX ], " \
-        "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, " \
+    GST_STATIC_CAPS ("audio/x-raw-float, " \
+        "rate = (int) [ 1, MAX ], " \
+        "channels = (int) [ 1, 256 ], " \
+        "endianness = (int) BYTE_ORDER, " \
         "width = (int) 32")
 
 #define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH           (32)
@@ -91,7 +93,8 @@ struct _ogg_packet_wrapper {
         "channels = (int) [ 1, 6 ], "      \
         "endianness = (int) BYTE_ORDER, "  \
         "width = (int) { 16, 32 }, "       \
-        "depth = (int) 16, " "signed = (boolean) true")
+        "depth = (int) 16, "               \
+        "signed = (boolean) true")
 
 #define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH           (16)
 
@@ -147,8 +150,9 @@ gst_ogg_packet_from_wrapper (ogg_packet_wrapper * packet)
 
 #endif
 
-void  copy_samples        (vorbis_sample_t *out, vorbis_sample_t **in,
+typedef void (*CopySampleFunc)(vorbis_sample_t *out, vorbis_sample_t **in,
                            guint samples, gint channels, gint width);
 
+CopySampleFunc get_copy_sample_func (gint channels, gint width);
 
 #endif /* __GST_VORBIS_DEC_LIB_H__ */