Blame speaker-test/pink.c

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