SDL icon indicating copy to clipboard operation
SDL copied to clipboard

After upgrading SDL2 from 2.0.22-2 to 2.24.0-1, get crackling noise when running Moonlight

Open NebuPookins opened this issue 3 years ago • 7 comments

I'm running Archlinux, and my problem occurs when I run Moonlight, which is a program that allows remote desktop access and is built using SDL2.

I performed a system upgrade today, and there were no updates to Moonlight, but there was an update to the SDL2 library. After the update, whenever I connect to another machine via Moonlight, all audio produced by my machine becomes very crackly, including audio produced by other apps. For example, I can have a Youtube video running in the background, and as long as Moonlight isn't connecting to another machine , the audio is fine. As soon as I connect to my remote desktop, the audio becomes crackly.

If I rollback the update to the SDL2 library, I am able to use Moonlight just fine with no audio distortion.

I'm not sure if this problem is specific to the way Moonlight is calling the SDL2 APIs. If you have other SDL2 demo audio programs you'd like me to test, I can try them. I was not able to reproduce the issue when using snes9x-gtk nor supertuxkart which I believe also use SDL2.

NebuPookins avatar Aug 24 '22 04:08 NebuPookins

I'm able to reproduce the problem with the following program. Compiling and running this program causes audio in other apps (e.g. Youtube) to become distorted when SDL 2.24.0-1 is installed. There is no audio distortion if 2.0.22-2 is installed.

#include <SDL2/SDL.h>
#include <stdio.h>

int main(int argc, char* args[]) {
	int initResult = SDL_Init(SDL_INIT_AUDIO);
	if (initResult < 0) {
		printf("SDL could not initialize: %s\n", SDL_GetError());
		return -1;
	}

	SDL_AudioSpec want, have;
	SDL_zero(want);
	want.freq = 48000;
	want.format = AUDIO_S16;
	want.channels = 2;
	want.samples = 240;

	SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
	printf("Waiting to continue...");
	getchar();
	SDL_Quit();
}

NebuPookins avatar Aug 25 '22 07:08 NebuPookins

The issue seems to be related to the number of samples. If I change the want.samples = 240; to want.samples = 4096;, I don't hear any distortion.

NebuPookins avatar Aug 25 '22 07:08 NebuPookins

Typically you don't go below 1024 samples because of this kind of issue (common to all audio drivers)

I'm surprised this is affecting other applications though. I'm guessing it's related to adding the flag PA_STREAM_ADJUST_LATENCY added in https://github.com/libsdl-org/SDL/commit/f6eb4b07593a3bb928ccf9d8569bf7a686159228. So we did two things, we removed doubling the buffer size, and added that flag, which sounds like it is affecting the latency for all audio sources on the system. @icculus, thoughts?

@cgutman, do you have logic to reduce the number of audio samples on PulseAudio because of the previous additional latency?

slouken avatar Aug 25 '22 14:08 slouken

@cgutman, do you have logic to reduce the number of audio samples on PulseAudio because of the previous additional latency?

I don't. I've always just used the number of samples that each audio packet contains (240) and it's worked fine on Windows, macOS, and Linux up until this point. I'm using SDL_QueueAudio() so I can accumulate more samples than just 240.

Typically you don't go below 1024 samples because of this kind of issue (common to all audio drivers)

The docs for SDL_OpenAudioDevice say 512-8192 are generally good. I can easily change my code to use 512 or something, but the fact that applications can cause system-wide audio crackling by merely playing silence seems bad.

Arguably this is something PulseAudio should fix, but we can probably put a floor on the sample count to mitigate it for common cases like this.

cgutman avatar Aug 26 '22 02:08 cgutman

Yeah, let's wait for feedback from @icculus. I suspect that PA_STREAM_ADJUST_LATENCY is a bigger hammer than we want in this case.

slouken avatar Aug 26 '22 02:08 slouken

I assume this is a pulseaudio bug if we can break other processes, and 240 is an low number in general.

But I'll see if I can reproduce it here.

icculus avatar Aug 26 '22 02:08 icculus

I could never reproduce it myself, but I realize now that was because I run Fedora which uses PipeWire instead of PulseAudio as the default audio daemon.

cgutman avatar Aug 26 '22 02:08 cgutman

So the PA_STREAM_ADJUST_LATENCY flag has been there since SDL 1.2, arriving here:

https://github.com/libsdl-org/SDL-1.2/issues/458

...and SDL2 got it during SDL 1.3, when this was merged/reworked for the new audio interfaces.

So I'm hesitant to change this at this point, but let's hedge our bets by only setting the flag if the sample count isn't too low (say, if it's >= 512 samples)...this should fix the pathological case and otherwise make the code work the way it has for many years.

(Also, fwiw, the test case does not reproduce here, although I imagine it's hardware and driver specific.)

icculus avatar Nov 16 '22 03:11 icculus

(But please let me know if the test case still causes problems for you with this change applied, and we'll reopen!)

icculus avatar Nov 16 '22 03:11 icculus

I still think changing the global latency is a terrible idea - there may be other reasons why the global latency is set to a particular value.

BUT, this seems like a safe change overall.

slouken avatar Nov 16 '22 05:11 slouken

@icculus, what other reason could an SDL update have suddenly triggered this? The original poster mentioned that rolling back SDL fixed the issue for them.

slouken avatar Nov 16 '22 05:11 slouken

The original sample program in https://github.com/libsdl-org/SDL/issues/6121#issuecomment-1226877523 no longer reproduces for me, even when I revert my system back to 2.24.0-1. (That is, I'm able to watch a Youtube video while the program is running, and the audio sounds fine).

I'm guessing there's some interactions with other packages on my system, but I'm not able to figure out which. In particular, I'm unable to downgrade PulseAudio as doing so would break other packages I have on my system.

NebuPookins avatar Nov 16 '22 08:11 NebuPookins

I still think changing the global latency is a terrible idea - there may be other reasons why the global latency is set to a particular value.

Part of the problem is that the docs say the default latency is set to two seconds, so we sort of have to do this, but also, the system shouldn't allow you to break other apps through this.

Since this issue vanished on the user's system, the only thing we should do here is maybe revert the patch I just made.

icculus avatar Nov 16 '22 12:11 icculus

Yes, I think this was the only report of this, so let's go ahead and revert for now.

slouken avatar Nov 16 '22 14:11 slouken

Reverted.

icculus avatar Nov 16 '22 14:11 icculus