gst/audiotestsrc/gstaudiotestsrc.*: fixed typo, added pink noise
authorStefan Kost <ensonic@users.sourceforge.net>
Sun, 9 Oct 2005 20:47:31 +0000 (20:47 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Sun, 9 Oct 2005 20:47:31 +0000 (20:47 +0000)
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
gst/audiotestsrc/gstaudiotestsrc.c
gst/audiotestsrc/gstaudiotestsrc.h

index f25fbe8..bcc104f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-10-09  Stefan Kost  <ensonic@users.sf.net>
+
+       * 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  <tim at centricular dot net>
 
        * gst/typefind/gsttypefindfunctions.c: (wavpack_type_find),
index 3b41ceb..06a3e9a 100644 (file)
@@ -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;
index 09a67b4..7d34d6c 100644 (file)
@@ -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__ */