Author 
Message 
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Thu Jan 31, 2008 1:41 pm Post subject:
Pink Noise Subject description: 1/f with ChucK 


Because Pink Noise is cool here's a patch:
Code:  //White noise => pinking_filter == Pink noise => dac;
Noise n => Gain in;
Gain out => dac;
PoleZero pz[16]; //The number controls the quality of the filter. Bigger ones bring out the lower frequencies.
for(0 => int i; i < pz.cap(); i++){
1.0 => pz[i].b0;
Math.pow(2.0,i + 1.0 pz.cap())1.0 => pz[i].a1;
Math.pow(2.0,i +1.5 pz.cap())1.0 => pz[i].b1;
}
in => pz[0];
for(1 => int i; i < pz.cap(); i++) pz[i1] => pz[i];
pz[pz.cap()1] => out;
0.2 => out.gain;
//for(now + second => time later; now < later; 10::ms => now);
second => now; 
I'm not sure if it's exactly pink. But the spectrum is a straight line when viewed in logfrequency.
It's not white. It's not brown. At least it's pinkish.
If you know a better way to make pink noise. Post away! _________________ To boldly go where no man has bothered to go before. 

Back to top



Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 5978 Location: San Antonio, Tx, USA
Audio files: 258

Posted: Thu Jan 31, 2008 2:07 pm Post subject:



Well, got this from the Wikipedia entry on pink noise, for what its worth:
There are no simple mathematical models to create pink noise. It is usually generated by filtering white noise. 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Fri Feb 01, 2008 5:17 am Post subject:



Another approach to a pinking filter:
This one doesn't cut off the lowest frequencies so it might be useful as a control signal. Because the "DC" component is not cut off the sound will clip at some point. Apply DC blocking as needed.
Code:  //Generating pink noise by integrating blue noise
//By: Pyry Pakkanen ( 2008 )
//Released under GNU GPL v3
//First the half derivate of white noise is taken (blue noise)
//then it's itegrated (browned) to get pink noise. (minus one halfth derivate of white noise)
//Don't ask me to prove this but I think that convolving a signal with the
//taylor series coefficients of (1x)^n returns the n'th derivate of the signal
//Don't ask me to prove either that pink noise is actually the 0.5th derivate of white noise. :)
float coeff[16]; //Quality of the half derivate approximation
//Get the taylor series of sqrt(1 + x)
binomial_series(1.0,0.5,coeff);
//Reverse odd coefficients to get the series for sqrt(1  x)
for(1 => int i; i < coeff.cap(); i + 2 => i) coeff[i] => coeff[i];
//for(0 => int i; i < coeff.cap(); i++)<<<coeff[i]>>>;
Noise white_noise => Gain noise_in;
Gain noise_out;
convolve(noise_in,noise_out,coeff);
noise_out => OnePole browner => dac;
0.01 => browner.b0;
1.0 => browner.a1;
10::second => now;
//Simple FIR filter
fun void convolve(Gain @ in, Gain @ out, float b[]){
Delay d[b.cap()];
for(0 => int i; i < b.cap(); i++){
in => d[i] => out;
i::samp => d[i].delay;
b[i] => d[i].gain;
}
}
//Generate the taylor series coefficients of (a+x)^n
fun void binomial_series(float a,float n,float coeff[]){
Math.pow(a,n) => float c;
for(0 => int i; i < coeff.cap(); i++){
c => coeff[i];
(ni$float)/(i$float+1.0)/a *=> c;
}
} 
_________________ To boldly go where no man has bothered to go before. 

Back to top



kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4

Posted: Sat Mar 08, 2008 9:39 am Post subject:



I'm not that good in this kind of physicsmathematics theory..
so here I come:
If it's hard to generate pink noise directly,
is it easier to come up with a physical model to simulate the behavior of a pink noise?
(that maybe later used as a filter or by any other kind of triggering methods) 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sat Mar 08, 2008 11:01 am Post subject:



