gst/audioconvert/: Implement a linear congruential generator as pseudo random number...
authorSebastian Dröge <slomo@circular-chaos.org>
Wed, 23 Jul 2008 18:34:19 +0000 (18:34 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Wed, 23 Jul 2008 18:34:19 +0000 (18:34 +0000)
Original commit message from CVS:
* gst/audioconvert/audioconvert.h:
* gst/audioconvert/gstaudioquantize.c:
(gst_audio_quantize_setup_dither),
(gst_audio_quantize_free_dither):
* gst/audioconvert/gstfastrandom.h:
Implement a linear congruential generator as pseudo random number
generator for the dither noise. This is about 2 times faster than
using GLib's mersenne twister. Also this uses only integer math for
generating integers while GLib internally uses floating point math.

ChangeLog
gst/audioconvert/audioconvert.h
gst/audioconvert/gstaudioquantize.c
gst/audioconvert/gstfastrandom.h [new file with mode: 0644]

index f46be65..513f8be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-07-23  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
+       * gst/audioconvert/audioconvert.h:
+       * gst/audioconvert/gstaudioquantize.c:
+       (gst_audio_quantize_setup_dither),
+       (gst_audio_quantize_free_dither):
+       * gst/audioconvert/gstfastrandom.h:
+       Implement a linear congruential generator as pseudo random number
+       generator for the dither noise. This is about 2 times faster than
+       using GLib's mersenne twister. Also this uses only integer math for
+       generating integers while GLib internally uses floating point math.
+
 2008-07-23  Michael Smith <msmith@songbirdnest.com>
 
        * configure.ac:
index 7c26ae1..98ce829 100644 (file)
@@ -121,8 +121,6 @@ struct _AudioConvertCtx
 
   GstAudioConvertDithering dither;
   GstAudioConvertNoiseShaping ns;
-  /* random number generate for dither noise */
-  GRand *dither_random;
   /* last random number generated per channel for hifreq TPDF dither */
   gpointer last_random;
   /* contains the past quantization errors, error[out_channels][count] */
index b638598..2155397 100644 (file)
@@ -37,6 +37,8 @@
 #include "audioconvert.h"
 #include "gstaudioquantize.h"
 
+#include "gstfastrandom.h"
+
 #define MAKE_QUANTIZE_FUNC_NAME(name)                                   \
 gst_audio_quantize_quantize_##name
 
@@ -144,8 +146,8 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   gint32 dither = (1<<(scale));
 
 #define ADD_DITHER_RPDF_I()                                             \
-        rand = g_rand_int_range (ctx->dither_random, bias - dither,     \
-               bias + dither);                                          \
+        rand = gst_fast_random_int32_range (bias - dither,              \
+           bias + dither);                                             \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
                 tmp = G_MAXINT32;                                       \
         else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand)       \
@@ -157,8 +159,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   gdouble dither = 1.0/(1U<<(32 - scale - 1));
 
 #define ADD_DITHER_RPDF_F()                                             \
-        tmp += g_rand_double_range (ctx->dither_random, - dither,       \
-               dither);
+        tmp += gst_fast_random_double_range (- dither, dither);
 
 #define INIT_DITHER_TPDF_I()                                            \
   gint32 rand;                                                          \
@@ -166,10 +167,10 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   bias = bias >> 1;
 
 #define ADD_DITHER_TPDF_I()                                             \
-        rand = g_rand_int_range (ctx->dither_random, bias - dither,     \
-               bias + dither - 1)                                           \
-               + g_rand_int_range (ctx->dither_random, bias - dither,   \
-               bias + dither - 1);                                          \
+        rand = gst_fast_random_int32_range (bias - dither,              \
+                   bias + dither - 1)                                   \
+               + gst_fast_random_int32_range (bias - dither,            \
+                   bias + dither - 1);                                  \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
                 tmp = G_MAXINT32;                                       \
         else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand)       \
@@ -181,10 +182,8 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   gdouble dither = 1.0/(1U<<(32 - scale));
 
 #define ADD_DITHER_TPDF_F()                                             \
-        tmp += g_rand_double_range (ctx->dither_random, - dither,       \
-               dither)                                                  \
-               + g_rand_double_range (ctx->dither_random, - dither,     \
-               dither);
+        tmp += gst_fast_random_double_range (- dither, dither)          \
+               + gst_fast_random_double_range (- dither, dither);
 
 #define INIT_DITHER_TPDF_HF_I()                                         \
   gint32 rand;                                                          \
