MythTV  master
pink.cpp
Go to the documentation of this file.
1 /*
2  patest_pink.c
3 
4  generate Pink Noise using Gardner method.
5  Optimization suggested by James McCartney uses a tree
6  to select which random value to replace.
7 
8  x x x x x x x x x x x x x x x x
9  x x x x x x x x
10  x x x x
11  x x
12  x
13 
14  Tree is generated by counting trailing zeros in an increasing index.
15  When the index is zero, no random number is selected.
16 
17  This program uses the Portable Audio library which is under development.
18  For more information see: http://www.audiomulch.com/portaudio/
19 
20  Author: Phil Burk, http://www.softsynth.com
21 
22  Revision History:
23 
24  Copyleft 1999 Phil Burk - No rights reserved.
25 */
26 
27 #include <cmath>
28 #include <cstdio>
29 #include "pink.h"
30 
31 /************************************************************/
32 /* Calculate pseudo-random 32 bit number based on linear congruential method. */
33 static uint32_t generate_random_number( void )
34 {
35  static uint32_t s_randSeed = 22222; /* Change this for different random sequences. */
36  s_randSeed = (s_randSeed * 196314165) + 907633515;
37  return s_randSeed;
38 }
39 
40 /* Setup PinkNoise structure for N rows of generators. */
41 void initialize_pink_noise( pink_noise_t *pink, int num_rows )
42 {
43  pink->pink_index = 0;
44  if (num_rows > PINK_MAX_RANDOM_ROWS)
45  num_rows = PINK_MAX_RANDOM_ROWS;
46  pink->pink_index_mask = (1ULL << num_rows) - 1;
47 /* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
48  int32_t pmax = (num_rows + 1) * (1<<(PINK_RANDOM_BITS-1));
49  pink->pink_scalar = 1.0F / pmax;
50 /* Initialize rows. */
51  pink->pink_rows.fill(0);
52  pink->pink_running_sum = 0;
53 }
54 
55 /* generate Pink noise values between -1.0 and +1.0 */
57 {
58 /* Increment and mask index. */
59  pink->pink_index = (pink->pink_index + 1) & pink->pink_index_mask;
60 
61 /* If index is zero, don't update any random values. */
62  if( pink->pink_index != 0 )
63  {
64  /* Determine how many trailing zeros in PinkIndex. */
65  /* This algorithm will hang if n==0 so test first. */
66  int num_zeros = 0;
67  int n = pink->pink_index;
68  while( (n & 1) == 0 )
69  {
70  n = n >> 1;
71  num_zeros++;
72  }
73 
74  /* Replace the indexed ROWS random value.
75  * Subtract and add back to Running_sum instead of adding all the random
76  * values together. Only one changes each time.
77  */
78  pink->pink_running_sum -= pink->pink_rows[num_zeros];
79  int32_t new_random = ((int32_t)generate_random_number()) >> PINK_RANDOM_SHIFT;
80  pink->pink_running_sum += new_random;
81  pink->pink_rows[num_zeros] = new_random;
82  }
83 
84 /* Add extra white noise value. */
85  int32_t new_random = ((int32_t)generate_random_number()) >> PINK_RANDOM_SHIFT;
86  int32_t sum = pink->pink_running_sum + new_random;
87 
88 /* Scale to range of -1.0 to 0.9999. */
89  float output = pink->pink_scalar * sum;
90 
91  return output;
92 }
PINK_RANDOM_BITS
static constexpr int8_t PINK_RANDOM_BITS
Definition: pink.h:9
pink.h
pink_noise_t::pink_index_mask
int32_t pink_index_mask
Definition: pink.h:17
PINK_MAX_RANDOM_ROWS
static constexpr int8_t PINK_MAX_RANDOM_ROWS
Definition: pink.h:8
PINK_RANDOM_SHIFT
static constexpr int8_t PINK_RANDOM_SHIFT
Definition: pink.h:10
pink_noise_t::pink_running_sum
int32_t pink_running_sum
Definition: pink.h:15
initialize_pink_noise
void initialize_pink_noise(pink_noise_t *pink, int num_rows)
Definition: pink.cpp:41
pink_noise_t::pink_index
int32_t pink_index
Definition: pink.h:16
pink_noise_t::pink_scalar
float pink_scalar
Definition: pink.h:18
generate_pink_noise_sample
float generate_pink_noise_sample(pink_noise_t *pink)
Definition: pink.cpp:56
pink_noise_t
Definition: pink.h:12
output
#define output
Definition: synaesthesia.cpp:220
generate_random_number
static uint32_t generate_random_number(void)
Definition: pink.cpp:33
pink_noise_t::pink_rows
std::array< int32_t, PINK_MAX_RANDOM_ROWS > pink_rows
Definition: pink.h:14