From 620391b3001854874c53c18c084e587c30eacbdd Mon Sep 17 00:00:00 2001 From: Kipp Cannon Date: Sun, 21 Jun 2009 12:27:37 +0200 Subject: [PATCH] audiotestsrc: Add support for generating gaussian white noise This patch adds support for stationary white Gaussian noise. The Box-Muller algorithm is used to generate pairs of independent normally-distributed random numbers. Fixes bug #586519. --- gst/audiotestsrc/gstaudiotestsrc.c | 45 +++++++++++++++++++++++++++++- gst/audiotestsrc/gstaudiotestsrc.h | 6 ++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/gst/audiotestsrc/gstaudiotestsrc.c b/gst/audiotestsrc/gstaudiotestsrc.c index ca77237ea3..32cb272075 100644 --- a/gst/audiotestsrc/gstaudiotestsrc.c +++ b/gst/audiotestsrc/gstaudiotestsrc.c @@ -130,10 +130,12 @@ gst_audiostestsrc_wave_get_type (void) {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"}, {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"}, {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"}, - {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White noise", "white-noise"}, + {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"}, {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"}, {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"}, {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"}, + {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise", + "gaussian"}, {0, NULL, NULL}, }; @@ -780,6 +782,44 @@ static ProcessFunc tick_funcs[] = { (ProcessFunc) gst_audio_test_src_create_tick_double }; +/* Gaussian white noise using Box-Muller algorithm. unit variance + * normally-distributed random numbers are generated in pairs as the real + * and imaginary parts of a compex random variable with + * uniformly-distributed argument and \chi^{2}-distributed modulus. + */ + +#define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \ +static void \ +gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble amp = (src->volume * scale); \ + \ + 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); \ + \ + samples[i++] = (g##type) (amp * mag * cos (phs)); \ + if (++c >= src->channels) \ + break; \ + samples[i++] = (g##type) (amp * mag * sin (phs)); \ + } \ + } \ +} + +DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0); +DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0); +DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0); +DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0); + +static ProcessFunc gaussian_white_noise_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double +}; + /* * gst_audio_test_src_change_wave: * Assign function pointer of wave genrator. @@ -823,6 +863,9 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src) gst_audio_test_src_init_sine_table (src); src->process = tick_funcs[src->format]; break; + case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: + src->process = gaussian_white_noise_funcs[src->format]; + break; default: GST_ERROR ("invalid wave-form"); break; diff --git a/gst/audiotestsrc/gstaudiotestsrc.h b/gst/audiotestsrc/gstaudiotestsrc.h index 60fbd9f9c7..69f73eda66 100644 --- a/gst/audiotestsrc/gstaudiotestsrc.h +++ b/gst/audiotestsrc/gstaudiotestsrc.h @@ -45,10 +45,11 @@ G_BEGIN_DECLS * @GST_AUDIO_TEST_SRC_WAVE_SAW: a saw wave * @GST_AUDIO_TEST_SRC_WAVE_TRIANGLE: a tringle wave * @GST_AUDIO_TEST_SRC_WAVE_SILENCE: silence - * @GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: white noise + * @GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: white uniform noise * @GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE: pink noise * @GST_AUDIO_TEST_SRC_WAVE_SINE_TAB: sine wave using a table * @GST_AUDIO_TEST_SRC_WAVE_TICKS: periodic ticks + * @GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: white (zero mean) Gaussian noise; volume sets the standard deviation of the noise in units of the range of values of the sample type, e.g. volume=0.1 produces noise with a standard deviation of 0.1*32767=3277 with 16-bit integer samples, or 0.1*1.0=0.1 with floating-point samples. * * Different types of supported sound waves. */ @@ -61,7 +62,8 @@ typedef enum { GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, - GST_AUDIO_TEST_SRC_WAVE_TICKS + GST_AUDIO_TEST_SRC_WAVE_TICKS, + GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE } GstAudioTestSrcWave; #define PINK_MAX_RANDOM_ROWS (30)