audiotestsrc: add red (brownian) noise generator
authorStefan Kost <ensonic@users.sf.net>
Wed, 25 May 2011 20:40:26 +0000 (23:40 +0300)
committerStefan Kost <ensonic@users.sf.net>
Wed, 25 May 2011 20:43:56 +0000 (23:43 +0300)
Add another noise generator which produces a quite dark noise color.

Fixes parts of #649969.

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

index ecbb2fb..1570c59 100644 (file)
@@ -130,6 +130,7 @@ gst_audiostestsrc_wave_get_type (void)
     {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
     {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
         "gaussian-noise"},
+    {GST_AUDIO_TEST_SRC_WAVE_RED_NOISE, "Red (brownian) noise", "red-noise"},
     {0, NULL, NULL},
   };
 
@@ -837,6 +838,49 @@ static const ProcessFunc gaussian_white_noise_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
 };
 
+/* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
+ * octave with increasing frequency
+ *
+ * taken from http://vellocet.com/dsp/noise/VRand.html
+ * by Andrew Simper of Vellocet (andy@vellocet.com)
+ */
+
+#define DEFINE_RED_NOISE(type,scale) \
+static void \
+gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
+{ \
+  gint i, c; \
+  gdouble amp = (src->volume * scale); \
+  gdouble state = src->red.state; \
+  \
+  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
+    for (c = 0; c < src->channels; ++c) { \
+      while (TRUE) { \
+        gdouble  r = g_rand_double_range (src->gen, -1.0, 1.0); \
+        state += r; \
+        if (state<-8.0f || state>8.0f) state -= r; \
+        else break; \
+      } \
+      samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
+    } \
+  } \
+  src->red.state = state; \
+}
+
+DEFINE_RED_NOISE (int16, 32767.0);
+DEFINE_RED_NOISE (int32, 2147483647.0);
+DEFINE_RED_NOISE (float, 1.0);
+DEFINE_RED_NOISE (double, 1.0);
+
+static const ProcessFunc red_noise_funcs[] = {
+  (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
+  (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
+  (ProcessFunc) gst_audio_test_src_create_red_noise_float,
+  (ProcessFunc) gst_audio_test_src_create_red_noise_double
+};
+
+
+
 /*
  * gst_audio_test_src_change_wave:
  * Assign function pointer of wave genrator.
@@ -889,6 +933,12 @@ gst_audio_test_src_change_wave (GstAudioTestSrc * src)
         src->gen = g_rand_new ();
       src->process = gaussian_white_noise_funcs[src->format];
       break;
+    case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
+      if (!(src->gen))
+        src->gen = g_rand_new ();
+      src->red.state = 0.0;
+      src->process = red_noise_funcs[src->format];
+      break;
     default:
       GST_ERROR ("invalid wave-form");
       break;
index 8c76594..971fe77 100644 (file)
@@ -50,6 +50,7 @@ G_BEGIN_DECLS
  * @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.
+ * @GST_AUDIO_TEST_SRC_WAVE_RED_NOISE: red (brownian) noise
  *
  * Different types of supported sound waves.
  */
@@ -63,8 +64,9 @@ typedef enum {
   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_GAUSSIAN_WHITE_NOISE
-} GstAudioTestSrcWave; 
+  GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE,
+  GST_AUDIO_TEST_SRC_WAVE_RED_NOISE
+} GstAudioTestSrcWave;
 
 #define PINK_MAX_RANDOM_ROWS   (30)
 #define PINK_RANDOM_BITS       (16)
@@ -78,6 +80,10 @@ typedef struct {
   gdouble    scalar;        /* Used to scale within range of -1.0 to +1.0 */
 } GstPinkNoise;
 
+typedef struct {
+  gdouble    state;         /* noise state */
+} GstRedNoise;
+
 typedef enum {
   GST_AUDIO_TEST_SRC_FORMAT_NONE = -1,
   GST_AUDIO_TEST_SRC_FORMAT_S16 = 0,
@@ -105,14 +111,14 @@ struct _GstAudioTestSrc {
   GstAudioTestSrcWave wave;
   gdouble volume;
   gdouble freq;
-    
+
   /* audio parameters */
   gint channels;
   gint samplerate;
   gint samples_per_buffer;
   gint sample_size;
   GstAudioTestSrcFormat format;
-  
+
   /*< private >*/
   gboolean tags_pushed;                        /* send tags just once ? */
   GstClockTimeDiff timestamp_offset;    /* base offset */
@@ -125,11 +131,12 @@ struct _GstAudioTestSrc {
   gint generate_samples_per_buffer;    /* used to generate a partial buffer */
   gboolean can_activate_pull;
   gboolean reverse;                  /* play backwards */
-  
+
   /* waveform specific context data */
   GRand *gen;               /* random number generator */
   gdouble accumulator;                 /* phase angle */
   GstPinkNoise pink;
+  GstRedNoise red;
   gdouble wave_table[1024];
 };