From ef5004e56ec74eea378d06a28757c7767abbd44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 23 Jul 2008 18:34:19 +0000 Subject: [PATCH] gst/audioconvert/: Implement a linear congruential generator as pseudo random number generator for the dither noise. ... 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 | 12 ++++ gst/audioconvert/audioconvert.h | 2 - gst/audioconvert/gstaudioquantize.c | 35 +++++------ gst/audioconvert/gstfastrandom.h | 90 +++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 gst/audioconvert/gstfastrandom.h diff --git a/ChangeLog b/ChangeLog index f46be65d66..513f8be592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-07-23 Sebastian Dröge + + * 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 * configure.ac: diff --git a/gst/audioconvert/audioconvert.h b/gst/audioconvert/audioconvert.h index 7c26ae1ed4..98ce829f36 100644 --- a/gst/audioconvert/audioconvert.h +++ b/gst/audioconvert/audioconvert.h @@ -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] */ diff --git a/gst/audioconvert/gstaudioquantize.c b/gst/audioconvert/gstaudioquantize.c index b6385985a5..2155397cb4 100644 --- a/gst/audioconvert/gstaudioquantize.c +++ b/gst/audioconvert/gstaudioquantize.c @@ -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 index 0000000000..b1c88b54da --- /dev/null +++ b/gst/audioconvert/gstfastrandom.h @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) 2008 Sebastian Dröge + * + * 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 + +#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__ */ +