Audio psuedo-code

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Audio psuedo-code

Post by rainwarrior »

tepples 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.
e.g. arcade games like Punch Out!! that use 2A03 for music/sound but a separate CPU for the game
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Re: Audio psuedo-code

Post by Disch »

oRBIT2002 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.
Tracelogs mofo! Do you make them? ;D

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]
This will do the following:

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.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Audio psuedo-code

Post by Zepper »

@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.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Re: Audio psuedo-code

Post by Disch »

@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.
User avatar
oRBIT2002
Posts: 687
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Audio psuedo-code

Post by oRBIT2002 »

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..
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Audio psuedo-code

Post by Zepper »

Regarding the triangle code...

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
Something's different here in my emu... :roll: :wink: :wink:

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
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Re: Audio psuedo-code

Post by Disch »

@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.
User avatar
oRBIT2002
Posts: 687
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Audio psuedo-code

Post by oRBIT2002 »

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. :)
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Re: Audio psuedo-code

Post by Disch »

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.
The frame counter is probably the most confusing and hardest part of the APU.

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.
fred
Posts: 67
Joined: Fri Dec 30, 2011 7:15 am
Location: Sweden

Re: Audio psuedo-code

Post by fred »

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.
User avatar
oRBIT2002
Posts: 687
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Audio psuedo-code

Post by oRBIT2002 »

Yeah this helped things alot. Disch is my number one hero at the moment. :)
User avatar
oRBIT2002
Posts: 687
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Audio psuedo-code

Post by oRBIT2002 »

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:
...

Code: Select all

TriangleOutput=RenderTriangleData();
TriangleOutput=DoFiltering(TriangleOutput);

..
MixAllChannels();
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.. :)
User avatar
oRBIT2002
Posts: 687
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Audio psuedo-code

Post by oRBIT2002 »

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...
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Audio psuedo-code

Post by zeroone »

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...
We wary of denormal numbers. Set very tiny floating point values to 0 to avoid performance issues.
Post Reply