kijjaz wrote:  If it's hard to generate pink noise directly,
is it easier to come up with a physical model to simulate the behavior of a pink noise? 
The physical theory of pink noise suggests that it is produced by a great number of oscillators. Energy of an oscillator is inversely porportional to the square of it's "size" but if these oscillators are distributed naturally so that there are a lot of tiny ones compared to the big oscillators it turns out that the energy on a given frequency band is then only inversely porportional to the frequency of that band. And because there are so many of oscillators, no individual vibration can be heard from the cacophony => 1/f noise.
So the model would be tens of thousands of SinOscs arranged naturally by frequency and amplitude.
More accurate model would be a physical simulation that takes virtual sound producing balls and puts them in to big virtual bucket. Shake things around until equilibrium is reached and render the sound.
So in conclusion: Code:  SinOsc oscillator[10000] > pink_filter_of_order_100; 
The answer is no.
Sorry, simulating statistical physics with accurate physical models is often infeasible.
And if you drop the physical accuracy of the model it's better to think it only as a mathematical model. _________________ To boldly go where no man has bothered to go before. 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sat Mar 08, 2008 4:40 pm Post subject:



Well that model of multiple oscillators got me thinking...
...IFFT can be seen as the big collection of sinusoid oscillators. The problem is that to get true pink noise out from an IFFT it's size needs to the same as the length of the resulting audio sample. So I take the same detour as I did in the previous post; First generate blue noise and then integrate it. This creates the pink random walk that is more gentle than the brownian motion you get from integrated white noise.
Code:  IFFT ifft => OnePole integrator => dac;
1.0 => integrator.a1;
samp/second => integrator.b0;
256 => ifft.size;
Windowing.hamming(ifft.size()) => ifft.window;
0.25 => float hopSize;
2.0*hopSize => ifft.gain;
dur hop;
complex s[ifft.size()/2];
while(true){
for(1.0 => float h; h < s.cap(); 1.0 +=> h){
( %( /*blue*/ Math.pow(h,0.5) /*blue*/ *10.0 ,pi*Std.randf() )$complex ) => s[h$int];
}
ifft.transform( s );
hopSize*ifft.size()::samp => hop;
hop => now;
} 
If you remove the OnePole integrator and replace the /*blue*/ part with Math.pow(h,0.5) you'll get DC blocked pink noise straight out of the IFFT. _________________ To boldly go where no man has bothered to go before. 

Back to top



kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4

Posted: Sun Mar 09, 2008 6:04 am Post subject:



Wow.. this is mathemagical!
I think about statistics and simulation now, ..
can we kinda ... generate pseudorandom numbers but with some characteristic in the movement of the data that would be close to Pink Noise?
I'm not a very math guy, just curious hahahha...
Thanks, Frostburn. this thread is inspiring. 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sun Mar 09, 2008 6:52 am Post subject:



kijjaz wrote:  can we kinda ... generate pseudorandom numbers but with some characteristic in the movement of the data that would be close to Pink Noise? 
Well you can chuck the pink noise generating IFFTOnePole patch in to a blackhole and just use integrator.last() to get random numbers with pink movement.
If you mean a random number generator that could be used like Std.randf() then the half derivating FIR filter that I posted can be turned in to a class that doesn't need to be ticked by a blackhole. All you need is a float array to hold concecutive (white) random numbers. A blue convolution table and one float to hold the previous value generated so that the blue noise can be integrated.
Another method involves adding together the output of many random number generators that run at different frequencies and are scaled accordingly. _________________ To boldly go where no man has bothered to go before. 

Back to top



Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3

Posted: Sun Mar 09, 2008 10:58 am Post subject:



Frostburn wrote: 
Well you can chuck the pink noise generating IFFTOnePole patch in to a blackhole and just use integrator.last() to get random numbers with pink movement.

Are you sure about this? Say that instead of that construction I'd use a saw wave's .last() yet poll it at random moment. There it's clear the distribution of the numbers will depend entirely on the timing of my calls, right? I'm not sure the method you propose here can be guaranteed to have any kind of distribution if you don't say anything about the timing of the calls.
Another option would be to use LiSa as a FIR filter by having her start a voice at every sample with the amplitude of Noise's last sample. Assuming we could get a impulse responce of a pinking filter that should create perfect pink noise though the price is obviously a rather high CPU cost. _________________ Kassen 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sun Mar 09, 2008 11:44 am Post subject:



