audiotestsrc: each element gets its own instance of GRand, if needed
authorLeo Singer <leo.singer@ligo.org>
Fri, 18 Feb 2011 21:27:23 +0000 (13:27 -0800)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Sat, 19 Feb 2011 07:37:46 +0000 (08:37 +0100)
As a result, pipelines that contain multiple instances of audiotestsrc
with the 'wave' property set to 'white-noise', 'pink-noise', or
'gaussian-noise' will run much faster, since they won't be competing
for access to the global, lock-protected instance of GRand.

Fixes bug #642720.

gst/audiotestsrc/gstaudiotestsrc.c
gst/audiotestsrc/gstaudiotestsrc.h

index 5b68971..ecbb2fb 100644 (file)
@@ -140,6 +140,8 @@ gst_audiostestsrc_wave_get_type (void)
   return audiostestsrc_wave_type;
 }
 
+static void gst_audio_test_src_finalize (GObject * object);
+
 static void gst_audio_test_src_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
 static void gst_audio_test_src_get_property (GObject * object,
@@ -190,6 +192,7 @@ gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
 
   gobject_class->set_property = gst_audio_test_src_set_property;
   gobject_class->get_property = gst_audio_test_src_get_property;
+  gobject_class->finalize = gst_audio_test_src_finalize;
 
   g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
       g_param_spec_int ("samplesperbuffer", "Samples per buffer",
@@ -263,11 +266,25 @@ gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class)
   src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
   src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
 
+  src->gen = NULL;
+
   src->wave = DEFAULT_WAVE;
   gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
 }
 
 static void
+gst_audio_test_src_finalize (GObject * object)
+{
+  GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
+
+  if (src->gen)
+    g_rand_free (src->gen);
+  src->gen = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
 {
   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad));
@@ -584,7 +601,7 @@ gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * s
   i = 0; \
   while (i < (src->generate_samples_per_buffer * src->channels)) { \
     for (c = 0; c < src->channels; ++c) \
-      samples[i++] = (g##type) (amp * g_random_double_range (-1.0, 1.0)); \
+      samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
   } \
 }
 
@@ -626,8 +643,9 @@ gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
 
 /* Generate Pink noise values between -1.0 and +1.0 */
 static gdouble
-gst_audio_test_src_generate_pink_noise_value (GstPinkNoise * pink)
+gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
 {
+  GstPinkNoise *pink = &src->pink;
   glong new_random;
   glong sum;
 
@@ -651,13 +669,15 @@ gst_audio_test_src_generate_pink_noise_value (GstPinkNoise * pink)
      * values together. Only one changes each time.
      */
     pink->running_sum -= pink->rows[num_zeros];
-    new_random = 32768.0 - (65536.0 * (gulong) rand () / (RAND_MAX + 1.0));
+    new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
+        / (G_MAXUINT32 + 1.0));
     pink->running_sum += new_random;
     pink->rows[num_zeros] = new_random;
   }
 
   /* Add extra white noise value. */
-  new_random = 32768.0 - (65536.0 * (gulong) rand () / (RAND_MAX + 1.0));
+  new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
+      / (G_MAXUINT32 + 1.0));
   sum = pink->running_sum + new_random;
 
   /* Scale to range of -1.0 to 0.9999. */
@@ -677,7 +697,7 @@ gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * sa
   while (i < (src->generate_samples_per_buffer * src->channels)) { \
     for (c = 0; c < src->channels; ++c) { \
       samples[i++] = \
-        (g##type) (gst_audio_test_src_generate_pink_noise_value (&src->pink) * \
+        (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
         amp); \
     } \
   } \
@@ -794,8 +814,8 @@ gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g#
   \
   for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
     for (c = 0; c < src->channels; ++c) { \
-      gdouble mag = sqrt (-2 * log (1.0 - g_random_double ())); \
-      gdouble phs = g_random_double_range (0.0, M_PI_M2); \
+      gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
+      gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
       \
       samples[i++] = (g##type) (amp * mag * cos (phs)); \
       if (++c >= src->channels) \
@@ -846,9 +866,13 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src)
       src->process = silence_funcs[src->format];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
+      if (!(src->gen))
+        src->gen = g_rand_new ();
       src->process = white_noise_funcs[src->format];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
+      if (!(src->gen))
+        src->gen = g_rand_new ();
       gst_audio_test_src_init_pink_noise (src);
       src->process = pink_noise_funcs[src->format];
       break;
@@ -861,6 +885,8 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src)
       src->process = tick_funcs[src->format];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
+      if (!(src->gen))
+        src->gen = g_rand_new ();
       src->process = gaussian_white_noise_funcs[src->format];
       break;
     default:
index 860c5c0..8c76594 100644 (file)
@@ -127,6 +127,7 @@ struct _GstAudioTestSrc {
   gboolean reverse;                  /* play backwards */
   
   /* waveform specific context data */
+  GRand *gen;               /* random number generator */
   gdouble accumulator;                 /* phase angle */
   GstPinkNoise pink;
   gdouble wave_table[1024];