APU Noise Channel
Moderator: Moderators
APU Noise Channel
Alright, so. I've been trying to fix the noise channel in my emulator, and almost every emulator source I try to use as a reference disagree with one another.
And none of them seem to work properly in my emulator.
The sound generated from this channel is like nails on a chalk board, and is ultra random (sometimes it crackles your speakers so much, it sounds like they are going to explode, other times it's dead silent when it should be generating sound).
http://www.filesend.net/download.php?f= ... 44d4ef0a84
There is a link to the recorded sound (Mega Man 3 intro, wooo). I can supply code as well, if need be.
EDIT: Forgot my question, lol. To start, which documents should I be using?
And none of them seem to work properly in my emulator.
The sound generated from this channel is like nails on a chalk board, and is ultra random (sometimes it crackles your speakers so much, it sounds like they are going to explode, other times it's dead silent when it should be generating sound).
http://www.filesend.net/download.php?f= ... 44d4ef0a84
There is a link to the recorded sound (Mega Man 3 intro, wooo). I can supply code as well, if need be.
EDIT: Forgot my question, lol. To start, which documents should I be using?
You are simulating the shift register and XOR operators to get proper NES noise, right? NES noise channel outputs either 0 or the channel's amplitude. It looks like a square wave with a random period.
Sounds like you are overflowing something into the negatives.
Sounds like you are overflowing something into the negatives.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Here is how I'm manipulating the Shift Register, etc.
It looks nothing like what the wiki describes (it's reversed bits, actually), but this is the only way it sounds proper. And it only sounds proper when used for music (intro sequences, etc).
Code: Select all
int bit0 = (this.shiftRegister & 0x4000) >> 14;
int bit1 = (this.shiftRegister & this.xor_tap) != 0 ? 1 : 0;
this.shiftRegister |= (bit0 ^ bit1);
this.shiftRegister <<= 1;
Code: Select all
noiseMode = (data & 0x80) != 0;
xor_tap = (noiseMode) ? 0x100 : 0x2000;
I'm not sure why you're reversing things. Anyway, your code inserts the new bit at the wrong time. You should do the shift before ORing the feedback in, not after.
BTW, here's a tested direct translation of the Wiki page to C:
BTW, here's a tested direct translation of the Wiki page to C:
Code: Select all
int other_bit = loop ? 6 : 1;
int feedback = (n & 1) ^ (n >> other_bit & 1);
n = n >> 1;
n = n | (feedback << 14);
Thanks blargg!
Another question I have about the noise channel is the frequency calculation.
This is what the no$ docs say about it:
Is this accurate? I think some of my noise problems could be an invalid frequency.

This is what the no$ docs say about it:
Code: Select all
400Eh - APU Frequency Channel 4 (Noise)
0-3 Noise frequency, F=1.79MHz/2/(N+1)
GBATEK is almost the bible for GBA and DS, but his EveryNES isn't always easy to understand. In this case, the frequency written to the noise channel is not used directly. Instead, it's an index into a lookup table:
The CPU clock is divided by two times the value from this LUT.002,004,008,010,020,030,040,050,065,07F,0BE,0FE,17D,1FC,3F9,7F2
Like this?
I'm still getting this weird effect in my noise channel, would actually hearing it do anything to diagnose the problem?
Code: Select all
public override void SetRegister3(byte data)
{
noiseMode = (data & 0x80) != 0;
if (this.Nes.RegionFormat == NesRegionFormat.Ntsc)
{
this.FrequencyTimer = NoiLut[0][data & 0x0F] * 2;
}
else
{
this.FrequencyTimer = NoiLut[1][data & 0x0F] * 2;
}
this.UpdateFrequency();
}