Discussion:
[music-dsp] Pink noise algorithm posted
RidgeRat
2006-03-26 22:48:21 UTC
Permalink
Hi group. I'm a recently signed newbie. After some advice from Douglas,
the friendly list admin, I have posted information about a possibly new
algorithm for direct digital synthesis of pink noise. (Otherwise, you
can tell me about my re-discovery.) You can find the full exposition at

http://home.earthlink.net/~ltrammell/tech/pinkalg.htm

A little background: When searching the web for a pink noise generator
method suitable for semi-automated loudspeaker or microphone testing, I
found the "Pink Noise page" at

http://www.firstpr.com.au/dsp/pink-noise/

My initial joy at learning about the Voss-McCartney algorithm there was
quickly damped when I found that I did not get good quality results from
it. This is illustrated in the web page. Further study led to some
insights, and from there variations that I believe are improvements,
which is why I am here, where the experts lurk.

To summarize the page briefly --

Abstract. The Voss-McCartney direct digital synthesis algorithm
generates a noise process approximating pink noise, from an
equally-weighted combination of random white noise sources, on a rigid
updating schedule. It is conjectured that the rigid periodicity of the
updating explains spectral artifacts that prevent the method from
converging uniformly to a good approximation of the desired 1/f power
spectral density curve. Generalizing the method to an unbalanced
weighting of correlated random sources yields an algorithm that
produces relatively accurate approximations to the 1/f power spectrum
characteristic with fewer terms. There is roughly 0.15 dB approximation
error over a 7 octave range using six uniform pseudo-random variates per
output value. Useful results are obtained from as few as four uniform
variates per output.

If this sounds interesting, check out the page and feel free to comment
here. I'm especially interested in whether you observe the same results.
Robin Whittle
2006-03-27 01:38:01 UTC
Permalink
I have added a link to your page from mine:

http://www.firstpr.com.au/dsp/pink-noise/

My page is definitive source on this particular subject and I am happy
to link to your page. If yours disappears at some stage, I will place a
copy of it on my site.

I suggested a simple randomisation of the Voss-McCartney algorithm but
never took it any further:

http://www.firstpr.com.au/dsp/pink-noise/#Ripple

Can you reveal your real name, or are you happy to be cited as
"RidgeRat" in scientific papers? Google finds 360 mentions of my page,
and I expect people to be using your algorithm.

Google Scholar finds two references, including one which uses the
Voss-McCartney algorithm for some precise statistical purpose which I
don't understand:

http://arxiv.org/ftp/nlin/papers/0511/0511041.pdf
Real-time update of multi-fractal analysis on dynamic time series
using incremental discrete wavelet transforms
Nicholas Brodu November 2005

GPL V2 C++ source code, driving the algorithm with the Mersenne Twister:

http://nicolas.brodu.free.fr./en/programmation/incremfa/index.html


- Robin
RidgeRat
2006-03-28 06:09:03 UTC
Permalink
Apologies, Robin, and others in the group!

My name is Larry Trammell, which is not a secret here. I am not
currently well configured to post to this list. I grabbed a mailbox that
was configured for posting to lists. But I forgot that it is also
configured for maximum concealment, because I occasionally stop by music
sites where exchange of all private information is streng verboten, for
the protection of young surfers who might appear there.

When I get this mess straightened out, or if I last that long, I will
try be a little less mysterious.

Thanks for pointing out this problem.
Post by RidgeRat
http://www.firstpr.com.au/dsp/pink-noise/
My page is definitive source on this particular subject and I am happy
to link to your page. If yours disappears at some stage, I will place a
copy of it on my site.
I suggested a simple randomisation of the Voss-McCartney algorithm but
http://www.firstpr.com.au/dsp/pink-noise/#Ripple
Can you reveal your real name, or are you happy to be cited as
"RidgeRat" in scientific papers? Google finds 360 mentions of my page,
and I expect people to be using your algorithm.
Google Scholar finds two references, including one which uses the
Voss-McCartney algorithm for some precise statistical purpose which I
http://arxiv.org/ftp/nlin/papers/0511/0511041.pdf
Real-time update of multi-fractal analysis on dynamic time series
using incremental discrete wavelet transforms
Nicholas Brodu November 2005
http://nicolas.brodu.free.fr./en/programmation/incremfa/index.html
- Robin
--
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
David Lowenfels
2006-03-27 03:41:05 UTC
Permalink
Hi "RidgeRat"

