bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
35k stars 3.43k forks source link

Ability to use non-default audio device #12420

Open inodentry opened 5 months ago

inodentry commented 5 months ago

What problem does this solve or what need does it fill?

Currently, bevy_audio simply initializes audio using the system default device, and there is no way to select anything else. This could result in a poor user experience on systems where there is more than one audio output. It makes it impossible to implement a game/app that offers audio output selection via its own settings.

What solution would you like?

There should be an API for enumerating devices and selecting which one to use.

What alternative(s) have you considered?

Well, users of Bevy apps with multiple audio outputs could just go into their OS settings and make sure their desired device is set as default, before launching a Bevy app/game. If that breaks other apps or messes with their workflow, tough luck.

Additional context

Also of note is that Bevy currently offers no way to change or reinitialize the audio output at runtime. It is only initialized once on app startup.

This causes further issues if devices disappear/reappear (user unplugs/replugs a removable audio output such as a HDMI monitor or wireless headphone dongle), or if the system default changes (from devices appearing/disappearing, or the user changing their OS settings while the app is running).

These issues are all related (it's all due to Bevy being inflexible with its audio output devices), so I thought I would put it all under one GH issue. Overall, audio device management needs to be improved, if Bevy is to have reliable audio output.

SolarLiner commented 5 months ago

Fixing these issues would require being able to "detach" processing from a specific OutputStream and into another, something which I'm afraid wasn't in mind in the design of rodio which we use for the audio engine in bevy_audio, and I'm not sure it would be particulatly easy to implement even upstream. The problem is that handles are intimately linked to instances in the audio thread for processing the audio, which would mean having a way to rip them out of one audio thread and put them into another.

Another solution would be somehow to have a special "Audio" schedule which would be run once with Startup, and then zero or more times when needed to recreate the audio engine. I don't know that an "external" (to bevy_ecs) crate can even execute a schedule in the main app, manually.