raylib
raylib copied to clipboard
[raudio] Crash when changing playback device
Issue description
Example (audio_sound_loading.c) crashes when changing playback device,.
Environment
This happens on Windows.
Initialization Logs
INFO: Initializing raylib 5.1-dev INFO: Platform backend: DESKTOP (GLFW) INFO: Supported raylib modules: INFO: > rcore:..... loaded (mandatory) INFO: > rlgl:...... loaded (mandatory) INFO: > rshapes:... loaded (optional) INFO: > rtextures:. loaded (optional) INFO: > rtext:..... loaded (optional) INFO: > rmodels:... loaded (optional) INFO: > raudio:.... loaded (optional) INFO: DISPLAY: Device initialized successfully INFO: > Display size: 1600 x 900 INFO: > Screen size: 800 x 450 INFO: > Render size: 800 x 450 INFO: > Viewport offsets: 0, 0 INFO: GLAD: OpenGL extensions loaded successfully INFO: GL: Supported extensions count: 230 INFO: GL: OpenGL device information: INFO: > Vendor: Intel INFO: > Renderer: Intel(R) UHD Graphics INFO: > Version: 3.3.0 - Build 27.20.100.8190 INFO: > GLSL: 3.30 - Build 27.20.100.8190 INFO: GL: VAO extension detected, VAO functions loaded successfully INFO: GL: NPOT textures extension detected, full NPOT textures supported INFO: GL: DXT compressed textures supported INFO: GL: ETC2/EAC compressed textures supported INFO: GL: ASTC compressed textures supported INFO: PLATFORM: DESKTOP (GLFW): Initialized successfully INFO: TEXTURE: [ID 1] Texture loaded successfully (1x1 | R8G8B8A8 | 1 mipmaps) INFO: TEXTURE: [ID 1] Default texture loaded successfully INFO: SHADER: [ID 1] Vertex shader compiled successfully INFO: SHADER: [ID 2] Fragment shader compiled successfully INFO: SHADER: [ID 3] Program shader loaded successfully INFO: SHADER: [ID 3] Default shader loaded successfully INFO: RLGL: Render batch vertex buffers loaded successfully in RAM (CPU) INFO: RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU) INFO: RLGL: Default OpenGL state initialized successfully INFO: TEXTURE: [ID 2] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps) INFO: FONT: Default font loaded successfully (224 glyphs) INFO: AUDIO: Device initialized successfully INFO: > Backend: miniaudio / WASAPI INFO: > Format: 32-bit IEEE Floating Point -> 32-bit IEEE Floating Point INFO: > Channels: 2 -> 2 INFO: > Sample rate: 48000 -> 48000 INFO: > Periods size: 1440 INFO: FILEIO: [resources/sound.wav] File loaded successfully INFO: WAVE: Data loaded successfully (44100 Hz, 16 bit, 1 channels) INFO: FILEIO: [resources/target.ogg] File loaded successfully INFO: WAVE: Data loaded successfully (22050 Hz, 16 bit, 2 channels) INFO: TIMER: Target time per frame: 16.667 milliseconds
Also note that miniaudio has a similar example (simple_playback.c
) that doesn't have an issue with switching playback devices.
Issue Screenshot
https://github.com/raysan5/raylib/assets/7282243/6cebb61c-ec89-41f9-86df-b666491a1881
Code Example
This happened to me on some personal projects and happens with the audio_sound_loading
example.
@thabetx Thanks for reporting, raudio
initializes some buffers internally and the player thread, probably the crash is related to some missing mutex or not properly managing the device change... It requires some review.
I looked into this a bit and here's what I found: in miniaudio.h -> ma_context_get_MMDevice__wasapi there is a call to ma_CoCreateInstance . It works initially on launch of the program when it's called from the main thread. When default audio device is changed ma_context_get_MMDevice__wasapi is eventually called from ma_IMMNotificationClient_OnDefaultDeviceChanged callback, from a different thread, which causes ma_CoCreateInstance to fail, because there was no ma_CoInitializeEx call from this thread. I haven't debug miniaudio simple_playback.c example, so I don't know how it works there.
Quick question @raysan5.
I looked into miniaudio and noticed that it can return a list of audio devices and to use a particular device. I currently do not see that feature in raylib. Is that something that we could get added to raylib?
I have an audio library that I built called CASL that my 2D game framework Velaptor uses for audio. Currently, CASL provides the ability to enumerate audio devices and switch to them. I was hoping to be able to use RayLib for audio under the hood in CASL instead of what it currently uses which is OpenAL.
Would this possibly be a feature added into RayLib?
Here is some info to possibly help with this.
Using this sample, I created a quick app to get familiar with how sound is done with RayLib using the C# binding project.
In my Windows system, I have the built-in system audio which is a Realtek Audio device. I also have a pair of Sony noise-canceling headphones which is the WH-1000XM5 model.
I connected the headphones and played the sample project and everything worked great. As the sound was playing, I turned off the headphones. I expected the app to crash, but to my surprise, it did not and just automatically started playing through the Realtek Audio device on the laptop. I also turned the headphones back on and it automatically changed from the laptop audio device back to the Sony headphones with no issue.
I hope this helps you out!!
Extra info: OS: Windows 11 PRO 23H2 (OS Build 22631.3085) C#/dotnet: v8.0
Example Source Code Used
using Raylib_cs;
const int screenWidth = 800;
const int screenHeight = 450;
Raylib.InitWindow(screenWidth, screenHeight, "Sound Testing");
Raylib.InitAudioDevice();
var music = Raylib.LoadMusicStream("Content/Audio/brinstar.mp3");
Raylib.PlayMusicStream(music);
var timePlayed = 0f;
var pause = false;
music.Looping = true;
Raylib.SetTargetFPS(30);
while (!Raylib.WindowShouldClose())
{
Raylib.UpdateMusicStream(music);
// Restart music playing (stop and play)
if (Raylib.IsKeyPressed(KeyboardKey.Space))
{
Raylib.StopMusicStream(music);
Raylib.PlayMusicStream(music);
}
// Pause/Resume music playing
if (Raylib.IsKeyPressed(KeyboardKey.P))
{
pause = !pause;
if (pause)
{
Raylib.PauseMusicStream(music);
}
else
{
Raylib.ResumeMusicStream(music);
}
}
if (Raylib.IsKeyPressed(KeyboardKey.Right))
{
var currentPosition = Raylib.GetMusicTimePlayed(music);
var newPosition = currentPosition + 10;
Raylib.SeekMusicStream(music, newPosition);
}
if (Raylib.IsKeyPressed(KeyboardKey.Left))
{
var currentPosition = Raylib.GetMusicTimePlayed(music);
var newPosition = currentPosition - 10;
Raylib.SeekMusicStream(music, newPosition);
}
// Get normalized time played for current music stream
timePlayed = Raylib.GetMusicTimePlayed(music)/Raylib.GetMusicTimeLength(music);
if (timePlayed > 1.0f) timePlayed = 1.0f; // Make sure time played is no longer than music
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
Raylib.BeginDrawing();
Raylib.DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, Color.LightGray);
Raylib.DrawRectangle(200, 200, 400, 12, Color.LightGray);
Raylib.DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, Color.Maroon);
Raylib.DrawRectangleLines(200, 200, 400, 12, Color.Gray);
Raylib.DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, Color.LightGray);
Raylib.DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, Color.LightGray);
Raylib.EndDrawing();
}
// De-Initialization
//--------------------------------------------------------------------------------------
Raylib.UnloadMusicStream(music); // Unload music stream buffers from RAM
Raylib.CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
Raylib.CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
This is likely related. When my monitor goes into sleep mode, my raylib game crashes with the following error. Windows 11 / raylib 5.0
Thread 14 received signal SIGSEGV, Segmentation fault. [Switching to Thread 6576.0x20ec] 0x00007ff7f64a26e9 in ma_device_start.wasapi_nolock ()
Reminder that this issue is causing shipped games to crash - happens for example when bluetooth headphones auto-connect to the PC.
@jkaup thanks for the reminder, feel free to review it and send a fix PR. thanks.
@jkaup thanks for the reminder, feel free to send a fix as soon as possible. waiting for your PR. thanks.
I will take a look in case this is not being worked on - however note that I have 0 prior experience with audio. I'll send a PR if I have any solution to this.