Kassen wrote:  Are you sure about this? Say that instead of that construction I'd use a saw wave's .last() yet poll it at random moment. There it's clear the distribution of the numbers will depend entirely on the timing of my calls, right? I'm not sure the method you propose here can be guaranteed to have any kind of distribution if you don't say anything about the timing of the calls. 
You're right Kassen, I should have been more clear on how to use the ifft. Naturally if you don't use all the data you get from the ifft and use it in that order you won't get a pink distribution.
So the ifft doesn't make for a very flexible RNG because you have to buffer everything you're going to need later. And if you need a lot of pink random numbers at the beginning of your song you're at a loss. _________________ To boldly go where no man has bothered to go before. 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sun Mar 09, 2008 12:30 pm Post subject:



Code:  class ColorRNG {
16 => int order; //Quality of the fractional derivate approximation
float coeff[]; //Binomial coefficients
float buffer[]; //Buffer for the FIR filter that does the fractional derivation
0.5 => float color; //0.0 = brown(red), 1.0 = white, defaults to pink = 0.5
0.0 => float last; //The last number generated, needed for integration
0.05 => float stepSize; //Integration step size
//Generate the next random number
fun float next(){
0.0 => float val;
for(0 => int i; i < order; i++){
buffer[i]*coeff[order1i] +=> val; //Convolve the FIR's impulse response with the buffer to get the fractional derivate
if( i < order1) buffer[i+1] => buffer[i];
else Std.randf() => buffer[i]; //add a new sample
}
return val*stepSize +=> last;
}
//Use this to change the color parameter
fun float setColor(float value){
value => color;
update_fir();
}
//Remember to initialize the instance before using it
fun void init(){ init(order); }
fun void init(int _order){
_order => order;
new float[order] @=> coeff;
new float[order] @=> buffer;
for(0 => int i; i < buffer.cap(); i++) Std.randf() => buffer[i]; //Fill her up with noise
update_fir();
}
//Generate the taylor series coefficients of (a+x)^n
fun void binomial_series(float a,float n,float coeff[]){
Math.pow(a,n) => float c;
for(0 => int i; i < coeff.cap(); i++){
c => coeff[i];
(ni$float)/(i$float+1.0)/a *=> c;
}
}
fun void update_fir(){
//Get the taylor series of Math.pow(1 + x,color)
binomial_series(1.0,color,coeff);
//Reverse odd coefficients to get the series for Math.pow(1  x,color)
for(1 => int i; i < coeff.cap(); i + 2 => i) coeff[i] => coeff[i];
}
}
ColorRNG randy;
randy.init(128); //Initialize and set the internal filter to have an order of 128
1.0 => randy.stepSize; //Spice things up a bit
0.5 => randy.setColor; //Pink
//Print out some random numbers with pink distribution
for(0 => int i; i < 10; i++) <<<randy.next()>>>; //Well ok you cannot actually tell from only 10 samples of noise. 
_________________ To boldly go where no man has bothered to go before. 

Back to top



Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3

Posted: Sun Mar 09, 2008 3:30 pm Post subject:



Another aspect is that with IFFT you would need to randomise the phase or the resulting values will be deterministic (like "pink" without "noise" :¬) ).
I think, BTW, that "pink" is a property of noise in therms of frequency. If you you are more interested in a series of random numbers the stochastic distribution they have will probably be more relevant. There's a good article in the Csound book on creating series of random numbers with various kinds of distributions. I could look it up for you later if you have specific interests? _________________ Kassen 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Mon Mar 10, 2008 12:18 am Post subject:



