From 7f3f034d44d46b27ddb15d5a7c115d2aaccce826 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Sun, 9 Oct 2005 20:47:31 +0000 Subject: [PATCH] gst/audiotestsrc/gstaudiotestsrc.*: fixed typo, added pink noise Original commit message from CVS: * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audiostestsrc_wave_get_type), (gst_audiotestsrc_class_init), (gst_audiotestsrc_init), (gst_audiotestsrc_create_sine), (gst_audiotestsrc_create_square), (gst_audiotestsrc_create_saw), (gst_audiotestsrc_create_triangle), (gst_audiotestsrc_create_silence), (gst_audiotestsrc_create_white_noise), (gst_audiotestsrc_init_pink_noise), (gst_audiotestsrc_generate_pink_noise_value), (gst_audiotestsrc_create_pink_noise), (gst_audiotestsrc_change_wave): * gst/audiotestsrc/gstaudiotestsrc.h: fixed typo, added pink noise --- ChangeLog | 16 ++++++ gst/audiotestsrc/gstaudiotestsrc.c | 87 +++++++++++++++++++++++++++++- gst/audiotestsrc/gstaudiotestsrc.h | 21 +++++++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f25fbe85d4..bcc104fcb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2005-10-09 Stefan Kost + + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audiostestsrc_wave_get_type), (gst_audiotestsrc_class_init), + (gst_audiotestsrc_init), (gst_audiotestsrc_create_sine), + (gst_audiotestsrc_create_square), (gst_audiotestsrc_create_saw), + (gst_audiotestsrc_create_triangle), + (gst_audiotestsrc_create_silence), + (gst_audiotestsrc_create_white_noise), + (gst_audiotestsrc_init_pink_noise), + (gst_audiotestsrc_generate_pink_noise_value), + (gst_audiotestsrc_create_pink_noise), + (gst_audiotestsrc_change_wave): + * gst/audiotestsrc/gstaudiotestsrc.h: + fixed typo, added pink noise + 2005-10-09 Tim-Philipp Müller * gst/typefind/gsttypefindfunctions.c: (wavpack_type_find), diff --git a/gst/audiotestsrc/gstaudiotestsrc.c b/gst/audiotestsrc/gstaudiotestsrc.c index 3b41ceb623..06a3e9a3fe 100644 --- a/gst/audiotestsrc/gstaudiotestsrc.c +++ b/gst/audiotestsrc/gstaudiotestsrc.c @@ -96,9 +96,10 @@ gst_audiostestsrc_wave_get_type (void) {GST_AUDIOTESTSRC_WAVE_SINE, "0", "Sine"}, {GST_AUDIOTESTSRC_WAVE_SQUARE, "1", "Square"}, {GST_AUDIOTESTSRC_WAVE_SAW, "2", "Saw"}, - {GST_AUDIOTESTSRC_WAVE_TRIANGLE, "3", "Trinagle"}, + {GST_AUDIOTESTSRC_WAVE_TRIANGLE, "3", "Triangle"}, {GST_AUDIOTESTSRC_WAVE_SILENCE, "4", "Silence"}, {GST_AUDIOTESTSRC_WAVE_WHITE_NOISE, "5", "White noise"}, + {GST_AUDIOTESTSRC_WAVE_PINK_NOISE, "6", "Pink noise"}, {0, NULL, NULL}, }; @@ -421,6 +422,86 @@ gst_audiotestsrc_create_white_noise (GstAudioTestSrc * src, gint16 * samples) } } +/* pink noise calculation is based on + * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c + * which has been released under public domain + * Many thanks Phil! + */ +static void +gst_audiotestsrc_init_pink_noise (GstAudioTestSrc * src) +{ + gint i; + gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */ + glong pmax; + + src->pink.index = 0; + src->pink.index_mask = (1 << num_rows) - 1; + /* calculate maximum possible signed random value. + * Extra 1 for white noise always added. */ + pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1)); + src->pink.scalar = 1.0f / pmax; + /* Initialize rows. */ + for (i = 0; i < num_rows; i++) + src->pink.rows[i] = 0; + src->pink.running_sum = 0; +} + +/* Generate Pink noise values between -1.0 and +1.0 */ +static gfloat +gst_audiotestsrc_generate_pink_noise_value (GstPinkNoise * pink) +{ + glong new_random; + glong sum; + + /* Increment and mask index. */ + pink->index = (pink->index + 1) & pink->index_mask; + + /* If index is zero, don't update any random values. */ + if (pink->index != 0) { + /* Determine how many trailing zeros in PinkIndex. */ + /* This algorithm will hang if n==0 so test first. */ + gint num_zeros = 0; + gint n = pink->index; + + while ((n & 1) == 0) { + n = n >> 1; + num_zeros++; + } + + /* Replace the indexed ROWS random value. + * Subtract and add back to RunningSum instead of adding all the random + * values together. Only one changes each time. + */ + pink->running_sum -= pink->rows[num_zeros]; + //new_random = ((glong)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT; + new_random = 32768.0 - (65536.0 * (gulong) rand () / (RAND_MAX + 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)); + sum = pink->running_sum + new_random; + + /* Scale to range of -1.0 to 0.9999. */ + return (pink->scalar * sum); +} + +static void +gst_audiotestsrc_create_pink_noise (GstAudioTestSrc * src, gint16 * samples) +{ + gint i; + gdouble amp; + + amp = src->volume * 32767.0; + + for (i = 0; i < src->samples_per_buffer; i++) { + samples[i] = + (gint16) (gst_audiotestsrc_generate_pink_noise_value (&src->pink) * + amp); + } +} + static void gst_audiotestsrc_change_wave (GstAudioTestSrc * src) { @@ -443,6 +524,10 @@ gst_audiotestsrc_change_wave (GstAudioTestSrc * src) case GST_AUDIOTESTSRC_WAVE_WHITE_NOISE: src->process = gst_audiotestsrc_create_white_noise; break; + case GST_AUDIOTESTSRC_WAVE_PINK_NOISE: + gst_audiotestsrc_init_pink_noise (src); + src->process = gst_audiotestsrc_create_pink_noise; + break; default: GST_ERROR ("invalid wave-form"); break; diff --git a/gst/audiotestsrc/gstaudiotestsrc.h b/gst/audiotestsrc/gstaudiotestsrc.h index 09a67b4460..7d34d6c0c0 100644 --- a/gst/audiotestsrc/gstaudiotestsrc.h +++ b/gst/audiotestsrc/gstaudiotestsrc.h @@ -49,8 +49,21 @@ typedef enum { GST_AUDIOTESTSRC_WAVE_TRIANGLE, GST_AUDIOTESTSRC_WAVE_SILENCE, GST_AUDIOTESTSRC_WAVE_WHITE_NOISE, + GST_AUDIOTESTSRC_WAVE_PINK_NOISE, } GstAudioTestSrcWaves; +#define PINK_MAX_RANDOM_ROWS (30) +#define PINK_RANDOM_BITS (16) +#define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS) + +typedef struct { + glong rows[PINK_MAX_RANDOM_ROWS]; + glong running_sum; /* Used to optimize summing of generators. */ + gint index; /* Incremented each sample. */ + gint index_mask; /* Index wrapped by ANDing with this mask. */ + gfloat scalar; /* Used to scale within range of -1.0 to +1.0 */ +} GstPinkNoise; + typedef struct _GstAudioTestSrc GstAudioTestSrc; typedef struct _GstAudioTestSrcClass GstAudioTestSrcClass; @@ -63,7 +76,7 @@ struct _GstAudioTestSrc { GstAudioTestSrcWaves wave; gdouble volume; gdouble freq; - + /* audio parameters */ gint samplerate; @@ -78,6 +91,11 @@ struct _GstAudioTestSrc { GstClockID clock_id; GstClockTimeDiff timestamp_offset; + + /* < private > */ + + /* waveform specific context data */ + GstPinkNoise pink; }; struct _GstAudioTestSrcClass { @@ -89,5 +107,4 @@ gboolean gst_audiotestsrc_factory_init (GstElementFactory *factory); G_END_DECLS - #endif /* __GST_AUDIOTESTSRC_H__ */