Less Chunky Audio and Better Timing

Less Chunky Audio and Better Timing

by ferris

This week I made a bunch more progress with emulator audio stuff!

It started with switching the audio backend from a simple .wav dump to using rodio, which got sound output to the speakers (on windows at least), but the implementation wasn't very solid. I later switched to the lower-level CPAL which solved a lot of these woes, although there's still some platform-specific bugs with that, but that situation will improve with time. I also improved the sound emulation quite a bit; envelopes are done with some community help and I removed some DC offset stuff I had put in for loudness as it would cause some nasty clicks/pops if the emulator ran too slow and the sound buffer underran (proper analog modelling of the circuitry after the DAC in the real system will fix this properly, but I don't want to work on that just yet).

I also did a bunch of cleanup work regarding timing of the emulated system. Now, all timing is counted in intervals of clock ticks rather than nanoseconds, which not only clears things up a little bit, but gave me the opportunity to double-check all of these intervals and make sure they make sense. Most of them were really straightforward, but I found some issues with one of the intervals in the hardware timer. The timer can operate at two speeds; a slower speed with a tick interval of 100us, and a faster one with a tick interval that the documentation claims is 20us. However, I found this smaller interval to actually be too slow.

In the intro to Galactic Pinball, there's a vocal sample.mp3) that's played by changing the volume of one of the voices on each timer tick using a multiple of this smaller interval. But in fact, compared to the real hardware, my emu was playing this sample too slowly (and so does that recording link, which I believe is output from the mednafen emulator). I ended up fixing this by taking a recording of the sample from real hardware, and then tweaking the timer algorithm and intervals in my emulator, recording that output, and comparing. As it turns out, the algorithm appears to be correct, as does the large timer interval; there seems to be very little (if any) drift/phasing based on that alone. The smaller interval, however, doesn't appear to be 20us after all - it actually appears to be 16.66us repeating. This works out to be almost exactly 333 clock ticks in length (which is a number that makes some sort of sense) and can make sense in the docs as well if they're rounding up (which they often do in other parts of the docs), and my recordings seem to agree, so that's rad. Of course, there is the possibility that other parts of the timing in the emulator is also wrong, and this is just compensation, but I don't believe this is the case after double-checking these and converting the timing to clock ticks this weekend. All of the pieces appear to be consistent as far as I can tell, and if nothing else, that's a pretty good feeling :)

This week will primarily focus on finishing up the last cpu/audio features and architectural details in order for it to be "feature complete but with a few bugs", so I can write up a list of tasks remaining for it to be a usable emulator and some contribution guidelines. My hope is that other folks in the Rust community will be able to contribute to the project while I put it on the backburner for a while. Worst case scenario is nobody jumps on it, but that's not too bad anyways, and best case is we end up with a pretty cool pure rust emulator! :)

Until next time!

Last Edited on Mon Jan 23 2017 05:52:30 GMT-0500 (EST)