I haven't found a believable documentation for it, so took a whack at the SAA1099 noise generator and decided to document it.

It is possible that the exact noise generator algorithm was already known, but it may be written in different form (Galois vs Fibonacci, left shift vs right shift, etc).

I controlled the chip to generate noise at some sane speed (about 3500 Hz update rate) and recorded it on another PC.

Visual inspection revealed that the noise has a period of approximately 262000 bits. That's about 2^18 bits, not a coincidence. Also, the longest low period encountered was 17 bits, and longest high period encountered was 18 bits.

This revealed it most likely is a 18-bit maximal length LFSR with period of 262143 bits. Not all sound chips use a maximal length LFSR, so never assume it is. Given the longest periods seen, the 18-bit period must be ones out from the LFSR, and the 17-bit period must be zeroes, as an LFSR can't have all bits zero or it's stuck with zeroes.

And since there are many tap configurations that can do it, most likely it's one with least amount of feedback taps, because why waste precious silicon area. Turns out the minimum tap count is two and there are only two different tap configurations (well, just one and it's reverse). After finding a good starting point in the stream, the next bits easily reveal the feedback taps, so it was easy to determine which one it is with pen and paper.

- Code: Select all
`int saa1099_prng(void)`

{

static uint32_t lfsr=1; // seed unknown, must be non-zero

/*

SAA1099P noise generator as documented by Jepael

18-bit Galois LFSR

Feedback polynomial = x^18 + x^11 + x^1

Period = 2^18-1 = 262143 bits

Verified to match recorded noise from my SAA1099P

*/

if (lfsr&1)

{

lfsr=(lfsr>>1)^0x20400;

return 1;

}

else

{

lfsr=(lfsr>>1);

return 0;

}

}

Then a comparison of recorded noise versus noise generated with above algorithm:

- SAA1099 noise comparison

Looks like a match, and it continues to match throughout the waveform, until the 262143-bit noise period ends. I can't believe I actually got it to match at first try.

What's next? I don't know, but I ran into some undocumented feature that enables higher noise frequencies than the ones documented.. Oh and current emulators tend to understand "mixing" noise and tone channels rather differently how the chip actually does it.