MonoGame/MonoGame

AL lib throws unclosed device warning on proper game exit

Dominav opened this issue · 4 comments

Prerequisites

  • I have verified this issue is present in the develop branch
  • I have searched open and closed issues to ensure it has not already been reported.

MonoGame Version

MonoGame 3.8.1.303

Which MonoGame platform are you using?

MonoGame Cross-Platform Desktop Application (mgdesktopgl)

Operating System

Windows 10 Pro 22H2

Description

The game doesn't properly dispose of audio somewhere on proper game exit, and it results in a AL lib warning and a possible (?) memory leak.

Steps to Reproduce

  1. Create a blank mgdesktopgl template project
  2. Load Song instance using Content Builder and Content.Load<Song>()
  3. Call MediaPlayer.Play(song instance)
  4. Close the game either through the red cross or pressing Esc

Minimal Example Repo

No response

Expected Behavior

The warning should not appear?

Resulting Behavior

The folowing warning is thrown in the Output console in VSCode:
"AL lib: (EE) alc_cleanup: 1 device not closed"

Files

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace audio_issue;

public class Game1 : Game
{
    private GraphicsDeviceManager _graphics;
    private SpriteBatch _spriteBatch;
    private Song song;

    public Game1()
    {
        _graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        IsMouseVisible = true;
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        _spriteBatch = new SpriteBatch(GraphicsDevice);
        song = Content.Load<Song>("Divider");
        MediaPlayer.Play(song);
        soundEffect.Play();
    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        base.Draw(gameTime);
    }
}

We're going to drop using OpenAL entirely in the near future, so that's a non-concern.

We're going to drop using OpenAL entirely in the near future, so that's a non-concern.

@mrhelmut Okay, thanks for reply! Have a great day :)

Adding some notes as I encountered this too (requires some surgical fixes - so may not be worth the effort - let process cleanup clean this with a silent harmless logging):
Song (NVorbis impl) uses both the static OpenALSoundController.EnsureInitialized and the non-static methods via the stream (OggStream). This makes it nearly impossible to cleanly call OpenALSoundController.DestroyInstance -> as there may be streams that are not disposed but holding onto the OpenALSoundController.

So we need to destroy all streams first and then destroy the sound controller - hard to achieve with the current design (mixing statc/non-static).

Curious, what's the alternative to OpenAL? SDL_Audio?

Curious, what's the alternative to OpenAL? SDL_Audio?

FAudio. It's a reimplementation of XAudio 2 that is 100% accurate to XNA, so it's a no brainer.