mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-13 11:20:31 +00:00
Expose experimental WASAPI support as a user config toggle
This commit is contained in:
@@ -96,6 +96,13 @@ namespace osu.Framework.Audio
|
||||
/// </summary>
|
||||
public readonly Bindable<string> AudioDevice = new Bindable<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether to use experimental WASAPI initialisation on windows.
|
||||
/// This generally results in lower audio latency, but also changes the audio synchronisation from
|
||||
/// historical expectations, meaning users / application will have to account for different offsets.
|
||||
/// </summary>
|
||||
public readonly BindableBool UseExperimentalWasapi = new BindableBool();
|
||||
|
||||
/// <summary>
|
||||
/// Volume of all samples played game-wide.
|
||||
/// </summary>
|
||||
@@ -176,6 +183,7 @@ namespace osu.Framework.Audio
|
||||
thread.RegisterManager(this);
|
||||
|
||||
AudioDevice.ValueChanged += _ => onDeviceChanged();
|
||||
UseExperimentalWasapi.ValueChanged += _ => onDeviceChanged();
|
||||
GlobalMixerHandle.ValueChanged += handle =>
|
||||
{
|
||||
onDeviceChanged();
|
||||
@@ -430,10 +438,16 @@ namespace osu.Framework.Audio
|
||||
// See https://www.un4seen.com/forum/?topic=19601 for more information.
|
||||
Bass.Configure((ManagedBass.Configuration)70, false);
|
||||
|
||||
if (!thread.InitDevice(device))
|
||||
return false;
|
||||
if (UseExperimentalWasapi.Value)
|
||||
{
|
||||
if (thread.InitDevice(device, true))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
Logger.Log($"BASS device {device} failed to initialise with experimental WASAPI, disabling", level: LogLevel.Error);
|
||||
UseExperimentalWasapi.Value = false;
|
||||
}
|
||||
|
||||
return thread.InitDevice(device, false);
|
||||
}
|
||||
|
||||
private void syncAudioDevices()
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace osu.Framework.Configuration
|
||||
SetDefault(FrameworkSetting.WindowedPositionY, 0.5, -0.5, 1.5);
|
||||
SetDefault(FrameworkSetting.LastDisplayDevice, DisplayIndex.Default);
|
||||
SetDefault(FrameworkSetting.AudioDevice, string.Empty);
|
||||
SetDefault(FrameworkSetting.AudioUseExperimentalWasapi, false);
|
||||
SetDefault(FrameworkSetting.VolumeUniversal, 1.0, 0.0, 1.0, 0.01);
|
||||
SetDefault(FrameworkSetting.VolumeMusic, 1.0, 0.0, 1.0, 0.01);
|
||||
SetDefault(FrameworkSetting.VolumeEffect, 1.0, 0.0, 1.0, 0.01);
|
||||
@@ -79,6 +80,7 @@ namespace osu.Framework.Configuration
|
||||
ShowLogOverlay,
|
||||
|
||||
AudioDevice,
|
||||
AudioUseExperimentalWasapi,
|
||||
VolumeUniversal,
|
||||
VolumeEffect,
|
||||
VolumeMusic,
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace osu.Framework
|
||||
public static bool NoStructuredBuffers { get; }
|
||||
public static string? DeferredRendererEventsOutputPath { get; }
|
||||
public static bool UseSDL3 { get; }
|
||||
public static bool UseWasapi { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether non-SSL requests should be allowed. Debug only. Defaults to disabled.
|
||||
@@ -56,8 +55,6 @@ namespace osu.Framework
|
||||
|
||||
// Desktop has many issues, see https://github.com/ppy/osu-framework/issues/6540.
|
||||
UseSDL3 = RuntimeInfo.IsMobile || (parseBool(Environment.GetEnvironmentVariable("OSU_SDL3")) ?? false);
|
||||
|
||||
UseWasapi = parseBool(Environment.GetEnvironmentVariable("OSU_AUDIO_WASAPI_EXPERIMENTAL")) ?? false;
|
||||
}
|
||||
|
||||
private static bool? parseBool(string? value)
|
||||
|
||||
@@ -196,6 +196,7 @@ namespace osu.Framework
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace osu.Framework.Threading
|
||||
/// </summary>
|
||||
private readonly Bindable<int?> globalMixerHandle = new Bindable<int?>();
|
||||
|
||||
internal bool InitDevice(int deviceId)
|
||||
internal bool InitDevice(int deviceId, bool useExperimentalWasapi)
|
||||
{
|
||||
Debug.Assert(ThreadSafety.IsAudioThread);
|
||||
Trace.Assert(deviceId != -1); // The real device ID should always be used, as the -1 device has special cases which are hard to work with.
|
||||
@@ -139,9 +139,7 @@ namespace osu.Framework.Threading
|
||||
if (!Bass.Init(deviceId, Flags: (DeviceInitFlags)128)) // 128 == BASS_DEVICE_REINIT
|
||||
return false;
|
||||
|
||||
// That this has not been mass-tested since https://github.com/ppy/osu-framework/pull/6651 and probably needs to be.
|
||||
// Currently envvar gated for users to test at their own discretion.
|
||||
if (FrameworkEnvironment.UseWasapi)
|
||||
if (useExperimentalWasapi)
|
||||
attemptWasapiInitialisation();
|
||||
|
||||
initialised_devices.Add(deviceId);
|
||||
@@ -182,10 +180,10 @@ namespace osu.Framework.Threading
|
||||
}
|
||||
}
|
||||
|
||||
private void attemptWasapiInitialisation()
|
||||
private bool attemptWasapiInitialisation()
|
||||
{
|
||||
if (RuntimeInfo.OS != RuntimeInfo.Platform.Windows)
|
||||
return;
|
||||
return false;
|
||||
|
||||
Logger.Log("Attempting local BassWasapi initialisation");
|
||||
|
||||
@@ -219,10 +217,10 @@ namespace osu.Framework.Threading
|
||||
|
||||
// To keep things in a sane state let's only keep one device initialised via wasapi.
|
||||
freeWasapi();
|
||||
initWasapi(wasapiDevice);
|
||||
return initWasapi(wasapiDevice);
|
||||
}
|
||||
|
||||
private void initWasapi(int wasapiDevice)
|
||||
private bool initWasapi(int wasapiDevice)
|
||||
{
|
||||
// This is intentionally initialised inline and stored to a field.
|
||||
// If we don't do this, it gets GC'd away.
|
||||
@@ -246,13 +244,14 @@ namespace osu.Framework.Threading
|
||||
Logger.Log($"Initialising BassWasapi for device {wasapiDevice}...{(initialised ? "success!" : "FAILED")}");
|
||||
|
||||
if (!initialised)
|
||||
return;
|
||||
return false;
|
||||
|
||||
BassWasapi.GetInfo(out var wasapiInfo);
|
||||
globalMixerHandle.Value = BassMix.CreateMixerStream(wasapiInfo.Frequency, wasapiInfo.Channels, BassFlags.MixerNonStop | BassFlags.Decode | BassFlags.Float);
|
||||
BassWasapi.Start();
|
||||
|
||||
BassWasapi.SetNotify(wasapiNotifyProcedure);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void freeWasapi()
|
||||
|
||||
Reference in New Issue
Block a user