ppsspp
ppsspp copied to clipboard
Frequent audio popping and clicking sounds in most games.
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:
- Growlanser: Wayfarer of Time
- Legend of Heroes Ao no Kiseki
- Nayuta: Endless Trails
- Riviera The Promised Land
- Tales of Eternia (Rare)
- Tales of Rebirth
- Tekken 6 (Rare)
- Valkyrie Profile
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
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:
- The PSP game produces audio data in small bursts, and sends this to PPSSPP's audio system.
- PPSSPP resamples this (if necessary) to keep it smooth, and keeps it in a buffer - that's the 8192 number.
- The platform glue (this part differs on SDL, Qt, retroarch, Windows, Android, iOS, etc.) pulls this data off the buffer whenever it is ready to play more audio, and sends it to the OS.
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.
#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]
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.
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.
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]
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.
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.
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:
- Platform glue has dedicated thread that waits for a few milliseconds, and sends new data to WASAPI periodically.
- WASAPI tells us how much data it still has, we just grab enough to refill its buffer.
- If we got less frames than WASAPI wanted, we fill the rest with padding.
- Ultimately, NativeMix() is called with dynamic sizes at a rate within PPSSPP code's control.
- Uses stereo resampler.
libretro is a bit simpler but similar, and more like DirectSound on Windows:
- Platform glue periodically pauses emulation to send a small batch of audio data (512 * 2 samples) to libretro.
- Pause is very short, but not threaded.
- Always tries for 512 stereo samples, but if less are available we only send as many as we could to libretro. No padding.
- Ultimately, an equivalent to NativeMix() is called with a variable size at a rate within PPSSPP code's control.
- Uses stereo resampler.
SDL works differently, though:
- Platform glue gives SDL the callback directly, and SDL asks for whatever data it wants when it wants it. We request a buffer of 2048 samples.
- SDL says this will "usually" run on a dedicated thread.
- SDL determines how many samples to request. If we get less samples than SDL wanted, we fill with padding.
- Ultimately, NativeMix() is called by SDL at a rate and with sizes PPSSPP doesn't control.
- Uses stereo resampler.
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.