Add float as an intermediate format, as well as float mixing. Enable test that was...
authorStefan Kost <ensonic@users.sourceforge.net>
Thu, 22 Feb 2007 09:04:37 +0000 (09:04 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Thu, 22 Feb 2007 09:04:37 +0000 (09:04 +0000)
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

ChangeLog
gst/audioconvert/audioconvert.c
gst/audioconvert/audioconvert.h
gst/audioconvert/gstchannelmix.c
gst/audioconvert/gstchannelmix.h
tests/check/elements/audioconvert.c

index a0cec58..e14724d 100644 (file)
--- a/ChangeLog
+++ b/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):
index d14a991..049e101 100644 (file)
@@ -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;
   }
index 3c90624..34e9032 100644 (file)
@@ -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); 
index f4f6e6f..94023d9 100644 (file)
@@ -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);
+  }
+}
index 866f34a..d046210 100644 (file)
@@ -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__ */
index f8ea130..deb2cc2 100644 (file)
@@ -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
   }
 }