audiotestsrc: each element gets its own instance of GRand, if needed

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.
This commit is contained in:
Leo Singer 2011-02-18 13:27:23 -08:00 committed by Sebastian Dröge
parent 0e3c32ac72
commit 82199c5815
2 changed files with 34 additions and 7 deletions

View file

@ -140,6 +140,8 @@ gst_audiostestsrc_wave_get_type (void)
return audiostestsrc_wave_type; return audiostestsrc_wave_type;
} }
static void gst_audio_test_src_finalize (GObject * object);
static void gst_audio_test_src_set_property (GObject * object, static void gst_audio_test_src_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec); guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_audio_test_src_get_property (GObject * object, 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->set_property = gst_audio_test_src_set_property;
gobject_class->get_property = gst_audio_test_src_get_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_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
g_param_spec_int ("samplesperbuffer", "Samples per buffer", g_param_spec_int ("samplesperbuffer", "Samples per buffer",
@ -263,10 +266,24 @@ gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class)
src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET; src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
src->gen = NULL;
src->wave = DEFAULT_WAVE; src->wave = DEFAULT_WAVE;
gst_base_src_set_blocksize (GST_BASE_SRC (src), -1); 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 static void
gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps) gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
{ {
@ -584,7 +601,7 @@ gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * s
i = 0; \ i = 0; \
while (i < (src->generate_samples_per_buffer * src->channels)) { \ while (i < (src->generate_samples_per_buffer * src->channels)) { \
for (c = 0; c < src->channels; ++c) \ 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 */ /* Generate Pink noise values between -1.0 and +1.0 */
static gdouble 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 new_random;
glong sum; glong sum;
@ -651,13 +669,15 @@ gst_audio_test_src_generate_pink_noise_value (GstPinkNoise * pink)
* values together. Only one changes each time. * values together. Only one changes each time.
*/ */
pink->running_sum -= pink->rows[num_zeros]; 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->running_sum += new_random;
pink->rows[num_zeros] = new_random; pink->rows[num_zeros] = new_random;
} }
/* Add extra white noise value. */ /* 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; sum = pink->running_sum + new_random;
/* Scale to range of -1.0 to 0.9999. */ /* 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)) { \ while (i < (src->generate_samples_per_buffer * src->channels)) { \
for (c = 0; c < src->channels; ++c) { \ for (c = 0; c < src->channels; ++c) { \
samples[i++] = \ 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); \ 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 (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
for (c = 0; c < src->channels; ++c) { \ for (c = 0; c < src->channels; ++c) { \
gdouble mag = sqrt (-2 * log (1.0 - g_random_double ())); \ gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
gdouble phs = g_random_double_range (0.0, M_PI_M2); \ gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
\ \
samples[i++] = (g##type) (amp * mag * cos (phs)); \ samples[i++] = (g##type) (amp * mag * cos (phs)); \
if (++c >= src->channels) \ if (++c >= src->channels) \
@ -846,9 +866,13 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src)
src->process = silence_funcs[src->format]; src->process = silence_funcs[src->format];
break; break;
case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
if (!(src->gen))
src->gen = g_rand_new ();
src->process = white_noise_funcs[src->format]; src->process = white_noise_funcs[src->format];
break; break;
case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE: case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
if (!(src->gen))
src->gen = g_rand_new ();
gst_audio_test_src_init_pink_noise (src); gst_audio_test_src_init_pink_noise (src);
src->process = pink_noise_funcs[src->format]; src->process = pink_noise_funcs[src->format];
break; break;
@ -861,6 +885,8 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src)
src->process = tick_funcs[src->format]; src->process = tick_funcs[src->format];
break; break;
case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: 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]; src->process = gaussian_white_noise_funcs[src->format];
break; break;
default: default:

View file

@ -127,6 +127,7 @@ struct _GstAudioTestSrc {
gboolean reverse; /* play backwards */ gboolean reverse; /* play backwards */
/* waveform specific context data */ /* waveform specific context data */
GRand *gen; /* random number generator */
gdouble accumulator; /* phase angle */ gdouble accumulator; /* phase angle */
GstPinkNoise pink; GstPinkNoise pink;
gdouble wave_table[1024]; gdouble wave_table[1024];