A reader (you know who you are!) proposed an interesting project that will involve measuring audio passbands and suggested using white noise to show the entire shape on a spectrum analyzer. He pointed me at the NOISE 1B Noise Generator based on a PIC microcontroller, which led to trying out the same idea on an Arduino.
The first pass used the low bit from the Arduino runtime’s built-in random()
function:

Well, that’s a tad pokey for audio: 54 μs/bit = 18.5 kHz. Turns out they use an algorithm based on multiplication and division to produce nice-looking numbers, but doing that to 32 bit quantities takes quite a while on an 8 bit microcontroller teleported from the mid 1990s.
The general idea is to send a bit from the end of a linear feedback shift register to an output to produce a randomly switching binary signal. Because successive values involve only shifts and XORs, it should trundle along at a pretty good clip and, indeed, it does:

I used the Galois optimization, rather than a traditional LFSR, because I only need one random bit and don’t care about the actual sequence of values. In round numbers, it spits out bits an order of magnitude faster at 6 μs/bit = 160 kHz.
For lack of anything smarter, I picked the first set of coefficients from the list of 32 bit maximal-length values at https://users.ece.cmu.edu/~koopman/lfsr/index.html:
0x80000057
.
The spectrum looks pretty good, particularly if you’re only interested in the audio range way over on the left side:

It’s down 3 dB at 76 kHz, about half the 160 kHz bit flipping pace.
If you were fussy, you’d turn off the 1 ms timer interrupt to remove a slight jitter in the output.
It’s built with an old Arduino Pro Mini wired up to a counterfeit FTDI USB converter. Maybe this is the best thing I can do with it: put it in a box with a few audio filters for various noise colors and be done with it.
It occurs to me I could fire it into the 60 kHz preamp’s snout to measure the response over a fairly broad range while I’m waiting for better RF reception across the continent.
The Arduino source code as a GitHub Gist:
// Quick test for random bit generation timing | |
// Ed Nisley KE4ZNU - 2017-10-25 | |
// Observe output bit on an oscilloscope | |
// LFSR info https://en.wikipedia.org/wiki/Linear-feedback_shift_register | |
// This code uses the Galois implementation | |
// Coefficients from https://users.ece.cmu.edu/~koopman/lfsr/index.html | |
#define PIN_RND 13 | |
#include <Entropy.h> | |
uint32_t Rnd; | |
byte LowBit; | |
void setup() { | |
Serial.begin(57600); | |
Serial.println("Random bit timing"); | |
Serial.println("Ed Nisley KE4ZNU - 2017-10-25"); | |
Entropy.initialize(); | |
pinMode(PIN_RND,OUTPUT); | |
uint32_t Seed = Entropy.random(); | |
Serial.print("Seed: "); | |
Serial.println(Seed,HEX); | |
randomSeed(Seed); | |
do { | |
Rnd = random(); | |
} while (!Rnd); // get nonzero initial value | |
} | |
void loop() { | |
// digitalWrite(PIN_RND,Rnd & 1); // about 55 us/bit | |
// Rnd = random(); | |
LowBit = Rnd & 1; | |
digitalWrite(PIN_RND,LowBit); // about 6 us/bit | |
Rnd >>= 1; | |
Rnd ^= LowBit ? 0x80000057ul : 0ul; | |
} |