mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-14 05:25:43 +01:00
97 lines
2.8 KiB
C
97 lines
2.8 KiB
C
|
/*
|
||
|
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;
|
||
|
}
|