Bit Depth and Sample Rate of NES Waveform and DPCM Chans?

Discuss NSF files, FamiTracker, MML tools, or anything else related to NES music.

Moderator: Moderators

Post Reply
User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Bit Depth and Sample Rate of NES Waveform and DPCM Chans?

Post by Laserbeak43 » Sun Jan 03, 2010 4:44 pm

hello can someone please tell me the bit-depth and sample-rates of each individual channel? thanks. oh also, since it all comes out on the same output, would that mean it's all output and the same depth and rate anyway? well if it were at a lower rate and depth it would still keep its characteristics, so it's still important to know, right?
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

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

Post by tepples » Sun Jan 03, 2010 5:49 pm

The first four channels have 4-bit DACs, but they're not mixed equally. The DPCM goes to a 7-bit channel. See also complete APU docs.

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Sun Jan 03, 2010 7:23 pm

simple as that hah? i dunno why i've expected more... ok. when i figure out what to ask, i'll be back :D
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

skrasms
Posts: 45
Joined: Mon Jan 14, 2008 7:20 pm
Location: Portland, OR

Post by skrasms » Sat Jan 09, 2010 7:05 pm

Given how you asked your question, it sounds like you're thinking in terms of PCM audio. It's a little bit different when talking about what the 2A03 does.

Take the triangle wave, for example. It does not have a constant sample rate. It has a constant set of values that get read back at different sample rates to produce different pitches. A modern digital synthesizer would have a constant sample rate and "resample" the triangle wave data instead (or use entirely different methods).

As a more confusing example, the noise generator is only 1 bit. However, it goes through a 4-bit DAC to allow amplitude adjustment. So the quietest noise wave will switch between 0 and 1, while the loudest will switch between 0 and 15. The 1-bit sequence comes from a linear feedback shift register, which was (and still is) a simple way of random number generation in hardware.

Then there's the DMC channel. The sample rate here depends on if you are using DPCM or PCM. Direct writes to the 7-bit DAC can be done through register $4011, meaning the sample rate will depend entirely on how quickly your code handles those writes. On the other hand, using DPCM there are preset sample rates. I seem to remember DPCM only exercising 6 actual bits from the DAC here, but I could be incorrect.

Then of course it all the channels add together in a non-linear way. There's a lot of reading to do if you really want all the details.

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Sat Jan 09, 2010 10:28 pm

wow, i didn't even know most of that stuff. Different sample rates!! interesting. I should look into making a shift register for random values in hardware. Never heard of that one.

Thanks for all of that information. What doc gave you all of that? (Brad Taylor's? I'd assume it's that one, cause it's the one i find most confusing.)
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

skrasms
Posts: 45
Joined: Mon Jan 14, 2008 7:20 pm
Location: Portland, OR

Post by skrasms » Sun Jan 10, 2010 1:50 am

Laserbeak43 wrote:wow, i didn't even know most of that stuff. Different sample rates!! interesting. I should look into making a shift register for random values in hardware. Never heard of that one.

Thanks for all of that information. What doc gave you all of that? (Brad Taylor's? I'd assume it's that one, cause it's the one i find most confusing.)
This is guaranteed to be a rambling post, so be warned...

I said random, but it's not *truly* random because it creates a sequence that will eventually repeat. That repetition is what gives the NES and Atari "pitched" noise sounds. As the shift register gets longer so does the sequence, until a long enough sequence sounds like pure white noise.

The thing is, current synthesis is all resource-intensive DSP. When arcades needed soundchips, they didn't have all the memory and processing power available that we do now. These days it is about optimizing software methods for sound generation. Back then, it was about getting the most mileage out of simple logic circuits and transistors. Even though the circuits are "digital" in the sense of being logic-based, there are things going on that can't be copied directly in the modern software world.

I noticed from another post that you seem to be trying to emulate 2A03 sounds in software. One of the main issues you will run into, if you haven't already, is that you will have all kinds of aliasing problems if you generate these waveforms the naive way.

Say you want to make a square wave. The naive way would be to make something that switches between high and low values instantly, making a pattern like this with the samples (values are arbitrary):

-500
1000
-500
1000
...

or an octave lower:
-500
-500
1000
1000
-500
-500
1000
1000

There are two big problems with this right away. First, the frequency will only be accurate when it is an integer division of the sample rate. If that's not the case then jitter will occur.

Suppose that's good enough, though, and non-integer-division frequencies are lame anyway. That naive square wave is easy to code and will look perfect on the screen, but it will not sound good compared to an actual 2A03 square wave. The problem is that instantaneous switching requires an *infinite* frequency response. If you look up the frequency spectrum of a square wave, you'll see a fundamental frequency plus harmonics that extend far off into the distance. That is what you get in the hardware world, though the very high frequency harmonics will roll off because circuits can only change so quickly...

