melonDS-emu / melonDS

DS emulator, sorta
https://melonds.kuribo64.net
GNU General Public License v3.0
3.15k stars 518 forks source link

Better audio enhancements #1521

Open Powerlated opened 1 year ago

Powerlated commented 1 year ago

The DS isn't exactly known for not having problems with sound quality. Most of these issues originate from the DS's use of nearest-neighbor resampling in its audio mixer, which creates non-harmonic alias frequencies in the output stream of existing frequencies from the input stream. By default, melonDS emulates the mixer with nearest-neighbor resampling, which would be fine (and hardware-accurate) if melonDS didn't do another nearest-neighbor resampling step in the frontend from the core's output sample rate to the sample rate that SDL wants.

My goal is to improve melonDS's audio quality to hardware level at minimum, by introducing a proper resampler in the frontend, and eventually by replacing melonDS's resampling options (Linear, Cubic, Cosine) with methods better suited for DS audio.

Why a sinc resampler?

The sinc function Sinc(x)=sin(x)/x is the impulse response (IR) of the perfect low-pass filter (LPF). To avoid the problem of infinite latency from using an impulse response that has an infinite domain, we have to window the Sinc(x) function so that it has a reasonable length. Using a resampler with a windowed sinc function scaled so that it is the IR of an LPF it at the DS's Nyquist rate, we can avoid nonharmonic aliases in the output stream while preserving the harmonic image frequencies of the input sample that appear in the output stream above the input sample's Nyquist rate. Most of these harmonic image frequencies are desirable since they add texture to the sound that the samples themselves don't have high enough of a sample rate to represent. Because the linear, cubic, and cosine resamplers dull these upper harmonics too much (this is especially noticable in games that use low sample-rate sounds like Pokémon Gen IV), I plan to replace them with a sinc resampler, along with an optional 96db/octave low-pass filter set at the sample's Nyquist rate to remove some of the high image harmonics that add to perceived harshness rather than adding a fuller sound.

To hear what I want melonDS's audio to sound like, head over to my project https://powerlated.net/OptimePlayer and keep the Audio Anti-Aliasing (corresponds to sinc resampling) and Enable Filter boxes checked.

RSDuck commented 1 year ago

hey someone who actually knows signal theory! A warm welcome from us, we appreciate any help with this.

Arisotura commented 1 year ago

my brain is gone

if anyone knows better than me about all this, I'll let them have fun :P

carmiker commented 1 year ago

I have found libsamplerate (aka Secret Rabbit Code) works very well with melonDS. It is well tested, widely available, and licensed under the BSD-2-Clause license if you want to vendor it. I recommend using this, as writing your own resampler can often end up an exercise in reinventing the wheel before understanding the wheel.

There are 3 sinc options plus a few low quality options: https://libsndfile.github.io/libsamplerate/api_misc.html#converters

I'd also like to add that it's nice to keep the option to not resample inside the core, so that people porting the core can resample however they choose.