hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
11.38k stars 2.19k forks source link

Frequent audio popping and clicking sounds in most games. #12705

Open orbea opened 4 years ago

orbea commented 4 years ago

What happens?

In many (Most?) games I experience often frequent minor audio popping and clicking sounds. This is highly distracting and makes it harder to enjoy games.

I have tried most settings and the only one that seems to make any clear impact is disabling Audio sync (resampling) which only helps a little. Both OpenGL and Vulkan are affected as well as both the SDL and Qt frontends. I also tried PR https://github.com/hrydgard/ppsspp/pull/12602 which did not help.

I tried going back to v1.0 without finding a good commit.

I can always reproduce it on the title screen for Lunar Silver Star Harmony where the FPS and speed counter is a solid 60 and 100% respectively.

Other games I have experienced in are:

One game I have not noticed it in is Guilty Gear XX Accent Core Plus.

What should happen?

Audio should be smooth and not suffer from popping or clicking sounds.

What hardware, operating system, and PPSSPP version? On desktop, GPU matters for graphical issues.

OS: Slackware64-current GPU: RX Vega 56 CPU: AMD FX-6350 compiler: clang-10.0.0, gcc-9.2.0 mesa: https://github.com/mesa3d/mesa/commit/461ee852486da724c79c5145fa2e50bdfa54aa55 llvm: 10.0.0 alsa-lib: 1.2.1.2 Qt: 5.14.1 SDL: 2.0.10 ppsspp: https://github.com/hrydgard/ppsspp/commit/d0e2aa3a4f394cedc956df3df24ce335d3f6d974

orbea commented 4 years ago

Issues https://github.com/hrydgard/ppsspp/issues/9736 and https://github.com/hrydgard/ppsspp/issues/10865 seem familiar, but maybe are different.

ghost commented 4 years ago

Can this PR #8717 helps this issue? sorry for asking 😅

orbea commented 4 years ago

That PR has a lot of conflicts making it harder to test, but thanks for pointing it out!

quicksilver7837 commented 4 years ago

I get the same behavior running ppsspp on my raspberry pi 4. Certain games even when running fullspeed, the audio will make popping noises. The audio pops even when the sample audio plays for certain games while navigating the game selection menu.

unknownbrackets commented 4 years ago

Well, even if you see 60/60 or 100%, that's an average. If you drop a single frame, you'll probably hear a pop even if you don't see it visually and even if it isn't enough to change the average.

If you enable the devmenu button in developer settings, you can turn on a "frame times" graph. Do the pops correspond with that graph in any way?

-[Unknown]

quicksilver7837 commented 4 years ago

It's hard to tell, though that does make sense. However, why would the sound be popping when it plays the preview audio on some titles in the game select area of the ppsspp menu? It's only playing audio and nothing is happening on the screen so I can't imagine it's that taxing, though I am not an expert on the matter.

orbea commented 4 years ago

Well, even if you see 60/60 or 100%, that's an average. If you drop a single frame, you'll probably hear a pop even if you don't see it visually and even if it isn't enough to change the average.

Sometimes it shows 99.9% or 100.1%, but this not seem to directly correspond to the pops.

If you enable the devmenu button in developer settings, you can turn on a "frame times" graph. Do the pops correspond with that graph in any way?

No, it does not seem to correspond to the graph in any way.

orbea commented 4 years ago

@unknownbrackets Actually with the audio debug from the dev menu, the number of overruns will increase by one with every pop.

1

unknownbrackets commented 4 years ago

Is the sample rate constant at 44100 or does it fluctuate slightly within +/- 10? Are you often seeing audio buffer above 2000 or is it usually below 2000 and sometimes jumping above 2000?

An overrun would mean audio buffer went up to 8192/8192. That basically shouldn't happen.

Architecturally, it works like this:

Often a larger buffer is needed to bluetooth or wireless audio, because it can't stream audio quite as immediately. This is why it's 8192 - it should not normally use that much buffer unless you have audio latency somewhere in your setup.

An overrun means that the buffer was full. So it means that the platform glue or OS was not taking enough data fast enough. An underrun would mean the opposite - that the emulation wasn't keeping up, and couldn't produce enough audio to keep the buffer moving.

It's possible this is an issue only with SDL and Qt.

To confirm this, it might be worth trying PPSSPP in WINE. If that works well, it really points to a problem in how data is being sent through on SDL and Qt.

-[Unknown]

orbea commented 4 years ago

Is the sample rate constant at 44100 or does it fluctuate slightly within +/- 10?

It never changes.

Are you often seeing audio buffer above 2000 or is it usually below 2000 and sometimes jumping above 2000?

It fluctuates with such speed I can't clearly read it, but from my screenshots it seems most are between 1000 and 3000, one was nearly 4000. I do not notice it reaching 8192 at all.

To confirm this, it might be worth trying PPSSPP in WINE. If that works well, it really points to a problem in how data is being sent through on SDL and Qt.

Trying 1.9.3 in wine-staging-5.0 and I am not experiencing any clicks or pops in the Lunar title screen. The sample rate fluctuates +/-10 around 44100 and the audio buffer is equally unreadable. It is not also not constantly registering overruns.

unknownbrackets commented 4 years ago

Do you have the audio resampler setting enabled (it should be on by default)? That's what would make the sample rate fluctuate, as it tries to match actual speed.

-[Unknown]

orbea commented 4 years ago

With wine it was the default so it was enabled, with SDL I had it off because it makes this problem worse. When enabled in SDL it reports the sample rate as fluctuating between about 44280 and 44300 and the problem is clearly worse.

unknownbrackets commented 4 years ago

10865 also describes the sample rate going over 44200 and a similar issue on Android.

The resampler increases the rate if there's more data in the buffer, meaning that it's reading PSP audio data faster to drain the buffer (keep it from overrun.) In theory this means your device is playing at below 44.1kHz.

That it happens more frequently when the resampler is enabled is interesting, though. Does the audio buffer look to stay below 3000 when it's enabled? Do overruns still correlate with the pops?

-[Unknown]

orbea commented 4 years ago

Does the audio buffer look to stay below 3000 when it's enabled?

Yes, none of my screenshots showed that it even reached 3000 and many were below 1000 which I did not see with the resampler disabled.

Do overruns still correlate with the pops?

Yes, at a much increased rate. Roughly 1 per second.

orbea commented 4 years ago

Is it possible to get ppsspp to use a 48000 sample rate instead? Maybe it would work better for my device?

$ cat /proc/asound/card0/pcm0p/sub0/hw_params 
access: MMAP_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 1024
buffer_size: 16384
unknownbrackets commented 4 years ago

Yes, change these two numbers: https://github.com/hrydgard/ppsspp/blob/875d53a4859bd47004334e68b79bc0913d932d9a/SDL/SDLMain.cpp#L95 https://github.com/hrydgard/ppsspp/blob/875d53a4859bd47004334e68b79bc0913d932d9a/SDL/SDLMain.cpp#L320

This will force the resampler on, I should note. PSP games always generate 44.1kHz audio, so we must resample to another hz.

-[Unknown]

orbea commented 4 years ago

That change makes the frequency of overruns and audio pops even faster, several per second followed by short moments where the pops stop.

The Audio buffer doesn't even exceed 2000 now and one was as low as 2.

orbea commented 4 years ago

Could increasing the max buffer size of 8192 possibly help?

orbea commented 4 years ago

I tried upgrading to SDL-2.0.12 and then downgrading to 2.0.6 where neither helped. Older SDL2 releases have a build failure I did not spend much time on.

orbea commented 4 years ago

@unknownbrackets

I doubled this number to 16384.

https://github.com/hrydgard/ppsspp/blob/55bb58e13edbfeafec2b32342503740cf01a3f66/Core/HW/StereoResampler.cpp#L23

With the resampler disabled the problem seems to be fixed at first, but after a minute or two the audio buffer grows from around 2000 to over 10000 and the problem begins again. With the resampler enabled the buffer is being constantly depleted and I get frequent popping sounds, but associated with underruns instead of overruns.

unknownbrackets commented 4 years ago

I'm not sure, but does increasing or decreasing CONTROL_FACTOR help with the resampler at all?

https://github.com/hrydgard/ppsspp/blob/e14bf3bcc35e30e85bb9fd2303d9cbf9f3e57386/Core/HW/StereoResampler.cpp#L29

Maybe try 0.1f or 0.3f?

Goal should be to keep the buffer "healthy". If it goes down to 2, that's like a narrow miss - it almost went below 0. Not healthy.

I think it's overcompensating somehow.

-[Unknown]

orbea commented 4 years ago

Increasing it to 0.3f caused the sample rate to report a solid 44300 even when the resampler is enabled. Otherwise it seems roughly the same behavior.

Also now I notice that with the resampler enabled it always registered underruns, the overruns are only when its disabled.

orbea commented 4 years ago

@unknownbrackets Now that I can use libretro again I can again confirm that this is only with SDL/Qt.

With #if 0 I can confirm that this code path results in underruns.

https://github.com/hrydgard/ppsspp/blob/e14bf3bcc35e30e85bb9fd2303d9cbf9f3e57386/Core/HW/StereoResampler.cpp#L190

While this results in overruns.

https://github.com/hrydgard/ppsspp/blob/e14bf3bcc35e30e85bb9fd2303d9cbf9f3e57386/Core/HW/StereoResampler.cpp#L181

Both have similar popping/clicking sounds. I think at least libretro is also using this code, so why is windows and libretro unaffected by this issue? I'm struggling to find what they are doing differently.

quicksilver7837 commented 4 years ago

I can confirm. I just tested libretro ppsspp on my rpi 4 and while performance is terrible compared to standalone ppsspp there is no popping/clicking sounds.

unknownbrackets commented 4 years ago

Windows typically uses WASAPI. How it works is:

libretro is a bit simpler but similar, and more like DirectSound on Windows:

SDL works differently, though:

Maybe it would help to increase or decrease the SDL buffer size which is here: https://github.com/hrydgard/ppsspp/blob/25197451e5cdb1b83dc69fea14c501bdb1e13b1a/SDL/SDLMain.cpp#L98

It looks like we could use SDL_QueueAudio() in SDL 2.0.4+, which would give us more control and allow us to operate like libretro or Windows.

-[Unknown]

orbea commented 4 years ago

Thanks for the detailed explanation!

Maybe it would help to increase or decrease the SDL buffer size

I tried 4096 and 8192 which is clearly worse, the sound is broken and there are constant overrunrs and underruns. With lower values the problem seems better, with values of 512 or 256 the problem is almost if not entirely gone when the resampler is enabled. When the resampler is disabled the problem begins again after some time when the audio buffer grows in size. With a value of 1024 the problem is greatly reduced, but still occurs even with the resampler enabled. I am also seeing framerates much closer to 44100 although its still slightly too high (~44130).

Perhaps it should be changed to a lower number to help mitigate this problem regardless?

It looks like we could use SDL_QueueAudio() in SDL 2.0.4+, which would give us more control and allow us to operate like libretro or Windows.

This sounds like a potentially good idea, would you be willing to spend time making a PR to test? SDL 2.0.4 came out in January of 2016 so that is not an unreasonable version requirement and potentially the old code could be left behind a conditional for backwards compatibility?

unknownbrackets commented 4 years ago

One challenge with the queue API is fast forward: it will accept as many samples as we give it, and play them at a steady pace. So if we send too many, it may desync audio. I guess we could flush it if SDL_GetQueuedAudioSize() gets too large? We probably should do it from a thread though, given this...

-[Unknown]

unknownbrackets commented 4 years ago

@hrydgard see above about the sample size and audio problems on SDL.

-[Unknown]

hrydgard commented 4 years ago

Increasing the low watermark by a large amount fixes it. Still, the low watermark is already considerably bigger than the SDL buffer size, but that just means it probably requests audio in bigger "lumps" in the background.

Going to have to make the buffer control algorithm a bit more adaptive.

orbea commented 4 years ago

@hrydgard Seems better on my end, thanks. The problem still seems to be present when the audio resampler is disabled, but its far less noticeable without the audio debug output.

Also there are still underruns and sometimes overruns when resuming from the ppsspp menu.

hrydgard commented 4 years ago

Yeah those little over and underruns with the menu are present on all platforms.

I am going to remove the ability to turn off the resampler, few platforms are so well synced that it works entirely without glitches.

hrydgard commented 4 years ago

@orbea Fixed a slight mistake that could cause the buffer to loop over and over if stopped, too.

quicksilver7837 commented 4 years ago

Fixed on my end (raspberry pi 4). So much more enjoyable without the audio constantly popping. Thanks! :)

hrydgard commented 4 years ago

Great, thanks for testing @quicksilver7837 !

quicksilver7837 commented 4 years ago

@hrydgard I may have spoken too soon. Most of the titles I tested are working great now. But just tested Castlevania Dracula X and I'm still getting popping on the game menu. 😕

Edit: turning on render duplicate frames to 60hz seems to fix it though?

hrydgard commented 4 years ago

Huh, that's surprising, although that option will smooth out the flow of audio packets too I guess, maybe enough to avoid it. May have to increase the margin a little further. Still seems like a good improvement overall.

mbriar commented 1 year ago

On linux I'm also still getting consistent underruns playing Brave Story: New Traveler, which also seems to be significantly improved by setting render duplicate frames to 60hz . It also doesn't happen at all running PPSSPP in wine.

mbriar commented 1 year ago

Setting

fmt.samples = 128;

in InitSDLAudioDevice() also completely fixes it for me.

hrydgard commented 1 year ago

Huh, the current value is 1024, very surprising that reducing it would improve things..

Might be one of those things we need to add an option for..

mbriar commented 1 year ago

FWIW, both the filled part of the Audio Buffer and the Effective Output sample rate in the audio debug overlay seems to be much more stable with lower fmt.samples. With the default of 1024 there is a lot of fluctuation.

viotech3 commented 1 year ago

Can verify, only noticed it when updating to 1.14.X (4 at the moment). Star Ocean 2 has it for context.

hrydgard commented 1 year ago

What bothers me about this is that 128 is a far too short buffer size to be realistic on most hardware, and it seems likely that SDL says "oh, this is too short, let's fall back to a safe value" and the result is worse audio latency. @mbriar what happens if you set it all the way down to 0?

mbriar commented 1 year ago

If you set it down to 0, SDL will pick a default which is around 2048 samples: https://github.com/libsdl-org/SDL/blob/SDL2/src/audio/SDL_audio.c#L1250 (and yeah, this also leads to underruns)

At least the pipewire SDL audio backend will allow samples to be as low as 32 for a frequency of 44100 (PW_MIN_SAMPLES is 32): https://github.com/libsdl-org/SDL/blob/SDL2/src/audio/pipewire/SDL_pipewire.c#L1145

With the pulseaudio backend, there appears to be no explicit clamping, but it sets PA_STREAM_ADJUST_LATENCY, the lowest I end up on the pulseaudio side using pipewire-pulse as pulseaudio server is 236 samples. However, on the SDL callback side, even ridiculously low samples are honored. If I add a printf here to print out len and set fmt.samples = 1, the callback is called with a len of 4, as expected, I guess.

FWIW, what first made me try using a lower value for samples was that I saw that the WASAPI backend updates every 5ms, and indeed ends up with 256 samples at 48000hz, or around 5ms, when run on wine (as seen in pw-top). So I guess something about the ppsspp audio backend behaves better with more frequent updates? Might be interesting to see if you can reproduce the underruns on Windows when making the WASAPI backend update less frequently.

All that said, using fmt.samples = 256 for the SDL backend also fixes the underruns for me and I suppose would be a reasonable default that brings it in line with what WASAPI defaults to. Of course making it configurable also wouldn't hurt.

Here are some comparison videos where I monitor the samples and frequency used by the pipewire audio server using pw-top next to the ppsspp audio debug overlay with different values for fmt.samples :

64 samples [ppsspp_64_samples.webm](https://user-images.githubusercontent.com/114156793/212852098-949659c2-acdb-47fe-8590-afa2304340fd.webm)
256 samples [ppsspp_256_samples.webm](https://user-images.githubusercontent.com/114156793/212852242-0df3a770-36b8-434b-849f-584e2a57f292.webm)
1024 samples [ppsspp_1024_samples.webm](https://user-images.githubusercontent.com/114156793/212852335-b5325a14-8ffa-499b-a96b-6cb891de0631.webm)
setting 0 samples which ends up with 2048 samples [ppsspp_0_samples.webm](https://user-images.githubusercontent.com/114156793/212856697-36bfa4f4-c04f-4840-ba7c-91db1dd4442a.webm)

Notice the underruns only going up in the 1024 and 0/2048 samples case.

hrydgard commented 1 year ago

Hm, interesting. Yeah I chose 1024 as what I though was some kind of safe enough default, but it seems to be worth trying 256.

I made the change.

foundObjects commented 1 year ago

That commit seems to have reduced random stuttering in final fantasy tactics on android quite a bit, thanks!

If you want a guaranteed repo case that'll run up thousands of underruns in short order (even after the sample change above) load up FFT to the main title menu and open the "continue" screen. Just sitting on the list of saved games screen induces underruns like crazy.

hrydgard commented 1 year ago

That commit should have done absolutely nothing for Android, so that's placebo :)

Thanks, good to know a good repro.

foundObjects commented 1 year ago

Ah, my bad. I'd turned on render duplicate frames to 60 to see if that would help with the audio issues on the load/save screen and forgot to switch it off after. That did seem to help with random audio underruns in other parts of the game.

ghost commented 1 year ago

Might be good to move this to future-prio milestone

kuro0768 commented 5 months ago

Is there any updates/fixes for this yet or better ways to mitigate the effects? Playing Growlanser 4 Wayfarer of Time and Unchained Blades using PPSSPP v1.16.6 on windows 10, the fixes I have that were recommended that I'm using are Setting the screen refresh rate to 60Hz, FPS Limit to 60FPS, and finally Render duplicate frames to 60hz on in ppsspp. I still get the popping and clicking maybe once every minute, and also an effect that I can only describe as audio "tearing", as if the audio is being slightly torn like a piece of paper. Issues aren't super frequent, but are enough to ruin any immersion...