Back in the software domain, though, we don't have infinite frequency response. We know that whatever our sample rate is, no frequencies greater than half that will be recreated properly. In fact, any frequencies higher will fold back down as new erroneous frequencies! By creating a square wave with the "naive" method, that is exactly what happens. All the harmonics of the square wave that occur naturally will become errors if they are greater than half the sample rate. What's even worse, since we are in the pristine digital domain, we get as many harmonics as mathematically possible! Even though higher and higher harmonics are eventually rolled off enough to be below the noise floor, there will be a whole lot of garbage piling up until then.

We really want a square wave that is 100% accurate as far as the frequency response of the digital system can get us. So how can we make a square wave with only frequencies less than half the sample rate?

This is where band-limited impulse trains (BLIT) work wonders. They use very simple signals (mainly a sinc function) and some relatively simple calculus concepts to create square waves (among other waves) that don't alias. If you're looking to emulate hardware, this is really the place to start.

Hopefully I'm somewhat correct in guessing what you are trying to do. If not, the rambling was still fun.

lidnariq
Posts: 8792
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Post by lidnariq » Sun Jan 10, 2010 10:13 am

skrasms wrote:Take the triangle wave, for example. It does not have a constant sample rate. It has a constant set of values that get read back at different sample rates to produce different pitches.
It's more manageable than that -- the NES always generates audio at 1.8MHz. Each of the audio channels change (or have the option to change) their value after a certain number of samples.

For example, the loop size of the triangle wave channel can be thought of as being 32 samples long. If a period of (e.g.) 1000 were written to the control registers, the location in the 32-sample loop would advance once every 1000** samples out of the NES. So the resultant stretched sound would be 32*1000 samples long, and so would product a tone at 1.8MHz / 32000 = 56 Hz


** Actually 1001, because something adds one, but that makes the description less clear.

skrasms
Posts: 45
Joined: Mon Jan 14, 2008 7:20 pm
Location: Portland, OR

Post by skrasms » Sun Jan 10, 2010 11:20 am

lidnariq wrote:
skrasms wrote:Take the triangle wave, for example. It does not have a constant sample rate. It has a constant set of values that get read back at different sample rates to produce different pitches.
It's more manageable than that -- the NES always generates audio at 1.8MHz. Each of the audio channels change (or have the option to change) their value after a certain number of samples.

For example, the loop size of the triangle wave channel can be thought of as being 32 samples long. If a period of (e.g.) 1000 were written to the control registers, the location in the 32-sample loop would advance once every 1000** samples out of the NES. So the resultant stretched sound would be 32*1000 samples long, and so would product a tone at 1.8MHz / 32000 = 56 Hz


** Actually 1001, because something adds one, but that makes the description less clear.
It is true that the variable sample rate will be an integer division of the 1.79 MHz master clock, but I'm not sure how that makes it more manageable. I think that's just semantecs, though. It can be seen as a variable sample rate signal with sample rates based on integer divisions of 1.79MHz, or it can be seen as a system with a single 1.79 MHz sample rate.

The end results are the same in the hardware world, but thinking about it as the latter can be misleading *if* you think in terms of normal digital signal processing.

I think of it like the former (variable sample rate) so that it can be accurately emulated in a 44.1 kHz environment with less confusion.

lidnariq
Posts: 8792
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Post by lidnariq » Mon Jan 11, 2010 8:35 am

skrasms wrote:The end results are the same in the hardware world, but thinking about it as the latter can be misleading *if* you think in terms of normal digital signal processing.
Speaking as a DSP person, I find the math (and therefore comprehension) a whole lot clearer without the hidden downsampling step in the middle. (And then ending everything with "throw it into libsamplerate to transform to the highest sample rate supported by the soundcard")
I think of it like the former (variable sample rate) so that it can be accurately emulated in a 44.1 kHz environment with less confusion.
If you're used to thinking of things as wavetables, your method definitely makes more sense. But both phase restarts and the noise channel for the highest 4 sample rates are harder to do easily/right if you directly synthesize at audio rates.

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

Post by tepples » Mon Jan 11, 2010 8:49 am

Any signal from the NES, Game Boy, or similar designs based on a variable-rate sample-and-hold DAC can be represented as a sum of Heaviside steps. For example, a square wave consists of two steps per period, one positive and one negative. So one way to render the signal is to make a set of pre-filtered step responses at various fractional sample delays, decompose the APU's output into a series of steps, and then sum them to synthesize the audio. The blip-buf library does this.

skrasms
Posts: 45
Joined: Mon Jan 14, 2008 7:20 pm
Location: Portland, OR

Post by skrasms » Mon Jan 11, 2010 9:33 am

tepples wrote:Any signal from the NES, Game Boy, or similar designs based on a variable-rate sample-and-hold DAC can be represented as a sum of Heaviside steps. For example, a square wave consists of two steps per period, one positive and one negative. So one way to render the signal is to make a set of pre-filtered step responses at various fractional sample delays, decompose the APU's output into a series of steps, and then sum them to synthesize the audio. The blip-buf library does this.
Yes, and the point I was trying to make is that Heaviside steps will alias if you make them directly. Instead it is often better to make a sinc function (a band-limited impulse) and integrate it. That is exactly what blip-buf does. It is the BLIT method that I mentioned.

Post Reply