Thanks for sharing this nice algorithm!
I rescaled the gain array by (1+P)/(1-P) since I used the second
generator method with no conditionals.
Is that the correct scaling factor for equivalency with the first
method?

Here is a C++ class that I made to test it:

#ifndef _PinkNoise_H
#define _PinkNoise_H

// http://home.earthlink.net/~ltrammell/tech/pinkalg.htm

#include <cstdlib>
#include <ctime>

#define PINK_NOISE_NUM_STAGES 3

class PinkNoise {
public:
PinkNoise() {
srand ( time(NULL) ); // initialize random generator
clear();
}

void clear() {
for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ )
state[ i ] = 0.0;
}

float tick() {
float output = 0;
for( size_t i = 0; i < PINK_NOISE_NUM_STAGES; i++ ) {
float temp = rand1();
state[i] = P[i] * (state[i] - temp) + temp;
output += A[i] * state[i];
}
return output;
}

protected:
float state[ PINK_NOISE_NUM_STAGES ];
static const float A[ PINK_NOISE_NUM_STAGES ];
static const float P[ PINK_NOISE_NUM_STAGES ];

float rand1() {
static const float RMI2 = 2.0 / float(RAND_MAX);
return float(rand()) * RMI2 - 1.0;
}

};

//A = [ 0.01089, 0.00899, 0.01359 ];
const float PinkNoise::A[] = { 0.02109238, 0.07113478,
0.68873558 }; // rescaled by (1+P)/(1-P)
const float PinkNoise::P[] = { 0.3190, 0.7756, 0.9613 };

#endif
RidgeRat
2006-03-28 04:17:58 UTC
Permalink
David, you seem to have captured the essence of the algorithm as I
described it. Oooh, now I have to hope I got it right... I will have to
confess that I have been concentrating on the form-1 generator because
it relates more directly to the Voss-McCartney algorithm that was the
motivation.

So I guess that makes you the principal investigator on applying the
second method. :-)

If I blew the math derivation, which is impossible of course, the the
results will be terrible. But repairable! With the right scalings the
results should end up fine.

While you are thinking about scaling, keep in mind that I was fitting to
a theoretical curve, NOT to a useful output level. So you will want to
find an overall scaling that gives you a good dynamic range for output
converter devices.
Post by David Lowenfels
Hi "RidgeRat"
Thanks for sharing this nice algorithm!
I rescaled the gain array by (1+P)/(1-P) since I used the second
generator method with no conditionals.
Is that the correct scaling factor for equivalency with the first method?
<snipped code for brevity...>
RidgeRat
2006-03-28 16:24:27 UTC
Permalink
David, I trust my math, but I trust my simulations more. Just to make
sure I wasn't suffering from coffee withdrawal, I rechecked my scaling
factor number math AND ran a quick simulation. You should be fine with
the scaling factor corrections as you coded them.

Here are some additional ideas to fuel the flames:

- When you get the algorithm working, you can omit the rand1 function
and use rand() directly, by noting that using rand() would result in an
expected value of 1.5 and half the magnitude. So you can compensate with
a 2 in your scaling factors, and apply one final subtraction. Should
reduce a lot of the overhead.

