APU stuff

APU stuff
by on (#3798)
Okay, normally I don't have an issue dissecting tech docs, but audio is not my strong point. On to the questions...

1) Are the 11 bit programmable timers (wavelength) clocked every CPU cycle, or at the start of a duty cycle? I ask this because freq = 1.79 MHz / wavelength / 16? but doesn't this depend on the duty cycle type? very confused

2) What is the sample rate of the apu? If the audio units can produce freqs in the 50k range, then the sample rate must be greater than 44k.

3) Why can there units produce sound at that high of a freq? Humans can't hear above 20k! Dog whistle??

Any help better understanding or breaking this down would be very helpful for everyone I think. Maybe once a have something working I can figure out the rest of my confusion.

by on (#3800)
1) The timers are clocked by the 1.79 MHz CPU clock. The duty cycle has no effect on the fundamental frequency (only on the harmonics).

2) The APU's sample rate is 1.79 MHz.

3) It's simpler to allow super-audible frequencies in hardware, so it's possible to generate sound with all harmonics above 20 kHz.

Feel free to ask further questions, no matter howsimple. BTW, which APU docs are you using?

by on (#3802)
I thought you would be the first to respond blargg :)
Quote:
BTW, which APU docs are you using?

2A03 technical reference.txt
apu_ref.txt
everynes.html
nessound.txt

Let's make the mud a little more clear.

So, once the 11 bit timer is loaded with value X and the channel is enabled, then X is decramented every CPU cycle and a value is outputted based on X's value relative to the duty cycle? Assume the most basic setup of the square wave.

Ex. if X = 8 and duty cycle type is 2 then
CPU Clock 012345678
SQ1 Output HHHHLLLL

H is High
L is Low

Which would generate a sound at 1.79MHz / 8 = 222500Hz ?

by on (#3804)
The frequency written to the 11 bit timer counts down before the duty cycle counter is adjusted... so in this sense there's actually two counters.

- Frequency counter counts down every cycle
- When frequency counter reaches 0, it's reloaded and the duty cycle counter is incremented (wrapping at 7->0).
- Output is based on the duty cycle counter's position. The value in the frequency counter is irrelevent.

by on (#3809)
Here's a concrete example:

$4002 = $09
$4003 = $00 (only the low 3 bits are are used)

The raw wavelength is $009. The timer's period is set to double this plus two, which is 9*2+2=20 in this case. So every 20 clocks the timer reaches zero, reloads, and clocks the duty unit. The duty unit has 8 steps no matter what mode it's in, so the output wave's period will be 20*8=160 clocks, or 11.2 kHz. In mode 2 the duty unit outputs a square wave, so the steps are divided evenly between 0 and 1. The output will be:

Code:
Duty  : 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
Output: 00000000111111110000000011111111

10 clocks per unit

by on (#3811)
Disch I think you may have made the light come on. So that I am sure I understand, let's try one last example. (I learn by others correcting)

duty cycle type of 4 (-_----)
$4002 = $D0
$4003 = $07 (only the low 3 bits are are used)

period = ($7D0 + 1) * 2 = 4002 (roughly 4000 so....)
which is a wave at 1.79MHz / 4002 = 445 or roughly a middle C?
Code:
   
CPU in thousnads of cycles : _________ 01234567890123456789012345
Duty Cycle Timer : ___________________ 0  1  2  3  4  5  6  7 
output : _____________________________ HHHLLLLLLHHHHHHHHHHHHHHH

by on (#3812)
Quote:
period = ($7D0 + 1) * 2 = 4002


That's the cycle delay between duty unit updates. every 4002 cycles, the duty unit will take another step. When it makes 8 steps, it completes a full wave. Therefore your following formula is off

Quote:
which is a wave at 1.79MHz / 4002 = 445


it would be 1.79MHz / (4002 * 8) = ~55.9 Hz -- a very low tone -- nowhere near middle C (you multiply by 8 because the duty unit needs to be clocked 8 times to generate one repitition of the square wave)


The tone to period formula works like so:

ToneInHz = 1789772.7272 / ( (F + 1) * 2 * 8 )

Where F is the 11-bit frequency value. Or, to work that so that you can plug in a tone and get the required F value:

F = ( 1789772.7272 / (2 * 8 * ToneInHz) ) - 1


So to do A-440, you'd write $0FD to the frequency.

by on (#3815)
Ok, Thanks. I guess it would help if I looked up that middle C is in fact 261Hz and A is 440Hz. And now I understand why you multiply by 8. I might get my emulator squicking this week after all. I *think* all of my initial questions are answered. Thanks everyone.