e.g. arcade games like Punch Out!! that use 2A03 for music/sound but a separate CPU for the gametepples wrote:APU Frame IRQ isn't very useful in the NES. It's mostly for other applications of the 2A03, which may have no NMI source, to keep time.
Audio psuedo-code
Moderator: Moderators
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Audio psuedo-code
Re: Audio psuedo-code
Tracelogs mofo! Do you make them? ;DoRBIT2002 wrote:I've changed a few things related to the APU Frame Counter but the triangle lengthproblem hasn't changed in the scenario with Mario Bros I explained. Back to the drawingboard.
A quick trace of the game shows that it does the following with the triangle every 8 frames:
Code: Select all
- write $08 to $4008
- write $34 to $400A
- write $08 to $400B
[Frame]
- write $C0 to $4017
[Repeat only $4017 writes for 8 frames]
1) the 4008 write sets the linear load value to 8
2) the 400B write sets the reload flag
3) the 4017 write will clock linear. Since the reload flag is set, the counter is loaded with 8, and the reload flag is cleared
4) During the following frame, the frame counter will clock the linear counter 4 times, knocking it down to 4 by frame end
5) Another 4017 write will clock linear again, knocking it down to 3
6) During the following frame, linear gets clocked 4 more times, knocking it down to 0
7) Further clocks are irrelevant, and the linear will now silence the channel until 400B is written to again (won't happen for another 6 frames)
So the triangle should have ~2 frames of output, followed by ~6 frames of silence.
So start dumping trace logs to see if you're catching these writes correctly. And to see how many times your linear counter is being clocked, and if it's behaving appropriately.
EDIT:
Also I think there's only like 2 NES games that actually use the frame IRQs. Dragon Quest is one... and I think Shin 4 Nin Uchi Mahjong (MMC5) is the other. They may be others but those are the only two I know about.
Re: Audio psuedo-code
@oRBIT2002
You mentioned SMB' time summing sfx effect, clearing the level. It's produced by squares, NOT triangle. The only effect I know of triangle channel is SMB3' sliding sound effect.
You mentioned SMB' time summing sfx effect, clearing the level. It's produced by squares, NOT triangle. The only effect I know of triangle channel is SMB3' sliding sound effect.
Re: Audio psuedo-code
@Zepper: I think he's talking about the music during the bonus stages of Mario Bros (not "Super" Mario Bros... but the other one -- the one with the POW blocks). Which uses the Triangle.
Re: Audio psuedo-code
Yes, I mean "Mario Bros". I've fixed a few errors but it hasn't affected the triangle length yet so probably I've got a bug elsewhere with my audiocode..
Re: Audio psuedo-code
Regarding the triangle code...
Something's different here in my emu...
Code: Select all
Clock_QuarterFrame:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ORIGINAL
; quarter frame clocks Linear
if( linear_reload )
linear_counter = linear_load
else if( linear_counter > 0 )
--linear_counter
if( !linear_control )
linear_reload = false
Code: Select all
Clock_QuarterFrame:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; quarter frame clocks Linear
if( linear_reload ) {
linear_counter = linear_load
if( !linear_control )
linear_reload = false
} else if( linear_counter > 0 )
--linear_counter
Re: Audio psuedo-code
@Zepper:
Both of those should have the same result.
@oRBIT:
Tracelogs tracelogs tracelogs.
Spit out a line of text at each of the following events:
- 4008-400B writes
- 4017 writes
- linear clocks
- Frame start
On each line, include the contents of the Linear Counter so you can see how it's being updated. If you can see where your counting is going wrong, you can see where the problem in your code is.
Both of those should have the same result.
@oRBIT:
Tracelogs tracelogs tracelogs.
Spit out a line of text at each of the following events:
- 4008-400B writes
- 4017 writes
- linear clocks
- Frame start
On each line, include the contents of the Linear Counter so you can see how it's being updated. If you can see where your counting is going wrong, you can see where the problem in your code is.
Re: Audio psuedo-code
I detected the error, you mentioned
"3) the 4017 write will clock linear. Since the reload flag is set, the counter is loaded with 8, and the reload flag is cleared"
I didn't see that in your psuedocode that the reloadflag is cleared during that condition. This is mentioned concerning "linear_reload=false":
if( !linear_control )
linear_reload = false
Perhaps I've missed something else..
I am slightly confused about $4017.. When bit 7 is set, should all channels immediately clock (quarter/half-frames)? Because when I do that, most sounds are bit "cut off" so I'm probably doing it wrong.
"3) the 4017 write will clock linear. Since the reload flag is set, the counter is loaded with 8, and the reload flag is cleared"
I didn't see that in your psuedocode that the reloadflag is cleared during that condition. This is mentioned concerning "linear_reload=false":
if( !linear_control )
linear_reload = false
Perhaps I've missed something else..
I am slightly confused about $4017.. When bit 7 is set, should all channels immediately clock (quarter/half-frames)? Because when I do that, most sounds are bit "cut off" so I'm probably doing it wrong.
Re: Audio psuedo-code
The frame counter is probably the most confusing and hardest part of the APU.I am slightly confused about $4017.. When bit 7 is set, should all channels immediately clock (quarter/half-frames)? Because when I do that, most sounds are bit "cut off" so I'm probably doing it wrong.
But yeah -- a $4017 write immediately triggers a quarter+half frame clock. Though I may have been wrong about the channel being clocked 4 times during the frame -- looking again at the wiki it should only be clocked 3 times + 1 for the $4017 write resulting in a total of 4 clocks per frame instead of the previously mentioned 5.
See this page for ref:
http://wiki.nesdev.com/w/index.php/APU_Frame_Counter
Note how there's a "blank step" in before that final half-frame clock in the 5-step sequence. That blank step should prevent the final clock from occurring because the $4017 write will happen first, which will restart the sequence from the top.
Re: Audio psuedo-code
This was a godsend. I had a lot of trouble understanding the APU, but reading / implementing the pseudocode made me understand it better. I also got pulse output! Thanks a lot.
Re: Audio psuedo-code
Yeah this helped things alot. Disch is my number one hero at the moment.
Re: Audio psuedo-code
I've discovered something strange in my APUcode. The triangle-related code is sometimes causing my emulator to slow down more or less randomly for a few secs, and then it continues at full frame rate again.
It looks something like this in psuedo:
...
If I comment away the filtering part (filtering algorithm described earlier in this thread), the problem goes away. If I let RenderTriangleData() always return zero (=0), problem goes away.
My first guess is that I had some loop that's not working correctly (since framerate drops from 60 to 20-30) but no, it doesn't seem to be related to a buggy loop or something similar..
There doesn't seem to be any exceptions going on either that might be causing this..
The puzzlepieces doesn't fit together here so I'm scratching my head a little, so if anyone got some nice ideas that you'd like to share, feel free..
It looks something like this in psuedo:
...
Code: Select all
TriangleOutput=RenderTriangleData();
TriangleOutput=DoFiltering(TriangleOutput);
..
MixAllChannels();
My first guess is that I had some loop that's not working correctly (since framerate drops from 60 to 20-30) but no, it doesn't seem to be related to a buggy loop or something similar..
There doesn't seem to be any exceptions going on either that might be causing this..
The puzzlepieces doesn't fit together here so I'm scratching my head a little, so if anyone got some nice ideas that you'd like to share, feel free..
Re: Audio psuedo-code
Just discovered that the triangle filter-algorithm "killed" my CPU more or less. The problem was floating point calculations, obviously the c#/x86 code wasn't up for the task, but converting it to "fixed point" saved the day. A friend of mine helped me discover this nasty one...
Re: Audio psuedo-code
We wary of denormal numbers. Set very tiny floating point values to 0 to avoid performance issues.oRBIT2002 wrote:Just discovered that the triangle filter-algorithm "killed" my CPU more or less. The problem was floating point calculations, obviously the c#/x86 code wasn't up for the task, but converting it to "fixed point" saved the day. A friend of mine helped me discover this nasty one...