- There just isn't that much code. For a mere three passes, you can
unroll the loop and present the instruction sequence directly. Depending
on the compiler, sometimes this code optimizes better.
Post by David Lowenfels
Hi "RidgeRat"
Thanks for sharing this nice algorithm!
I rescaled the gain array by (1+P)/(1-P) since I used the second
generator method with no conditionals.
Is that the correct scaling factor for equivalency with the first method?
#ifndef _PinkNoise_H
#define _PinkNoise_H
// http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
#include <cstdlib>
#include <ctime>
#define PINK_NOISE_NUM_STAGES 3
class PinkNoise {
PinkNoise() {
srand ( time(NULL) ); // initialize random generator
clear();
}
void clear() {
for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ )
state[ i ] = 0.0;
}
float tick() {
float output = 0;
for( size_t i = 0; i < PINK_NOISE_NUM_STAGES; i++ ) {
float temp = rand1();
state[i] = P[i] * (state[i] - temp) + temp;
output += A[i] * state[i];
}
return output;
}
float state[ PINK_NOISE_NUM_STAGES ];
static const float A[ PINK_NOISE_NUM_STAGES ];
static const float P[ PINK_NOISE_NUM_STAGES ];
float rand1() {
static const float RMI2 = 2.0 / float(RAND_MAX);
return float(rand()) * RMI2 - 1.0;
}
};
//A = [ 0.01089, 0.00899, 0.01359 ];
const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; //
rescaled by (1+P)/(1-P)
const float PinkNoise::P[] = { 0.3190, 0.7756, 0.9613 };
#endif
--
dupswapdrop -- the music-dsp mailing list and website: subscription
info, FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
--
RidgeRat is the 'list lurking' alter-ego of Larry Trammell.
David Lowenfels
2006-03-29 06:44:05 UTC
Permalink
Post by RidgeRat
- When you get the algorithm working, you can omit the rand1
function and use rand() directly, by noting that using rand() would
result in an expected value of 1.5 and half the magnitude. So you
can compensate with a 2 in your scaling factors, and apply one
final subtraction. Should reduce a lot of the overhead.
I assume what you mean is use float(rand()) and factor out everything
into a single (output*RMI2 - offset) at the end.
At first I thought the offset would be 1.0, but on second glance it
is actually the sum of the state gain factors.
Post by RidgeRat
- There just isn't that much code. For a mere three passes, you can
unroll the loop and present the instruction sequence directly.
Depending on the compiler, sometimes this code optimizes better.
yes, I had the same idea.

Thanks,
David


Here's the new optimized method:
(ready for inclusion into the code archive! :)

float tick() {
static const float RMI2 = 2.0 / float(RAND_MAX);
static const float offset = A[0] + A[1] + A[2];

float temp = float( rand() );
state[0] = P[0] * (state[0] - temp) + temp;
temp = float( rand() );
state[1] = P[1] * (state[1] - temp) + temp;
temp = float( rand() );
state[2] = P[2] * (state[2] - temp) + temp;
return ( A[0]*state[0] + A[1]*state[1] + A[2]*state[2] )*RMI2 -
offset;
}

Magnus Jonsson
2006-03-27 06:51:56 UTC
Permalink
Hi RidgeRat,

Interesting work! How does it compare to using one noise source and a
filter consisting of parallel poles?

I also came up with a (different) modification of the Voss-McCartney
algorithm in 2002:

http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html

It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now think of
another improvement to mine and the Voss-McCartney: Each generator should
have an approximately gaussian distribution. (Maybe triangular is good
enough.)

-Magnus Jonsson
Post by RidgeRat
Hi group. I'm a recently signed newbie. After some advice from Douglas,
the friendly list admin, I have posted information about a possibly new
algorithm for direct digital synthesis of pink noise. (Otherwise, you
can tell me about my re-discovery.) You can find the full exposition at
http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
A little background: When searching the web for a pink noise generator
method suitable for semi-automated loudspeaker or microphone testing, I
found the "Pink Noise page" at
http://www.firstpr.com.au/dsp/pink-noise/
My initial joy at learning about the Voss-McCartney algorithm there was
quickly damped when I found that I did not get good quality results from
it. This is illustrated in the web page. Further study led to some
insights, and from there variations that I believe are improvements,
which is why I am here, where the experts lurk.
To summarize the page briefly --
Abstract. The Voss-McCartney direct digital synthesis algorithm
generates a noise process approximating pink noise, from an
equally-weighted combination of random white noise sources, on a rigid
updating schedule. It is conjectured that the rigid periodicity of the
updating explains spectral artifacts that prevent the method from
converging uniformly to a good approximation of the desired 1/f power
spectral density curve. Generalizing the method to an unbalanced
weighting of correlated random sources yields an algorithm that
produces relatively accurate approximations to the 1/f power spectrum
characteristic with fewer terms. There is roughly 0.15 dB approximation
error over a 7 octave range using six uniform pseudo-random variates per
output value. Useful results are obtained from as few as four uniform
variates per output.
If this sounds interesting, check out the page and feel free to comment
here. I'm especially interested in whether you observe the same results.
--
dupswapdrop -- the music-dsp mailing list and website: subscription info,
FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
Urs Heckmann
2006-03-27 09:49:32 UTC
Permalink
Hi all,
Post by RidgeRat
http://www.firstpr.com.au/dsp/pink-noise/
If anybody is interested...

... I'm using a nice little method involving 2 lookup tables. This
way I don't need to loop through the stages. It could be called Fast-
Voss-McCartney, because I think the result is the same with a lot
less cpu cycles involved ;-)

