Demonstrate HN: Random web entry to noise – counter-essentially essentially essentially based pseudo-random number generator
By Joel Okay. Pettersson. Added 2022-03-14. Updated 2022-03-26.
A fundamental form of audio noise generator produces contemporary pseudo-random numbers at a payment, or frequency, and connects these dots in a scheme, as an instance producing squarish protect lines between values. Sweeping the frequency of this kind of generator up and down produces some sounds which many dangle heard for a long time. However what if you should must spice things up pretty extra and strengthen “by means of-zero” FM synthesis habits (reversing the waveshape in time when frequency becomes detrimental)? Or what if you should must make use of impolite section modulation to take dangle of noise values at some (perchance trim) distance from a center? Now I mediate I dangle a ravishing solution, in the develop of a straightforward purpose that turns an trim series of values into something chaotic ample to sound adore white noise, that may perchance perchance be aged in a future version of the saugns program.
On some reflection, I made up my recommendations that the order to solve was, how one can plan a movement of white noise values efficiently, whereas allowing random web entry to to noise values within a roughly 232 duration? Efficient random web entry to, meaning perfect predictability and skill to merely leap around, is clearly at odds with the cryptographic criteria for ravishing random numbers that folks most most incessantly are attempting to strive for, but it be precisely what’s wanted if as a alternative the fair is a flexible audio mark generator. Ignore pre-computing and caching noise values, as that’s inefficient, and the duration is also pretty arbitrary and will as successfully be a 64-bit duration.
Update: Below, dinky by dinky I checklist the pattern of my ranoise32 purpose, which uses a terrifying 32-bit counter for speak. For the impatient, the final half has take a look at statistics and a final version in C99. Extra may perchance perchance well be chanced on in my “ranoise” git repository on Codeberg. After experimentation, it ended up making an strive out as being greater for non-cryptographic random number technology than many broadly aged RNGs, but plainly aloof has its flaws. For my applications it seems to be colossal. A apply-on modification makes it even greater.
Correct avalanching and a white noise sound
From the arena of cryptography and hash functions, the avalanche carry out is the property of a purpose that the bits of the final consequence alternate vastly ample on every occasion ravishing one bit of the input changes. Review a sawtooth wave ramp (linearly increasing values) to a white noise sequence (random numbers), and that’s clearly also relevant for digital audio white noise synthesis. There’s no neater formulation to my order than a payment-efficient and uncomplicated purpose that turns the worn into the latter, i.e. some purpose which provides ravishing avalanching with minimal computation; then the value of a linear counter will present the sample space in a corresponding movement of noise, and the counter may perchance perchance well be read and modified arbitrarily.
An different solution would be a straightforward ragged random number generator which may perchance perchance well be aged in two instructions, e.g. a linear congruential generator – for which it is straightforward to calculate how one can develop a purpose to retrieve the old value, which may perchance perchance well be aged alongside the aim for offering the following value. However intriguing several steps support or forth would then require looping, so it be not a ravishing solution for random web entry to. Update: I didn’t realize it beforehand, but it be imaginable to develop a LCG leap around in logarithmic time (facing the preference of steps to lunge bit by bit), so it may perchance perchance well dangle labored in put collectively as an answer, even supposing less optimally.
So, returning to the foundation of a straightforward-ample bit-scrambling purpose, what to make use of? There are some more successfully-identified functions aged as section of hash functions, to combine up the bits some more after producing some number (e.g. Murmur hash fmix, and diversified multiply and/or xor and shift/rotate diversifications), or in most cases even for terrifying random number technology applications, even supposing whatever the aim, they tend to either hasten input values a long way too poorly for it to sound adore white noise, or they’re the reverse and use rather heavy-responsibility cryptographic computations that appear overkill – even supposing in this context, looping about a straightforward operations more than about a instances per sample is already uninteresting, and pointless as it seems to be.
I arrived at something intuitively, by means of experimenting, browsing out constructing blocks as I went. If truth be told, I ended up pondering of the order of developing diffusion or avalanching as a two-dimensional order, the keep apart two diversified things handle two diversified parts of what is to be accomplished. The first, spreading values out all over the aim vary, would be solved with a multiplication. The second, making the spacing of values less favorite, would be solved in section by using a variable amount of bitrotation.
Fibonacci hashing
So to spread a chain of values out evenly all over a purpose vary, in the sense that regardless of whether about a or a form of input values are aged, they cease up overlaying the identical vary, Fibonacci hashing may perchance perchance well be aged. It uses a straightforward multiplication with a model; for 32-bit integer numbers, 232 divided by the golden ratio provides 2654435769
as the multiplier. The tip consequence for a linear input sequence is, then again, aloof evenly-spaced values rising or falling and wrapping around. In diversified words, it aloof sounds completely periodic as lengthy as frequency (spacing between successive input values) stays fixed.
The multiplication section of Fibonacci hashing seems to be adore a ravishing purpose for in the initiating altering the 32-bit input in the aim to originate, making lower and better numbers mighty more identical, and spreading out bits some. Bit-twiddling when accomplished afterwards provides mighty more bang for the computational buck.
Outlandish-or with bitshift and multiply
I attempted to make use of distinctive-or (xor) of bitshifted values in diverse ways for easy extra transformations, but by itself it be merely not ravishing ample to be a purposeful addition. Many diversifications, when positioned following the Fibonacci hashing multiplication, every consequence in its dangle queer metal sound, noisy but very diversified from white noise. Throwing in extra and more mounted shifts (or mounted rotations) may perchance perchance well enhance results, but shouldn’t be the finest technique to cease so.
It began to appear promising when twice using a xor with the bitshifted value, and among the instances also using an multiplication of the shifted value with the unshifted value. it sounded greater – almost but not pretty adore white noise. Doing it that scheme, audibly some parts of the frequency spectrum aloof rating too-repetitive noise, but at which frequencies the aim sounds ravishing vs. not pretty ravishing depend on specifics of the shifts, multiplications, and the scheme they’re ordered.
Below are four diversifications of a purpose which every plan a variation of noise almost, but not pretty, adore white noise. Without some alternate to the arrive, it seems to be it be not imaginable to assign away with the defects with out many more operations, only to develop trade-offs and audibly trail all over the issues.
/Four straightforward diversifications of a purpose usable with a counter. Produces noise pretty but not pretty adore white noise. Less purposeful, amongst earlier making an strive out sooner than contemporary arrive. */ int32_t warp1(uint32_t n) { uint32_t s=n 2654435769UL; s ^=(s>> 16) s; s ^=(s > 16); return s; } int32_t warp3(uint32_t n) { uint32_t s=n 2654435769UL; s ^=(s>> 16); s ^=(s > 16) s; return s; }
All of these, and white noise, consequence in spectrograms which gaze very mighty alike; that particular size arrive doesn’t indubitably work at and past this point.
Variable bitrotation and multiply
The use of bitrotation as a alternative of bitshifts can present pretty more, but the largest development on the above came from using a variable length of shift or rotation, in space of a mounted length. The bottom bits appear to fluctuate successfully ample, so why not ravishing use them? This alternate to the above arrive eliminated the audibly repetitive parts of the noise here and there in the frequency spectrum. Thereafter it grew to change into out that most of what else I’d added would be simplified away with out audible lack of quality. I chanced on that every xor would be dropped.
Right here is the most minimal code I’ve written that sounds ravishing, passable to make use of as a provide of white noise. (For my listening, the upper 16 bits went into 16-bit samples at one or one other sample payment.) The variable x
specifies the noise sample to compute, giving random web entry to, even supposing it may perchance perchance well in the finest case be the value of an increasing counter. While x
is unsigned, it be honest to lunge values from a signed integer mark as input. Furthermore, the value 0 stays 0. The aim can, in diversified words, be aged adore a waveshaping purpose with a chaotic consequence for non-silence.
#outline FIBH32 2654435769UL // 32-bit Fibonacci hashing fixed #outline ROR32(x, r) ((uint32_t)(x)>> ((r) & 31) | ((uint32_t)(x)What about the
>>x + 16
above?