hajimehoshi / ebiten

Ebitengine - A dead simple 2D game engine for Go
https://ebitengine.org
Apache License 2.0
10.78k stars 651 forks source link

Complete loss of audio in Linux with external monitor, When the monitor is switched off #2235

Open abishekmuthian opened 2 years ago

abishekmuthian commented 2 years ago

Greetings hajimehoshi and other contributors. I appreciate your effort in creating this wonderful library.

I'm using ebiten in my health and productivity timer application/game(WASM) - buttmover, Which is triggered using a hardware button on the chair (or) Keyboard.

Source code: https://github.com/abishekmuthian/buttmoverWebApp/blob/main/main.go

Note: My application continues to run in background (Even without SetRunnableOnUnfocused) As I'm using web workers to sync the game. The issues are with audio alone.

Two different scenarios of audio issues w/o external monitor

Ebiten Version: 2.3.7 Platform: WASM

Case 1: Without external monitor

OS: Arch Linux, Kernel 5.18.10 Audio Framework: Pulseaudio

There are known issues like delay of audio(sound), temporary loss in audio when the browser is out of focus (or) tab is in background. But there's no complete loss of audio.

Case 2: With external monitor

OS: Arch Linux, Kernel 5.18.10 Audio Framework: Pipewire, Pipewire-pulse

The known issues with audio (i.e. delay, temporary loss) doesn't occur with external monitor, Application works perfectly as long as the external monitor is ON after starting the game. But if the monitor is OFF (power saving), (Or) system is suspended(not always) (Or) in combination of both then the audio for the game is lost completely until the game is restarted(website reload).

Reproducing the issue:

  1. Visit the website with a computer with external monitor.
  2. Press 'S' to start the game timer(First hit sound is heard).
  3. While the game is running, Power off the monitor and/or Suspend the system.
  4. Wake the system, Let the timer continue.
  5. At 25:00, Another hit sound should play but it wouldn't.

Note: Sometimes it takes multiple suspends to loose the audio and then there are times when the audio recovers automatically.

Findings:

  1. Not likely due to Chrome's Media Engagement Index:

I launched chrome session with autoplay policy ignored and can still reproduce the issue - chromium --incognito --autoplay-policy=no-user-gesture-required .

  1. Not likely due auto discards:

I disabled discards for the application(tab) in chrome://discards, The issue occurs irrespective of whether its enabled or disabled.

  1. Not due to audio init() strategy:

I initialized audio at different places(From your audio example), incl. Even just before the sound needs to be triggered. It doesn't make any difference, Once audio is lost it's lost.

I understand that this might be a difficult issue to reproduce and fix. But I just wanted to do my bid to improve this amazing project.

hajimehoshi commented 2 years ago

Hi,

I think this is an issue in your browser, rather than Ebitengine.

abishekmuthian commented 2 years ago

Could be, But I was able to reproduce the issue with both Firefox and Chrome/Chromium.

The hardware input version for the game requires Chrome browser (web serial), The keyboard version can be played on Firefox.

abishekmuthian commented 2 years ago

Also, When this issue occurs the audio from any other tab on the browser (or) the system works fine.

hajimehoshi commented 2 years ago

Could be, But I was able to reproduce the issue with both Firefox and Chrome/Chromium.

So this might be an issue in an audio settings in your Linux machine, as Ebitengine just uses WebAPIs for audio. I think the same issue could happen with other similar web applications.

abishekmuthian commented 2 years ago

Is there any suggestions for testing another application?

I tried to test using the audio example, But I wasn't able to reproduce the issue. I guess its since there's no timed invocation of sound in the audio example, I was able to get the sound after key press once waking from the suspend(monitor off).

With my application, When this issue happens the browser is not shown in pavucontrol(Pulse Audio Control) while at other times when the game produces sound the browser is shown there.

superloach commented 2 years ago

It sounds like pipewire/pulse is dropping the audio stream when the audio device is removed, and since it's a long-running audio player, your browser does not attempt to create a new stream. not really sure why browsers can't handle this elegantly, but I've had the issue before with regular browser video players

abishekmuthian commented 2 years ago

I thought that could be the reason and tried playing an video with audio over web (YouTube) and suspending the machine while its playing; But the audio resumed just fine and I saw the browser again in the pavucontrol.

It could be that WASM behaves differently, Or that YouTube isn't using the WebAPIs for audio?

superloach commented 2 years ago

There's a lot of moving parts here, and a lot of information we're missing. Logs from Pipewire/Pulse might help. Logs from the browser might help. A smaller reproducible case might help. I haven't been able to replicate the issue on my hardware.

superloach commented 2 years ago

Hopefully we can get to the bottom of this :)

abishekmuthian commented 2 years ago

I haven't been able to replicate the issue on my hardware.

Sometimes it takes couple of suspends and sometimes even taken a day .

Key step is to keep the timer in the application running when the machine is suspended with external monitor (Note the audio is played using HDMI through the external monitor's speakers).

Toyking10 commented 2 years ago

@abishekmuthian have you tried reproducing in another operating system on the same hardware?

abishekmuthian commented 2 years ago

Good suggestion, I always assumed this to be a Linux specific issue; I'll try this in Windows when I get a chance.