The problem was, I'm using 11 stages and thus I wanted to get rid of
counting bits in a loop for each sample.

The idea is, for any sample, only one of the stages > 0 changes. Thus
you can use a circular LUT containing stage indices to check which
stage is due for a change. You gotta take out stage[0] off the
algorithm as it *always* changes (white noise component) and as it's
the only stage that is not calculated strictly "interleaved".

The LUT has a size of 2^N - 1, where N is the number of stages. But
for N > 8-or-so one can dramatically reduce the LUT by unrolling the
loop, i.e. calculate 4 samples at once and by splitting the table
into two, where the first table holds a short repetitive pattern of,
say 32 stage indices and the second table holds modifications to one
index in the first table that occurr only once every 32 samples.

D'oh. I should write emails *after* my second coffee.

Anyway, if you like, I'll post it in a couple of hours or so. (Gotta
check out RidgeRat's method first)

Cheers,

;) Urs


urs heckmann
***@u-he.com
www.u-he.com
Urs Heckmann
2006-03-27 11:29:25 UTC
Permalink
Okay,

Another coffee and a few smokes later, here's a little algorithm for
an 11-stage Voss-McCartney with very little overhead to compute the
running bits.

Hope it contains fewer bugs than my code normally does.

Cheers,

;) Urs


urs heckmann
***@u-he.com
www.u-he.com


// YFRand() <- Your Favourite Randomizer for white noise

// constants

const int stages[ 31 ] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1,
0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
const float scale = 1.f/11.f;

// global data used by the algorithm

float stageMem[ 10 ] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f );
float stageSum = 0.f;

int stageCount0 = 0;
int stageCount1 = 0;


float FastVossMcCartney()
{

// updateStage contains the stage-1 to be updated

int updateStage = 0;

// calculate stage 0, changes every sample

float stage0 = YFRand( -1.f, 1.f ) * scale;

if ( stageCount0 < 31 )
{
// retrieve stage that has to change for stages 1 - 5

updateStage = stages[ stageCount0++ ];
}
else
{
// okay our Table holds only 31 changes for stages 1-5
// but, with a little trick we add stages 9-10
// We simply map the table vertically to itself on element 32,
// effectively using the same pattern, but adding 5 to the index.
// (As we don't explicitely need to store element 32, it's not in
the array)

stageCount0 = 0;

if ( stageCount1 < 31 )
{
updateStage = 5 + stages[ stageCount1++ ];
}
else
{
// Oh. We reached the 1024th sample...
// This is the case where nothing happens in stages 1-10...
// Effectively, the stage 10 updates
// every 1024 samples, thus it represents the
// eleventh octave below Nyquist

stageCount1 = 0;
return stage0 + stageSum;
}
}

// okay, now that we know which of stages 1-10 updates,
// we calculate a new value.
// To speed things up, we use a sum, much like the method
// of a running average FIR filter.

stageSum -= stageMem[ updateStage ];
stageMem[ updateStage ] = YFRand( -1.f, 1.f ) * scale;
stageSum += stageMem[ updateStage ];

return stage0 + stageSum;
}

Please note, for faster execution you have to invert the logic of
conditional branches ("if"s), but putting it this way round is easier
to read! Also, this version isn't multithreaded. You gotta put it
into objects and make the data variables object members.

