Does libretro's API support audio downsampling?

Hello everyone, this is my first post. Glad to be joining the libretro/retroarch community!

A friend and I started an NES emulator some years ago https://github.com/aLaix2/O-Nes-Sama, we have always struggled to develop a cross-platform GUI for it. For the time being it’s running only though SDL but we are changing that by making it a libretro core. As some of you might know NES’s audio sampling rate is pretty high, around 1789772.66 Hz, so downsampling is necessary so you can output that through the sound card. I searched through the documentation and in the libretro.h file too but couldn’t find any info regarding API supporting downsampling, Does libretro’s API support downsampling? Can I output all those samples or should I downsample them before sending them to retroarch? Would that depend on a front-end basis?

Thank you!

***** O-Nes-Sama emulator team *****

Hey, that’s awesome news :slight_smile:

libretro doesn’t support downsampling directly in the API, but we have a suite of tools that can help:

The resampler in there is pretty good in a lot of respects.

1 Like

Thank you for the quick reply hunterk. We have a basic implementation (average of all samples) already in place for the SDL “front-end”. I’m going to check the tools you just posted and see if we can use them without too much trouble. :slight_smile:

RetroArch, at least, will resample it for output–dunno about other fronts, like GNOME Games–but I’m not sure if it can decimate all the way from 1.79 mhz… Might be worth trying, though :man_shrugging:

I’ll give it a try in some days and will let you know. Do you know what algorithm would it use? I’m asking because I’ve used nearest-neighbor or whatever it’s called (selecting one sample out of many) and it doesn’t give good results, it makes games sound weird as if they were poorly emulated. Thanks.

RetroArch has sinc, nearest and cubic convolution IIRC. I don’t know if the resampler in libretro-common provides the same or any additional algos.

And yeah, NES decimation sounds weird if not done properly. I recall byuu writing some things on his forum about the resampler he wrote when he first started working on NES emulation where he tried a few different algos, starting with just discarding most of the samples.

Hello hunterk, sorry for the delay, I spent all these days decoupling the SDL code from the actual emulator so we could run it as a libretro core.

Finally i got a working demo of the emulator in RetroArch! and i can confirm it is decimating it as you were saying, pretty nice considering it is a great jump from the very-high original sampling rate.
Thanks for your help.

There is still one question i have, the retro_system_av_info structure accepts sample_rate as a double (same for fps but i guess that’s a question for another thread), the exact sampling rate should be 21477272/12, around 1789772.6666.
Do you know how does RetroArch handles that fractional part of the sampling_rate?

I’m asking because in the past we had some timing issues related to very small quantities getting accumulated over a span of minutes, a tiny fractional amount of cycles was missing because we were thinking “tiny fractional amounts doesn’t matter”.
Thanks again for your help!

Hmm, that’s a good question about the sample rate. For reference, I see FCEUmm does this:

If there is anything left over, RetroArch should be able to handle it with dynamic rate control (resampling the audio to keep the buffer from filling/emptying).

Thanks for such quick reply, I’m gonna take a deep look into that libretro.c file!

1 Like