APU Noise Channel

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

APU Noise Channel

Post by beannaich » Wed Mar 31, 2010 12:47 pm

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?

beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Post by beannaich » Fri Apr 02, 2010 3:13 pm

Ok, got the channel working properly (I think). Noise used in music sounds fine now, but sound effects are a different question :S

Sound effects now sound like a high-frequency screech. Any idea what would cause this? I'm not using DC blocking or any other filtering, could that be the cause?

3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Fri Apr 02, 2010 3:17 pm

Welcome to the forums, I can't really help you there except for just read up online on some peoples homemade APU documents, or just wait for the other members to come on XD

User avatar
Dwedit
Posts: 4408
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Fri Apr 02, 2010 4:03 pm

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.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Post by beannaich » Fri Apr 02, 2010 5:29 pm

Here is how I'm manipulating the Shift Register, 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;
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).

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Fri Apr 02, 2010 6:54 pm

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:

Code: Select all

int other_bit = loop ? 6 : 1;
int feedback = (n & 1) ^ (n >> other_bit & 1);
n = n >> 1;
n = n | (feedback << 14);

beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Post by beannaich » Sat Apr 03, 2010 3:28 am

Thanks blargg! :D Another question I have about the noise channel is the frequency calculation.

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)
Is this accurate? I think some of my noise problems could be an invalid frequency.

tepples
Posts: 22277
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Sat Apr 03, 2010 3:51 am

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:
002,004,008,010,020,030,040,050,065,07F,0BE,0FE,17D,1FC,3F9,7F2
The CPU clock is divided by two times the value from this LUT.

beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Post by beannaich » Sat Apr 03, 2010 4:47 am

Like this?

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();
}
I'm still getting this weird effect in my noise channel, would actually hearing it do anything to diagnose the problem?

User avatar
Zepper
Formerly Fx3
Posts: 3223
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Sat Apr 03, 2010 6:38 am

- It may not be a matter of how you're generating signed/unsigned samples, but the way you're resample it and the amount of samples. In other words, AFAIK, you should generate the samples at same rate of the NES, or 1 sample per CPU cycle; and do some resampling method.

Post Reply