You may also want to add a dc-blocker to compensate for rounding
errors adding up in updateStage. Or just make it a little leaky.
RidgeRat
2006-03-28 06:05:50 UTC
Permalink
You seem to have some experience with the Voss-McCartney generators. I
have not taken the V-M generator past 9 stages. Spectral coverage was
very good, but accuracy... Have you studied the power spectrum you get
from averaging the power spectrum of, say, 10000 or so 4096-sample
signal blocks using your longer generator sequences? I am curious about
whether artifacts I observed are no longer present when the number of
stages grows large.
Okay,
Another coffee and a few smokes later, here's a little algorithm for an
11-stage Voss-McCartney with very little overhead to compute the
running bits.
Hope it contains fewer bugs than my code normally does.
Cheers,
;) Urs
urs heckmann
www.u-he.com
// YFRand() <- Your Favourite Randomizer for white noise
// constants
const int stages[ 31 ] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
const float scale = 1.f/11.f;
// global data used by the algorithm
float stageMem[ 10 ] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f );
float stageSum = 0.f;
int stageCount0 = 0;
int stageCount1 = 0;
float FastVossMcCartney()
{
// updateStage contains the stage-1 to be updated
int updateStage = 0;
// calculate stage 0, changes every sample
float stage0 = YFRand( -1.f, 1.f ) * scale;
if ( stageCount0 < 31 )
{
// retrieve stage that has to change for stages 1 - 5
updateStage = stages[ stageCount0++ ];
}
else
{
// okay our Table holds only 31 changes for stages 1-5
// but, with a little trick we add stages 9-10
// We simply map the table vertically to itself on element 32,
// effectively using the same pattern, but adding 5 to the index.
// (As we don't explicitely need to store element 32, it's not
in the array)
stageCount0 = 0;
if ( stageCount1 < 31 )
{
updateStage = 5 + stages[ stageCount1++ ];
}
else
{
// Oh. We reached the 1024th sample...
// This is the case where nothing happens in stages 1-10...
// Effectively, the stage 10 updates
// every 1024 samples, thus it represents the
// eleventh octave below Nyquist
stageCount1 = 0;
return stage0 + stageSum;
}
}
// okay, now that we know which of stages 1-10 updates,
// we calculate a new value.
// To speed things up, we use a sum, much like the method
// of a running average FIR filter.
stageSum -= stageMem[ updateStage ];
stageMem[ updateStage ] = YFRand( -1.f, 1.f ) * scale;
stageSum += stageMem[ updateStage ];
return stage0 + stageSum;
}
Please note, for faster execution you have to invert the logic of
conditional branches ("if"s), but putting it this way round is easier
to read! Also, this version isn't multithreaded. You gotta put it into
objects and make the data variables object members.
You may also want to add a dc-blocker to compensate for rounding errors
adding up in updateStage. Or just make it a little leaky.
--
dupswapdrop -- the music-dsp mailing list and website: subscription
info, FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
Urs Heckmann
2006-03-28 08:22:07 UTC
Permalink
Post by RidgeRat
You seem to have some experience with the Voss-McCartney generators. I
have not taken the V-M generator past 9 stages. Spectral coverage was
very good, but accuracy... Have you studied the power spectrum you get
from averaging the power spectrum of, say, 10000 or so 4096-sample
signal blocks using your longer generator sequences? I am curious about
whether artifacts I observed are no longer present when the number
of stages grows large.
Sorry,

honest answer: I've just used a realtime analyzer, thought "yep, the
spectrum looks like expected", found that it performs well, sounds
good to my ears, asked the beta team, they nodded, I shipped the
product & never touched the code again ;-)

Cheers,

;) Urs
Larry Trammell (aka RidgeRat)
2006-03-29 05:46:29 UTC
Permalink
Right, Urs! My moaning about accuracies is theoretical. Maybe certain
test and research purposes could be affected, and I need to think about
that. But when it comes to audibility, nobody would know if a pure tone
1/64-step below high F-sharp was down a half dB... especially if the
tone 2/64-step below is on target.
Post by Urs Heckmann
Post by RidgeRat
You seem to have some experience with the Voss-McCartney generators. I
have not taken the V-M generator past 9 stages. Spectral coverage was
very good, but accuracy... Have you studied the power spectrum you get
from averaging the power spectrum of, say, 10000 or so 4096-sample
signal blocks using your longer generator sequences? I am curious about
whether artifacts I observed are no longer present when the number of
stages grows large.
Sorry,
honest answer: I've just used a realtime analyzer, thought "yep, the
spectrum looks like expected", found that it performs well, sounds good
to my ears, asked the beta team, they nodded, I shipped the product &
never touched the code again ;-)
Cheers,
;) Urs
--
dupswapdrop -- the music-dsp mailing list and website: subscription
info, FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
James McCartney
2006-03-27 23:22:50 UTC
Permalink
Post by Urs Heckmann
The problem was, I'm using 11 stages and thus I wanted to get rid
of counting bits in a loop for each sample.
I use 16 generators.
There is no need to use a loop or a lookup table to count zero bits.
Both PowerPC and Intel have an instruction to do this.
Have a look at the link to my code that I posted previously.
It has no conditional statements in the loop, so is likely faster
than the code you posted.
Post by Urs Heckmann
The idea is, for any sample, only one of the stages > 0 changes.
Thus you can use a circular LUT containing stage indices to check
which stage is due for a change. You gotta take out stage[0] off
the algorithm as it *always* changes (white noise component) and as
it's the only stage that is not calculated strictly "interleaved".
Urs Heckmann
2006-03-28 00:11:39 UTC
Permalink
Post by James McCartney
Post by Urs Heckmann
The problem was, I'm using 11 stages and thus I wanted to get rid
of counting bits in a loop for each sample.
I use 16 generators.
There is no need to use a loop or a lookup table to count zero
bits. Both PowerPC and Intel have an instruction to do this.
Have a look at the link to my code that I posted previously.
Yeah, seen that later. Didn't know that ctz was available on PPC...
Post by James McCartney
It has no conditional statements in the loop, so is likely faster
than the code you posted.
Well, isn't a commonly not taken branch often faster than i.e. a
logical and that has to be executed every cycle and might increase
instruction dependencies? (Not defending my solution, ctz is
definately faster, just curious about recent optimization paradigms
in general)

