At long last, we have working audio! Well, kind of anyway. I’ve implemented the register settings and a good bit of the behavior for the two Pulse channels, which is already enough to get decent sounding audio out of most games, despite lacking some features. Because I haven’t figured out Rust’s audio output capabilities yet, I first worked on getting audio on-screen:
Despite looking an awful lot like a square wave and animating roughly in time with the mario theme, this implementation left a lot to be desired. I quickly learned that one sample per CPU cycle, while very, very hardware accurate, results in 1.7 MHz audio, which is just a bit too much. So much that when I tried to dump it out, my emulator ground to a halt just dealing with the data flow. No good.
Some research and a 44.1 KHz sample rate implementation later, I finally got Zelda II to produce the following raw audio dump:
Not bad! Not good either, this is just the frequency data being turned into pulse clocks with no extra features, but it definitely produces the right notes. I noticed that Zelda II was modulating the pitch all on its own… could it perhaps be setting the volume too? I quickly implemented direct volume control, and was pleasantly surprised by the result:
This is pretty good for not having implemented volume envelopes or the frequency sweep register! As it turns out, a lot of games simply don’t use these features very often, leading to pleasant sounding music with just 2 incomplete channels in place:
Super Mario Bros:
The music sounds pretty great! Sound effects not so much, Mario’s jump in particular is making use of the unimplemented sweep unit. This will be a great test case!
The menu’s a bit unfortunate, and I’m pretty sure I’ll need either length counters, or the sweep register and automatic muting to take care of it. More interesting though, battle scenes now crash when selecting an attack! Investigating that will be fun later…
Castlevania II: Simon’s Quest:
The audio here is really good! Unfortunately my playing is not– I tried to head left to record the overworld audio, and promptly died a LOT. This is NES hard at its finest.
Overall, I’m pretty happy with this! Now my challenge is to get Rust outputting the audio directly, and then it’ll just be a matter of implementing the rest of the channels. I can also use hook up the new Audio IRQ and finally run some of the CPU timing tests, which are badly needed; at this point my CPU is still wildly overclocked and in dire need of work in the timing department.