From 64d68c660fcd9cf8f63fdcf07901e0dd4176c516 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Oct 2025 20:52:33 +0900 Subject: [PATCH] Fix multiple bass initialisations on startup --- osu.Framework/Audio/AudioManager.cs | 48 ++++++++++++++--------------- osu.Framework/Game.cs | 9 +----- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/osu.Framework/Audio/AudioManager.cs b/osu.Framework/Audio/AudioManager.cs index 684a09da6..b6ca28d93 100644 --- a/osu.Framework/Audio/AudioManager.cs +++ b/osu.Framework/Audio/AudioManager.cs @@ -17,6 +17,7 @@ using osu.Framework.Audio.Mixing.Bass; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Configuration; using osu.Framework.Development; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.IO.Stores; @@ -176,20 +177,22 @@ namespace osu.Framework.Audio /// The host's audio thread. /// The resource store containing all audio tracks to be used in the future. /// The sample store containing all audio samples to be used in the future. - public AudioManager(AudioThread audioThread, ResourceStore trackStore, ResourceStore sampleStore) + /// + public AudioManager(AudioThread audioThread, ResourceStore trackStore, ResourceStore sampleStore, FrameworkConfigManager config) { thread = audioThread; thread.RegisterManager(this); - AudioDevice.ValueChanged += _ => - { - scheduler.AddOnce(initCurrentDevice); - }; - UseExperimentalWasapi.ValueChanged += _ => - { - scheduler.AddOnce(initCurrentDevice); - }; + // attach config bindables + config.BindWith(FrameworkSetting.AudioDevice, AudioDevice); + config.BindWith(FrameworkSetting.AudioUseExperimentalWasapi, UseExperimentalWasapi); + config.BindWith(FrameworkSetting.VolumeUniversal, Volume); + config.BindWith(FrameworkSetting.VolumeEffect, VolumeSample); + config.BindWith(FrameworkSetting.VolumeMusic, VolumeTrack); + + AudioDevice.ValueChanged += _ => scheduler.AddOnce(initCurrentDevice); + UseExperimentalWasapi.ValueChanged += _ => scheduler.AddOnce(initCurrentDevice); GlobalMixerHandle.ValueChanged += handle => { scheduler.AddOnce(initCurrentDevice); @@ -215,12 +218,12 @@ namespace osu.Framework.Audio return store; }); - CancellationToken token = cancelSource.Token; - syncAudioDevices(); + + // check for changes in any audio devices every 1000ms (slightly expensive operation) + CancellationToken token = cancelSource.Token; scheduler.AddDelayed(() => { - // sync audioDevices every 1000ms new Thread(() => { while (!token.IsCancellationRequested) @@ -254,18 +257,6 @@ namespace osu.Framework.Audio base.Dispose(disposing); } - private void onDevicesChanged() - { - scheduler.Add(() => - { - if (cancelSource.IsCancellationRequested) - return; - - if (!IsCurrentDeviceValid()) - initCurrentDevice(); - }, false); - } - private static int userMixerID; /// @@ -470,7 +461,14 @@ namespace osu.Framework.Audio var oldDeviceNames = audioDeviceNames; var newDeviceNames = audioDeviceNames = audioDevices.Skip(BASS_INTERNAL_DEVICE_COUNT).Where(d => d.IsEnabled).Select(d => d.Name).ToImmutableList(); - onDevicesChanged(); + scheduler.Add(() => + { + if (cancelSource.IsCancellationRequested) + return; + + if (!IsCurrentDeviceValid()) + initCurrentDevice(); + }, false); var newDevices = newDeviceNames.Except(oldDeviceNames).ToList(); var lostDevices = oldDeviceNames.Except(newDeviceNames).ToList(); diff --git a/osu.Framework/Game.cs b/osu.Framework/Game.cs index 3ca7ab425..f3df45232 100644 --- a/osu.Framework/Game.cs +++ b/osu.Framework/Game.cs @@ -188,19 +188,12 @@ namespace osu.Framework samples.AddStore(new NamespacedResourceStore(Resources, @"Samples")); samples.AddStore(CreateOnlineStore()); - Audio = new AudioManager(Host.AudioThread, tracks, samples) { EventScheduler = Scheduler }; + Audio = new AudioManager(Host.AudioThread, tracks, samples, config) { EventScheduler = Scheduler }; dependencies.Cache(Audio); dependencies.CacheAs(Audio.Tracks); dependencies.CacheAs(Audio.Samples); - // attach our bindables to the audio subsystem. - config.BindWith(FrameworkSetting.AudioDevice, Audio.AudioDevice); - config.BindWith(FrameworkSetting.AudioUseExperimentalWasapi, Audio.UseExperimentalWasapi); - config.BindWith(FrameworkSetting.VolumeUniversal, Audio.Volume); - config.BindWith(FrameworkSetting.VolumeEffect, Audio.VolumeSample); - config.BindWith(FrameworkSetting.VolumeMusic, Audio.VolumeTrack); - Shaders = new ShaderManager(Host.Renderer, new NamespacedResourceStore(Resources, @"Shaders")); dependencies.Cache(Shaders);