Cheers,

;) Urs
James McCartney
2006-03-27 16:23:55 UTC
Permalink
I implemented Magnus Jonsson's suggestion in SuperCollider (search
for Magnus on this page):
http://cvs.sourceforge.net/viewcvs.py/*checkout*/supercollider/
SuperCollider3/source/plugins/NoiseUGens.cpp
Post by Magnus Jonsson
Hi RidgeRat,
Interesting work! How does it compare to using one noise source and
a filter consisting of parallel poles?
I also came up with a (different) modification of the Voss-
http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html
It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now
think of another improvement to mine and the Voss-McCartney: Each
generator should have an approximately gaussian distribution.
(Maybe triangular is good enough.)
Why does that matter?
The amplitude distribution of a random number generator has no effect
on its spectrum. If you have sequentially independent random values,
you'll have a white noise spectrum - the amplitude distribution can
be anything.
Post by Magnus Jonsson
-Magnus Jonsson
Post by RidgeRat
Hi group. I'm a recently signed newbie. After some advice from Douglas,
the friendly list admin, I have posted information about a
possibly new
algorithm for direct digital synthesis of pink noise. (Otherwise, you
can tell me about my re-discovery.) You can find the full
exposition at
http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
A little background: When searching the web for a pink noise
generator
method suitable for semi-automated loudspeaker or microphone
testing, I
found the "Pink Noise page" at
http://www.firstpr.com.au/dsp/pink-noise/
My initial joy at learning about the Voss-McCartney algorithm
there was
quickly damped when I found that I did not get good quality
results from
it. This is illustrated in the web page. Further study led to some
insights, and from there variations that I believe are improvements,
which is why I am here, where the experts lurk.
To summarize the page briefly --
Abstract. The Voss-McCartney direct digital synthesis algorithm
generates a noise process approximating pink noise, from an
equally-weighted combination of random white noise sources, on a rigid
updating schedule. It is conjectured that the rigid periodicity of the
updating explains spectral artifacts that prevent the method from
converging uniformly to a good approximation of the desired 1/f power
spectral density curve. Generalizing the method to an unbalanced
weighting of correlated random sources yields an algorithm that
produces relatively accurate approximations to the 1/f power spectrum
characteristic with fewer terms. There is roughly 0.15 dB
approximation
error over a 7 octave range using six uniform pseudo-random
variates per
output value. Useful results are obtained from as few as four uniform
variates per output.
If this sounds interesting, check out the page and feel free to comment
here. I'm especially interested in whether you observe the same results.
--
subscription info, FAQ, source code archive, list archive, book
reviews, dsp links http://shoko.calarts.edu/musicdsp http://
ceait.calarts.edu/mailman/listinfo/music-dsp
--
dupswapdrop -- the music-dsp mailing list and website: subscription
info, FAQ, source code archive, list archive, book reviews, dsp
links http://shoko.calarts.edu/musicdsp http://ceait.calarts.edu/
mailman/listinfo/music-dsp
Magnus Jonsson
2006-03-27 16:51:33 UTC
Permalink
Ohh that's cool :) It got useful somewhere... Thanks for letting me know!
I implemented Magnus Jonsson's suggestion in SuperCollider (search for Magnus
http://cvs.sourceforge.net/viewcvs.py/*checkout*/supercollider/
SuperCollider3/source/plugins/NoiseUGens.cpp
Post by Magnus Jonsson
Hi RidgeRat,
Interesting work! How does it compare to using one noise source and a
filter consisting of parallel poles?
I also came up with a (different) modification of the Voss-McCartney
http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html
It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now think of
another improvement to mine and the Voss-McCartney: Each generator should
have an approximately gaussian distribution. (Maybe triangular is good
enough.)
Why does that matter?
The amplitude distribution of a random number generator has no effect on its
spectrum. If you have sequentially independent random values, you'll have a
white noise spectrum - the amplitude distribution can be anything.
Post by Magnus Jonsson
-Magnus Jonsson
Post by RidgeRat
Hi group. I'm a recently signed newbie. After some advice from Douglas,
the friendly list admin, I have posted information about a possibly new
algorithm for direct digital synthesis of pink noise. (Otherwise, you
can tell me about my re-discovery.) You can find the full exposition at
http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
A little background: When searching the web for a pink noise generator
method suitable for semi-automated loudspeaker or microphone testing, I
found the "Pink Noise page" at
http://www.firstpr.com.au/dsp/pink-noise/
My initial joy at learning about the Voss-McCartney algorithm there was
quickly damped when I found that I did not get good quality results from
it. This is illustrated in the web page. Further study led to some
insights, and from there variations that I believe are improvements,
which is why I am here, where the experts lurk.
To summarize the page briefly --
Abstract. The Voss-McCartney direct digital synthesis algorithm
generates a noise process approximating pink noise, from an
equally-weighted combination of random white noise sources, on a rigid
updating schedule. It is conjectured that the rigid periodicity of the
updating explains spectral artifacts that prevent the method from
converging uniformly to a good approximation of the desired 1/f power
spectral density curve. Generalizing the method to an unbalanced
weighting of correlated random sources yields an algorithm that
produces relatively accurate approximations to the 1/f power spectrum
characteristic with fewer terms. There is roughly 0.15 dB approximation
error over a 7 octave range using six uniform pseudo-random variates per
output value. Useful results are obtained from as few as four uniform
variates per output.
If this sounds interesting, check out the page and feel free to comment
here. I'm especially interested in whether you observe the same results.
--
dupswapdrop -- the music-dsp mailing list and website: subscription info,
FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp http://
ceait.calarts.edu/mailman/listinfo/music-dsp
--
dupswapdrop -- the music-dsp mailing list and website: subscription info,
FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp http://ceait.calarts.edu/
mailman/listinfo/music-dsp
--
dupswapdrop -- the music-dsp mailing list and website:subscription info, FAQ,
source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
Magnus Jonsson
2006-03-27 16:51:33 UTC
Permalink
Ohh that's cool :) It got useful somewhere... Thanks for letting me know!
I implemented Magnus Jonsson's suggestion in SuperCollider (search for Magnus
http://cvs.sourceforge.net/viewcvs.py/*checkout*/supercollider/
SuperCollider3/source/plugins/NoiseUGens.cpp
Post by Magnus Jonsson
Hi RidgeRat,
Interesting work! How does it compare to using one noise source and a
filter consisting of parallel poles?
I also came up with a (different) modification of the Voss-McCartney
http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html
It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now think of
another improvement to mine and the Voss-McCartney: Each generator should
have an approximately gaussian distribution. (Maybe triangular is good
enough.)
Why does that matter?
The amplitude distribution of a random number generator has no effect on its
spectrum. If you have sequentially independent random values, you'll have a
white noise spectrum - the amplitude distribution can be anything.
Post by Magnus Jonsson
-Magnus Jonsson
Post by RidgeRat
Hi group. I'm a recently signed newbie. After some advice from Douglas,
the friendly list admin, I have posted information about a possibly new
algorithm for direct digital synthesis of pink noise. (Otherwise, you
can tell me about my re-discovery.) You can find the full exposition at
http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
A little background: When searching the web for a pink noise generator
method suitable for semi-automated loudspeaker or microphone testing, I
found the "Pink Noise page" at
http://www.firstpr.com.au/dsp/pink-noise/
My initial joy at learning about the Voss-McCartney algorithm there was
quickly damped when I found that I did not get good quality results from
it. This is illustrated in the web page. Further study led to some
insights, and from there variations that I believe are improvements,
which is why I am here, where the experts lurk.
To summarize the page briefly --
Abstract. The Voss-McCartney direct digital synthesis algorithm
generates a noise process approximating pink noise, from an
equally-weighted combination of random white noise sources, on a rigid
updating schedule. It is conjectured that the rigid periodicity of the
updating explains spectral artifacts that prevent the method from
converging uniformly to a good approximation of the desired 1/f power
spectral density curve. Generalizing the method to an unbalanced
weighting of correlated random sources yields an algorithm that
produces relatively accurate approximations to the 1/f power spectrum
characteristic with fewer terms. There is roughly 0.15 dB approximation
error over a 7 octave range using six uniform pseudo-random variates per
output value. Useful results are obtained from as few as four uniform
variates per output.
If this sounds interesting, check out the page and feel free to comment
here. I'm especially interested in whether you observe the same results.
--
dupswapdrop -- the music-dsp mailing list and website: subscription info,
FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp http://
ceait.calarts.edu/mailman/listinfo/music-dsp
--
dupswapdrop -- the music-dsp mailing list and website: subscription info,
FAQ, source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp http://ceait.calarts.edu/
mailman/listinfo/music-dsp
--
dupswapdrop -- the music-dsp mailing list and website:subscription info, FAQ,
source code archive, list archive, book reviews, dsp links
http://shoko.calarts.edu/musicdsp
http://ceait.calarts.edu/mailman/listinfo/music-dsp
RidgeRat
2006-03-28 06:25:28 UTC
Permalink
I'll have to add your SuperCollider page to my late hours study list.