@@ -193,8 +192,8 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   bias = bias >> 1;
 
 #define ADD_DITHER_TPDF_HF_I()                                          \
-        tmp_rand = g_rand_int_range (ctx->dither_random, bias - dither, \
-                   bias + dither); \
+        tmp_rand = gst_fast_random_int32_range (bias - dither,          \
+                       bias + dither);                                  \
         rand = tmp_rand - last_random[chan_pos];                        \
         last_random[chan_pos] = tmp_rand;                               \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
@@ -213,8 +212,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
   gdouble *last_random = (gdouble *) ctx->last_random, tmp_rand;
 
 #define ADD_DITHER_TPDF_HF_F()                                          \
-        tmp_rand = g_rand_double_range (ctx->dither_random, - dither,   \
-                   dither);                                             \
+        tmp_rand = gst_fast_random_double_range (- dither, dither);     \
         rand = tmp_rand - last_random[chan_pos];                        \
         last_random[chan_pos] = tmp_rand;                               \
         tmp += rand;
@@ -445,16 +443,13 @@ gst_audio_quantize_setup_dither (AudioConvertCtx * ctx)
         ctx->last_random = g_new0 (gint32, ctx->out.channels);
       else
         ctx->last_random = g_new0 (gdouble, ctx->out.channels);
-      ctx->dither_random = g_rand_new ();
       break;
     case DITHER_RPDF:
     case DITHER_TPDF:
-      ctx->dither_random = g_rand_new ();
       ctx->last_random = NULL;
       break;
     case DITHER_NONE:
     default:
-      ctx->dither_random = NULL;
       ctx->last_random = NULL;
       break;
   }
@@ -465,8 +460,6 @@ static void
 gst_audio_quantize_free_dither (AudioConvertCtx * ctx)
 {
   g_free (ctx->last_random);
-  if (ctx->dither_random)
-    g_rand_free (ctx->dither_random);
 
   return;
 }
diff --git a/gst/audioconvert/gstfastrandom.h b/gst/audioconvert/gstfastrandom.h
new file mode 100644 (file)
index 0000000..b1c88b5
--- /dev/null
@@ -0,0 +1,90 @@
+/* GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * gstfastrandom.h: Fast, bad PNRG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+
+#ifndef __GST_FAST_RANDOM__
+#define __GST_FAST_RANDOM__
+
+/* transform [0..2^32] -> [0..1] */
+#define GST_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
+
+/* This is the base function, implementing a linear congruential generator
+ * and returning a pseudo random number between 0 and 2^32 - 1.
+ */
+static inline guint32
+gst_fast_random_uint32 ()
+{
+  static guint32 state = 0xdeadbeef;
+
+  return (state = state * 1103515245 + 12345);
+}
+
+static inline guint32
+gst_fast_random_uint32_range (gint32 start, gint32 end)
+{
+  guint64 tmp = gst_fast_random_uint32 ();
+
+  tmp = (tmp * (end - start)) / G_MAXUINT32 + start;
+
+  return (guint32) tmp;
+}
+
+static inline gint32
+gst_fast_random_int32 (void)
+{
+  return (gint32) gst_fast_random_uint32 ();
+}
+
+static inline gint32
+gst_fast_random_int32_range (gint32 start, gint32 end)
+{
+  gint64 tmp = gst_fast_random_uint32 ();
+
+  tmp = (tmp * (end - start)) / G_MAXUINT32 + start;
+
+  return (gint32) tmp;
+}
+
+static inline gdouble
+gst_fast_random_double (void)
+{
+  gdouble ret;
+
+  ret = gst_fast_random_uint32 () * GST_RAND_DOUBLE_TRANSFORM;
+  ret = (ret + gst_fast_random_uint32 ()) * GST_RAND_DOUBLE_TRANSFORM;
+
+  if (ret >= 1.0)
+    return gst_fast_random_double ();
+
+  return ret;
+}
+
+static inline gdouble
+gst_fast_random_double_range (gdouble start, gdouble end)
+{
+  return gst_fast_random_double () * (end - start) + start;
+}
+
+#undef GST_RAND_DOUBLE_TRANSFORM
+
+#endif /* __GST_FAST_RANDOM__ */
+