MythTV  0.26-pre
pink.c
Go to the documentation of this file.
00001 /*
00002   patest_pink.c
00003 
00004   generate Pink Noise using Gardner method.
00005   Optimization suggested by James McCartney uses a tree
00006   to select which random value to replace.
00007 
00008   x x x x x x x x x x x x x x x x 
00009   x   x   x   x   x   x   x   x   
00010   x       x       x       x       
00011   x               x               
00012   x                               
00013 
00014   Tree is generated by counting trailing zeros in an increasing index.
00015   When the index is zero, no random number is selected.
00016 
00017   This program uses the Portable Audio library which is under development.
00018   For more information see:   http://www.audiomulch.com/portaudio/
00019 
00020   Author: Phil Burk, http://www.softsynth.com
00021         
00022   Revision History:
00023 
00024   Copyleft 1999 Phil Burk - No rights reserved.
00025 */
00026 
00027 #include <stdio.h>
00028 #include <math.h>
00029 #include "pink.h"
00030 
00031 /************************************************************/
00032 /* Calculate pseudo-random 32 bit number based on linear congruential method. */
00033 static unsigned long generate_random_number( void )
00034 {
00035     static unsigned long rand_seed = 22222;  /* Change this for different random sequences. */
00036     rand_seed = (rand_seed * 196314165) + 907633515;
00037     return rand_seed;
00038 }
00039 
00040 /* Setup PinkNoise structure for N rows of generators. */
00041 void initialize_pink_noise( pink_noise_t *pink, int num_rows )
00042 {
00043     int i;
00044     long pmax;
00045     pink->pink_index = 0;
00046     pink->pink_index_mask = (1<<num_rows) - 1;
00047 /* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
00048     pmax = (num_rows + 1) * (1<<(PINK_RANDOM_BITS-1));
00049     pink->pink_scalar = 1.0f / pmax;
00050 /* Initialize rows. */
00051     for( i=0; i<num_rows; i++ ) pink->pink_rows[i] = 0;
00052     pink->pink_running_sum = 0;
00053 }
00054 
00055 /* generate Pink noise values between -1.0 and +1.0 */
00056 float generate_pink_noise_sample( pink_noise_t *pink )
00057 {
00058     long new_random;
00059     long sum;
00060     float output;
00061 
00062 /* Increment and mask index. */
00063     pink->pink_index = (pink->pink_index + 1) & pink->pink_index_mask;
00064 
00065 /* If index is zero, don't update any random values. */
00066     if( pink->pink_index != 0 )
00067     {
00068         /* Determine how many trailing zeros in PinkIndex. */
00069         /* This algorithm will hang if n==0 so test first. */
00070         int num_zeros = 0;
00071         int n = pink->pink_index;
00072         while( (n & 1) == 0 )
00073         {
00074             n = n >> 1;
00075             num_zeros++;
00076         }
00077 
00078         /* Replace the indexed ROWS random value.
00079          * Subtract and add back to Running_sum instead of adding all the random
00080          * values together. Only one changes each time.
00081          */
00082         pink->pink_running_sum -= pink->pink_rows[num_zeros];
00083         new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
00084         pink->pink_running_sum += new_random;
00085         pink->pink_rows[num_zeros] = new_random;
00086     }
00087         
00088 /* Add extra white noise value. */
00089     new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
00090     sum = pink->pink_running_sum + new_random;
00091 
00092 /* Scale to range of -1.0 to 0.9999. */
00093     output = pink->pink_scalar * sum;
00094 
00095     return output;
00096 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends