Open orbea opened 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.
Can this PR #8717 helps this issue? sorry for asking 😅
That PR has a lot of conflicts making it harder to test, but thanks for pointing it out!
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.
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]
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.
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.
@unknownbrackets Actually with the audio debug from the dev menu, the number of overruns
will increase by one with every pop.
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]
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.
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]
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.
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]
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.
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
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]
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.
Could increasing the max buffer size of 8192 possibly help?
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.
@unknownbrackets
I doubled this number to 16384.
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.
I'm not sure, but does increasing or decreasing CONTROL_FACTOR help with the resampler at all?
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]
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.
@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.
While this results in overruns.
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.
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.
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]
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?
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]
@hrydgard see above about the sample size and audio problems on SDL.
-[Unknown]
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.
@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.
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.
@orbea Fixed a slight mistake that could cause the buffer to loop over and over if stopped, too.
Fixed on my end (raspberry pi 4). So much more enjoyable without the audio constantly popping. Thanks! :)
Great, thanks for testing @quicksilver7837 !
@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?
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.
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.
Setting
fmt.samples = 128;
in InitSDLAudioDevice() also completely fixes it for me.
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..
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.
Can verify, only noticed it when updating to 1.14.X (4 at the moment). Star Ocean 2 has it for context.
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?
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
:
Notice the underruns only going up in the 1024 and 0/2048 samples case.
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.
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.
That commit should have done absolutely nothing for Android, so that's placebo :)
Thanks, good to know a good repro.
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.
Might be good to move this to future-prio milestone
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...
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. BothOpenGL
andVulkan
are affected as well as both theSDL
andQt
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