Square's decay volume confusion
Moderator: Moderators
Square's decay volume confusion
My implimentation of the square channels involves keeping two seperate volume levels. One is the volume which is actually output by the channel... the other is the "decay volume", which is altered by the envelope/decay unit and is reset to $0F on $4003/$4007 writes. My understanding is that the decay volume is always altered by the decay unit, regardless of whether or not decay is enabled... however if decay is disabled, the output volume is unaltered by the decay unit.
My old implimentation was like the following:
on $4003 write:
- set decay volume to $0F
- if decay is enabled, set output volume to $0F as well
Doing it this way... someone (koitsu probably) brought Shin Onigashima.nsf to my attention. Apparently the first track on this nsf gets crackly and poppy with this implimentation. So with that in mind... I removed the above portion in my new implimentation and leave the output volume unaltered on $4003 writes (only updating the output volume on decay unit clocks). This solved the NSF problems.
However, someone else has brought this problem up with a test ROM... implying that the old implimentation was correct.
Can anyone give me a definative answer on which method is correct? is the Shin Onigashima NSF supposed to be crackly?
I tried the NSF and test ROM in Nintendulator and FCEU. Nintendulator seems to do my old implimentation -- it plays the test rom fine but crackles the nsf. FCEU, oddly, plays both fine... I don't know what it's doing.
Anyway, any help appreciated.
My old implimentation was like the following:
on $4003 write:
- set decay volume to $0F
- if decay is enabled, set output volume to $0F as well
Doing it this way... someone (koitsu probably) brought Shin Onigashima.nsf to my attention. Apparently the first track on this nsf gets crackly and poppy with this implimentation. So with that in mind... I removed the above portion in my new implimentation and leave the output volume unaltered on $4003 writes (only updating the output volume on decay unit clocks). This solved the NSF problems.
However, someone else has brought this problem up with a test ROM... implying that the old implimentation was correct.
Can anyone give me a definative answer on which method is correct? is the Shin Onigashima NSF supposed to be crackly?
I tried the NSF and test ROM in Nintendulator and FCEU. Nintendulator seems to do my old implimentation -- it plays the test rom fine but crackles the nsf. FCEU, oddly, plays both fine... I don't know what it's doing.
Anyway, any help appreciated.
He's asking this because I noticed that some games's sound is off in his emu, so I went to my beloved SNDTest rom (made by someone else. ), and set the registers as follows:
4000 - %10001000
4001 - %00000000
4002 - %10000000
4003 - %00000000
This makes a simple beep noise. In Disch's emu, the beep has a 'fade in' type effect in it (the volume isn't full at the start... it's seemingly random, and then it goes full, as though he's not resetting the volume right away), and I don't think that's right, as Nintendulator doesn't do this, and neither does anything else I've tried.
4000 - %10001000
4001 - %00000000
4002 - %10000000
4003 - %00000000
This makes a simple beep noise. In Disch's emu, the beep has a 'fade in' type effect in it (the volume isn't full at the start... it's seemingly random, and then it goes full, as though he's not resetting the volume right away), and I don't think that's right, as Nintendulator doesn't do this, and neither does anything else I've tried.
0.960 when?
I don't see any releases newer then 0.900 in Nintendulator's file list nor newer than 0.950 on the web page.Quietust wrote:I can't hear the crackling you are referring to - are you using the latest version of Nintendulator?
The envelope unit section in the NES APU Reference is based on lots of hardware testing. Could it use improvement?
Here's the code I use, edited for clarity ("Shin Onigashima.nsf" sounds clean when playing with it):
Here's the code I use, edited for clarity ("Shin Onigashima.nsf" sounds clean when playing with it):
Code: Select all
bool env_enabled;
bool env_loop;
int env_period;
int env_delay;
int env_vol;
int volume;
void write_4000( int n )
{
env_loop = (n & 0x20) != 0;
env_period = (n & 15) + 1;
env_enabled = !(n & 0x10);
volume = env_enabled ? env_vol : n & 15;
// ...
}
void write_4003( int n )
{
env_reset = true;
// ...
}
void clock_envelope()
{
if ( env_reset )
{
env_reset = false;
env_vol = 15;
env_delay = env_period;
}
else if ( --env_delay == 0 )
{
env_delay = env_period;
if ( env_loop || env_vol > 0 )
env_vol = (env_vol - 1) & 15;
}
if ( env_enabled )
volume = env_vol;
}
I just wrote this simple test ROM which uses the volume envelope in a way that depends on some subtleties of its behavior. It also depends on some aspects of proper $4017 implementation. The archive contains the test ROM (iNES format), asm source, and a recording of output when run on a NES. It should play a sound slowly fading in then holding. I may make an NSF of it to test NSF players.
It moved! http://blargg.8bitalley.com/ripway/temp/test_apu_env.zip
It moved! http://blargg.8bitalley.com/ripway/temp/test_apu_env.zip
Awesome... seems to be working for me. Thanks for the test ROM... they're always a good thing =)
Btw, I've been meaning to ask you... your APU doc led me to believe that when $4017 is written to with the high bit set, the frame sequencer is clocked immediately (which this demo confirms). But when it's written to with the high bit off... it doesn't get clocked for ~7457 cycles. That's how I'm doing it anyway. Is that right? Or should I be clocking it immediately regardless of the high bit?
Thanks again blargg, you rock ;D
Btw, I've been meaning to ask you... your APU doc led me to believe that when $4017 is written to with the high bit set, the frame sequencer is clocked immediately (which this demo confirms). But when it's written to with the high bit off... it doesn't get clocked for ~7457 cycles. That's how I'm doing it anyway. Is that right? Or should I be clocking it immediately regardless of the high bit?
Thanks again blargg, you rock ;D
Correct, and the test ROM above relies on this to keep the envelope unit at a constant volume during each step of the test. Below wlp keeps resetting the APU just before 1/240 second would pass, effectively suspending envelope clocks:Disch wrote:Your APU doc led me to believe that when $4017 is written to with the high bit set, the frame sequencer is clocked immediately (which this demo confirms). But when it's written to with the high bit off... it doesn't get clocked for ~7457 cycles.
Code: Select all
ldy #16 ; y controls volume
loop:
lda #$08 ; schedule envelope reset on *next clock*
sta $4003
lda #$20 ; enable envelope now, with looping to expose bugs
sta $4000
; Play at current envelope volume and suspend
; envelope clocks to extend this for a while
ldx #80
wlp: lda #$40 ; reset sequencer *without* clocking envelope
sta $4017
lda #39 ; wait until just before envelope clock
jsr delay_01msec ; delays a*0.1 msec
dex
bne wlp
lda #$10 ; volume = 0, disable envelope
sta $4000
; Now clock envelope 'y' times. First clock will
; reset it to 15 (the write to $4003 at the top
; will finally take effect).
tya
tax
rlp: lda #$c0 ; reset sequencer and clock envelope now
sta $4017
dex
bne rlp
dey
bne loop
The envelope is clocked at approximately 240 Hz or 192 Hz, as described on the NESdevWiki: http://nesdevwiki.org/wiki/index.php/APU_Frame_Counter