aboutsummaryrefslogtreecommitdiff
path: root/speaker-test/pink.c
diff options
context:
space:
mode:
Diffstat (limited to 'speaker-test/pink.c')
-rw-r--r--speaker-test/pink.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/speaker-test/pink.c b/speaker-test/pink.c
new file mode 100644
index 0000000..ef30755
--- /dev/null
+++ b/speaker-test/pink.c
@@ -0,0 +1,96 @@
+/*
+ patest_pink.c
+
+ generate Pink Noise using Gardner method.
+ Optimization suggested by James McCartney uses a tree
+ to select which random value to replace.
+
+ x x x x x x x x x x x x x x x x
+ x x x x x x x x
+ x x x x
+ x x
+ x
+
+ Tree is generated by counting trailing zeros in an increasing index.
+ When the index is zero, no random number is selected.
+
+ This program uses the Portable Audio library which is under development.
+ For more information see: http://www.audiomulch.com/portaudio/
+
+ Author: Phil Burk, http://www.softsynth.com
+
+ Revision History:
+
+ Copyleft 1999 Phil Burk - No rights reserved.
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "pink.h"
+
+/************************************************************/
+/* Calculate pseudo-random 32 bit number based on linear congruential method. */
+static unsigned long generate_random_number( void )
+{
+ static unsigned long rand_seed = 22222; /* Change this for different random sequences. */
+ rand_seed = (rand_seed * 196314165) + 907633515;
+ return rand_seed;
+}
+
+/* Setup PinkNoise structure for N rows of generators. */
+void initialize_pink_noise( pink_noise_t *pink, int num_rows )
+{
+ int i;
+ long pmax;
+ pink->pink_index = 0;
+ pink->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));
+ pink->pink_scalar = 1.0f / pmax;
+/* Initialize rows. */
+ for( i=0; i<num_rows; i++ ) pink->pink_rows[i] = 0;
+ pink->pink_running_sum = 0;
+}
+
+/* generate Pink noise values between -1.0 and +1.0 */
+float generate_pink_noise_sample( pink_noise_t *pink )
+{
+ long new_random;
+ long sum;
+ float output;
+
+/* Increment and mask index. */
+ pink->pink_index = (pink->pink_index + 1) & pink->pink_index_mask;
+
+/* If index is zero, don't update any random values. */
+ if( pink->pink_index != 0 )
+ {
+ /* Determine how many trailing zeros in PinkIndex. */
+ /* This algorithm will hang if n==0 so test first. */
+ int num_zeros = 0;
+ int n = pink->pink_index;
+ while( (n & 1) == 0 )
+ {
+ n = n >> 1;
+ num_zeros++;
+ }
+
+ /* Replace the indexed ROWS random value.
+ * Subtract and add back to Running_sum instead of adding all the random
+ * values together. Only one changes each time.
+ */
+ pink->pink_running_sum -= pink->pink_rows[num_zeros];
+ new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
+ pink->pink_running_sum += new_random;
+ pink->pink_rows[num_zeros] = new_random;
+ }
+
+/* Add extra white noise value. */
+ new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
+ sum = pink->pink_running_sum + new_random;
+
+/* Scale to range of -1.0 to 0.9999. */
+ output = pink->pink_scalar * sum;
+
+ return output;
+}