feat: implement audio backend specific audio managers
Working on #705
This PR changes the audio management system to use a more modular approach. The main changes include:
- Deprecating the old
osu.Framework.Audio.AudioManagerclass, which was a monolithic audio manager. - Introducing a new
osu.Framework.Audio.Manager.IAudioManagerinterface and a newosu.Framework.Audio.Manager.AudioManagerabstract class, which are no longer dependent on BASS, will allow for easier work on other audio backends in the future (cc: #6002). - Introducing a new
osu.Framework.Audio.Manager.Bass.BassAudioManagerabstract class, which will contain BASS-specific audio management logic. - Introducing a new
osu.Framework.Audio.Manager.Bass.BassPrimitiveAudioManagerclass, which is a concrete implementation of audio management using BASS, so it can be used as a drop-in replacement for the oldosu.Framework.Audio.AudioManagerclass. WASAPI support is completely removed in this class. - Introducing a new
osu.Framework.Audio.Manager.Bass.BassWasapiAudioManagerclass, which is a concrete implementation of audio management using BASS with WASAPI support.
And the following tweaks:
- Removed BASS-specific logics from
osu.Framework.Threading.AudioThreadand moved them toBassPrimitiveAudioManagerandBassWasapiAudioManager. - The audio backend and/or device can now be configured via environment variables
OSU_AUDIO_BACKENDandOSU_AUDIO_DEVICE.
Notable breaking changes
- The old
osu.Framework.Audio.AudioManagerclass is no longer available, and new audio manager classes have some design differences.- The new audio manager identifies audio devices by their identifiers provided by concrete implementations, instead of using their names.
- The new audio manager does not require resource stores in the constructor and instead provides a
SetStoremethod to set the resource store after construction. - The new audio manager does not have the global mixer handle at abstract levels. Instead, concrete implementations which need a global mixer implement
osu.Framework.Audio.Manager.IGlobalMixerProvideinterface to provide the global mixer handle.
Known issues
- ~~Switching devices later using WASAPI causes the sound to stop playing. I've probably made a design mistake regarding global mixer handling.~~
- ~~When a debugger breakpoint occurs while using WASAPI, buffer updates stall, causing the last data in the buffer to loop indefinitely. This may surprise or frustrate you.~~
I haven't considered the new code splitting, structure, DI usage or anything. That's going to take hours / days of consideration.
Hard to say if any of this abstraction is required when wasapi was already working with the old structure.
- Switching devices later using WASAPI causes the sound to stop playing. I've probably made a design mistake regarding global mixer handling.
This problem is fixed @ 1d0f32463bea65e73003d9059b2fafac612edd87.
When a debugger breakpoint occurs while using WASAPI, buffer updates stall, causing the last data in the buffer to loop indefinitely. This may surprise or frustrate you.
This problem is also fixed @ 07b472791c5b025ad5385a77f934177880b9c785.