Kassen wrote:  Another aspect is that with IFFT you would need to randomise the phase or the resulting values will be deterministic (like "pink" without "noise" :¬) ). 
Yes the phase randomization is a must but it'll still be deterministic because all random number generators in home computers are pseudo random, they're just seeded with a value from the system clock or something so that you don't always get the same sequence.
You'd need one of those fancy quantum random number generators to get truly random sequences.
Or you could just plug some electronic device to the microphone port and record the noise it produces, it usually has a pink distribution.
EDIT:
Kassen wrote:  I think, BTW, that "pink" is a property of noise in therms of frequency. If you you are more interested in a series of random numbers the stochastic distribution they have will probably be more relevant. There's a good article in the Csound book on creating series of random numbers with various kinds of distributions. I could look it up for you later if you have specific interests? 
You're right. The color of the noise has to do with scale, both time and spatial scale. Or to put it in another way, frequency and the weight of those frequencies.
To preserve the color of the sequence you need to use the random values in the specific order they were generated.
I used the term "distribution" in the wrong place in my code comments. It has to do with how the individual values relate to each other without respect to generation order.
A random sequence can have pretty much any distribution and still be white in the spectrum. I'm not sure if it's generally true but I think that distribution and color are pretty much independant properties of random sequences. _________________ To boldly go where no man has bothered to go before. 

Back to top



Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3

Posted: Mon Mar 10, 2008 5:01 pm Post subject:



Frostburn wrote:  I'm not sure if it's generally true but I think that distribution and color are pretty much independant properties of random sequences. 
I was just wondering about that as well. Wouldn't like to have to deliver proof on this as that's well out of my range :¬)
I do suspect you can say that for two successive samples the delta will tend to be higher in white then in pink noise but beyond that.... Hard stuff. _________________ Kassen 

Back to top



wppk
Joined: Jan 25, 2008 Posts: 31 Location: Los Angeles

Posted: Wed Mar 12, 2008 1:29 pm Post subject:
Make use of that Pink noise. 


Here's a simple Binaural Beat generator to throw under your Pink Noise.
Entrain your Brain.
Code:  fun void beatgen( float base, float beat, float gain, int minutes){
beat/2 => float half;
base + half => float freq1;
base  half => float freq2;
SinOsc s1 => dac.left;
SinOsc s2 => dac.right;
freq1 => s1.freq;
freq2 => s2.freq;
minutes::minute => now;
} 


Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Wed Mar 12, 2008 1:38 pm Post subject:



Ahh the good old binaural beats.
I used to play with them couple of years ago, fun things.
Hmm... I just figured out how to do free (enharmonic) additive synthesis with IFFT. Maybe it could be used to enhance the entrainment... well at least get the same effect with more expressive instruments than just sine beeps.
EDIT: And the verdict is: It works!
Replacing sinewave partials with binaural beating sinewave partials creates a perceivable binaural beat while keeping the waveform intact on both channels.
It even works through melodies with a sawtooth wave. Time to go all binaural on the brain. _________________ To boldly go where no man has bothered to go before. 

Back to top



Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9

Posted: Sun Mar 16, 2008 1:42 am Post subject:



Why use pink noise only as a background for binaural sinewaves when you can make the noise itself do the beating.
The following piece of code sounds quite nauseating because it messes with the sense of sound localisation.
I take no responsibility for any damages it may cause.
Use at your own risk!
Code:  //Binaural beating pink noise
//Use at your own risk. The author takes no responsibility of it's effects.
//Choose your beating frequency
16.0 => float binauralBeat;
//
IFFT ifft[2];
ifft[0] => dac.left;
ifft[1] => dac.right;
256 => ifft[0].size => ifft[1].size;
4 => int overlap;
Windowing.triangle(2*ifft[0].size()/overlap) => ifft[0].window => ifft[1].window;
complex s[2][ifft[0].size()/2];
dur hop;
polar tmp;
0.0 => float binauralPhase;
while(true){
for(1.0 => float h; h < s[0].cap(); 1.0 +=> h){
%( Math.pow(h,0.5) ,pi*Std.randf() ) => tmp; //This is the pink part
( tmp * %(0.05,binauralPhase) )$complex => s[0][h$int]; //Shift the left channel
( tmp * %(0.05,binauralPhase) )$complex => s[1][h$int]; //and the right channel in phase. (also scale them by 0.05)
}
ifft[0].transform( s[0] );
ifft[1].transform( s[1] );
(ifft[0].size()/overlap)::samp => hop;
binauralBeat*pi*hop/second +=> binauralPhase; //Accumulate the phase shift
hop => now;
} 
_________________ To boldly go where no man has bothered to go before. 

Back to top



