Square duty cycle vs apu_mixer/square test
Posted: Tue Dec 20, 2016 7:51 pm
(This is pretty much a follow up of the conversation in Mesen's main thread, but I figured this might be better off as a thread of its own at this point)
So I've been taking another look at Mesen's square channel code, and looking at the "apu_mixer/square" test's code..
And there's something that I just can't make sense of.
In the test, square 2's duty cycle is set to 50%.
The code writes to $4007 to reset square 2's sequencer and sets the timer to 111 (i.e clock every 224 cpu cycles)
Then, it loops and writes 127 to $4011, 160 times in a row (each 896 cycles apart), before finally writing 123 on the 161th write.
The sequence looks like this, right after the $4007 write that causes the sequencer to reset to 0 (thus outputting 0 for the next 4 square cycles)
So odd writes (1, 3, #161) match with a "0" for the duty cycle and even writes (#2, #4, #160) match with a "1".
This means that the 161th write (value = 123) falls on a falling edge for the duty cycle (1 -> 0), which makes BOTH channels drop at the same time.
Considering the test is attempting to cancel both channels by applying the opposite change, that doesn't make sense. I would expect the exact opposite.
What am I not understanding?
Current problems I had with my code vs the wiki:
1- Writes to $4003/7 were resetting the sequencer AND the timer (instead of just the sequencer).
2- The sequencer was counting upwards instead of downwards.
(It looks like both of these might be "fixes" I took from puNES' code while attempting to make the apu_mixer tests work, but they both contradict the wiki)
After fixing these to match the wiki, I get a perfect match up (cycle-wise) between the square duty changes and the DMC writes, but the value of the square channel is always opposite of what it would need to be for it to cancel out the DMC's output.
At this point, if I invert the duty cycle so that the sequence after a $4007 write is 11110000 instead of 00001111, everything falls into place and the sound output is (to my ears) even closer to the apu_mixer/square recording than my older code.
Picture below is the (what I assume to be) NES recording that was bundled with the tests, Mesen's 0.5.3 output (bottom), and Mesen's current output if I fix both bugs, and invert the duty cycle like I said (middle).
Clearly the middle one is the closest to the recording - so what am I not getting?
So I've been taking another look at Mesen's square channel code, and looking at the "apu_mixer/square" test's code..
And there's something that I just can't make sense of.
In the test, square 2's duty cycle is set to 50%.
The code writes to $4007 to reset square 2's sequencer and sets the timer to 111 (i.e clock every 224 cpu cycles)
Then, it loops and writes 127 to $4011, 160 times in a row (each 896 cycles apart), before finally writing 123 on the 161th write.
The sequence looks like this, right after the $4007 write that causes the sequencer to reset to 0 (thus outputting 0 for the next 4 square cycles)
Code: Select all
DMC Value: 127 #1 127 #2 127 #3 ... (156 more writes) ... 127 #160 123 127 [...]
Square Output: 0 0 0 0 1 1 1 1 0 ... ... 1 1 1 1 0 0 0 0 1 1 1 1 [...]
This means that the 161th write (value = 123) falls on a falling edge for the duty cycle (1 -> 0), which makes BOTH channels drop at the same time.
Considering the test is attempting to cancel both channels by applying the opposite change, that doesn't make sense. I would expect the exact opposite.
What am I not understanding?
Current problems I had with my code vs the wiki:
1- Writes to $4003/7 were resetting the sequencer AND the timer (instead of just the sequencer).
2- The sequencer was counting upwards instead of downwards.
(It looks like both of these might be "fixes" I took from puNES' code while attempting to make the apu_mixer tests work, but they both contradict the wiki)
After fixing these to match the wiki, I get a perfect match up (cycle-wise) between the square duty changes and the DMC writes, but the value of the square channel is always opposite of what it would need to be for it to cancel out the DMC's output.
At this point, if I invert the duty cycle so that the sequence after a $4007 write is 11110000 instead of 00001111, everything falls into place and the sound output is (to my ears) even closer to the apu_mixer/square recording than my older code.
Picture below is the (what I assume to be) NES recording that was bundled with the tests, Mesen's 0.5.3 output (bottom), and Mesen's current output if I fix both bugs, and invert the duty cycle like I said (middle).
Clearly the middle one is the closest to the recording - so what am I not getting?