I've come to truce with the notion that the "distribution doesn't
matter" when working with white noise sources. If the correlations
turn out right, so do the power spectra. But it still seems so
implausible that there isn't something statistically different about the
data sets generated using different distributions. Here is the
challenge: suppose that two generators produce sequences with the same
autocorrelation but using different methods with different
distributions. Given a sample set from each, scaled by unknown arbitrary
constants, is there no statistical test that can tell which generator
generated which sample set? Look out Starbucks, I need a big refill.
I implemented Magnus Jonsson's suggestion in SuperCollider (search for
http://cvs.sourceforge.net/viewcvs.py/*checkout*/supercollider/
SuperCollider3/source/plugins/NoiseUGens.cpp
Post by Magnus Jonsson
Hi RidgeRat,
Interesting work! How does it compare to using one noise source and a
filter consisting of parallel poles?
I also came up with a (different) modification of the Voss- McCartney
http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html
It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now
think of another improvement to mine and the Voss-McCartney: Each
generator should have an approximately gaussian distribution. (Maybe
triangular is good enough.)
Why does that matter?
The amplitude distribution of a random number generator has no effect
on its spectrum. If you have sequentially independent random values,
you'll have a white noise spectrum - the amplitude distribution can be
anything.
<snipped original post>
RidgeRat
2006-03-28 06:02:25 UTC
Permalink
Thanks for the link Magnus. I'll have to give it a look.

