shonumi / gbe-plus

DMG/GBC/GBA emulator and experimental NDS emulator.
GNU General Public License v2.0
501 stars 79 forks source link

Metroid II - Sound effects play inaccurately #120

Open FateForWindows opened 2 years ago

FateForWindows commented 2 years ago

Almost all of the sound effects in Metroid II sound noticeably different compared to how they sound on a real Game Boy or most emulators. This appears to be due to inaccurate Ch.1 sweep emulation.

A lot of issues seem to be caused by frequency_samples in DMG_APU::generate_channel_1_samples not being updated when the frequency change is applied to the channel's output frequency. This can easily be "fixed" with a quick hack (add the lines to update frequency_samples after the respective output frequency change), but it still leaves a few more problems and I haven't tested other games to see if it created any regressions.

Sounds that are broken without "fix": Standard jump, fire, crouch, uncrouch, morph ball, land/turn, health pickup, missile pickup, health/missile full refill Sounds that have minor problems after "fix": Firing sound is still a little off (slightly inconsistent "crunchiness") Sounds that are still broken after "fix": Metroid hit sounds (excl. Omegas and the Queen)

shonumi commented 2 years ago

Thanks for catching this and reporting it!

It's indeed an issue of the samples not being updated in a timely fashion. For the DMG/GBC, GBE+ takes a somewhat lazy approach to generating samples (i.e. it's not based on the emulated CPU, a design choice I made years ago when I first started) but it works well enough if SDL can update everything fast enough. Changing the output frequency is one way, but the amount of samples SDL will process for each callback matters too.

Currently SDL waits until 1024 samples need to be processed. That's okay for most games, but if quicker updates than that are needed, obviously problems like Metroid II occur. The fix seems to be changing this line in apu.cpp from this...

 desired_spec.samples = 1024;

to something like this...

 desired_spec.samples = 256;

The results sound much closer to the original hardware, with that one-liner. I've a physical copy of Metroid II myself, so I'll keep checking to see if this change really does work and make sure it doesn't cause any regressions elsewhere.

FateForWindows commented 2 years ago

I tried your fix and it seems to work well on my end as well. The beam sound still seems a little off; a bit less accurate than my initial hack, from my ears, though halving the number of processed samples to 128 seemed to improve it to the point where the difference between the two was negligible. That's a worst-case solution, though. Maybe adding an option to change it would help with that? The Metroid hit sounds are still an issue, though.

Interestingly, this (and the hack) also significantly improve the accuracy of the pipe sounds in Super Mario Land 2 (and the rest of the channel 1 sound effects to a far lesser extent). I'll update this with more info as I continue testing.

shonumi commented 2 years ago

It really shouldn't be a problem to set the samples to 128 for the DMG/GBC core for every game. I can't imagine a situation where it would be detrimental, but if you turn up anything, let me know. Ideally for something like this, I'd rather not add another configurable option unless absolutely necessary. It's understandable if it can't be helped; I know other emulators expose it too.