Google-Code-Fork / snes9x-gtk

Automatically exported from code.google.com/p/snes9x-gtk
0 stars 0 forks source link

Problems disabling resampling in APU core #55

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hello. I am part of the Snes9x-PS3 team, and I have some query about the 
current state of the APU core in snes9x.

Basically, I noticed that the APU does internal resampling so that it can 
output at e.g. 48kHz. While this is nice, it steals CPU cycles from the main 
thread since we are able to resample in our audio thread. I tried to disable 
the resampler by brute force, implementing a NullResampler class that basically 
did nothing more than push data around in the ring buffer, for a nice 2-3 fps 
increase in certain demanding games.

We noticed after a while that something was not quite right with audio, as in 
slight buffer underruns at certain intervals with some games. I looked around 
in the code for a bit, and saw this in apu/apu.cpp:

[code]
static void UpdatePlaybackRate (void)
{
    if (Settings.SoundInputRate == 0)
        Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE;

    double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator);
    spc::resampler->time_ratio(time_ratio);
}
[/code]

It seems that your resampling ratio is dependant on some APU hacks, which might 
have broken the audio when we disregarded that hack. Is the current APU core in 
snes9x dependant on this resampling taking place internally, or is there some 
sane way to properly disable the resampling being done internally without 
getting bitten by APU hacks?

Original issue reported on code.google.com by airmake...@gmail.com on 27 Oct 2010 at 7:40

GoogleCodeExporter commented 9 years ago
This has to do with the input rate, which is designed to accommodate audio 
output rates or video refresh rates that tend to vary slightly even in spec. 

The code you posted is just adjusting the ratio so as to not affect the output 
rate when timing are enabled, and is dependent on a timing hack in itself. Your 
problem is that there's not enough sound data for the slow speed your video is 
output at. The only way to fix this without changing hardware is to use a 
high-resolution resampler to stretch the data slightly. 

The core resampler is designed to be able to multithread by default anyways. 
Read the porting.html file that comes in the doc folder of the Snes9x source. 
In short, you need to set up S9xSetSamplesAvailableCallback, then lock a common 
mutex around the S9xFinalizeSamples in the callback and the S9xMixSamples calls 
in your audio thread--S9xMixSamples is what actually performs the resampling. 

If you're still against using the built-in resampler, you're going to need your 
own high precision resampler somewhere to avoid the underruns. If you can get 
significantly faster than the LinearResampler without any CPU-specific 
instructions, though, I'd be surprised.

BTW, you should stick to the Snes9x development forum for core questions like 
these (http://www.snes9x.com/phpbb2/viewforum.php?f=8). This issue tracker is 
specifically for Snes9x-gtk.

Original comment by bear...@gmail.com on 30 Oct 2010 at 4:33

GoogleCodeExporter commented 9 years ago
Sorry, part of that second paragraph should read:
"when timing hacks are enabled, and is not dependent on a timing hack in itself"

Original comment by bear...@gmail.com on 30 Oct 2010 at 4:35

GoogleCodeExporter commented 9 years ago
And if you want to disregard the timing hacks, you probably can. You'll only 
see overruns, not underruns, and these will be eliminated by duplicate frames 
if you're properly using sound sync.

Original comment by bear...@gmail.com on 30 Oct 2010 at 4:39