I believe the filtering approach promises better accuracy, at least
theoretically. I'm really unsure about whether it offers better
efficiency, as this can depend a lot on the cost of the generators. But
there are some practical matters. You will find that most of the filter
designs are done in the analog domain and... then what? If you have ever
tried to map an analog filter filter into a digital design that is
accurate beyond about 20% of the Nyquist frequency, you will know what I
mean.
Post by Magnus Jonsson
Hi RidgeRat,
Interesting work! How does it compare to using one noise source and a
filter consisting of parallel poles?
I also came up with a (different) modification of the Voss-McCartney
http://aulos.calarts.edu/pipermail/music-dsp/2002-May/015908.html
It addresses the same problem as your method does, but with another
solution. Unfortunately I never analyzed it rigorously. I can now think
of another improvement to mine and the Voss-McCartney: Each generator
should have an approximately gaussian distribution. (Maybe triangular is
good enough.)
-Magnus Jonsson
<snipped original post>
RidgeRat
2006-03-28 06:14:21 UTC
Permalink
Experiments with the second correlated generator form might prove
interesting along this vein, because I would expect it to produce a much
different local distribution from the first generator form. But the
power spectrum with both generator forms should have the right 1/f form
because they produce the same correlation statistics so I'm reluctant to
fix something that isn't broken (so far).
Post by Magnus Jonsson
Hi RidgeRat,
<snip>
Post by Magnus Jonsson
I can now think
of another improvement to mine and the Voss-McCartney: Each generator
should have an approximately gaussian distribution. (Maybe triangular is
good enough.)
-Magnus Jonsson
<original post snipped>
Loading...