From bd388cf4f9421febac45060d63f9ac3754222464 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 27 Jan 2026 17:28:59 -0600 Subject: [PATCH] Expose AudioToolkit in UI --- Ryujinx.sln | 4 +++ assets/Locales/Root.json | 27 ++++++++++++++++++- .../AppleHardwareDeviceDriver.cs | 4 ++- .../AppleHardwareDeviceSession.cs | 4 +-- .../Ryujinx.Audio.Backends.Apple.csproj | 2 +- src/Ryujinx/Ryujinx.csproj | 3 ++- src/Ryujinx/Systems/AppHost.cs | 7 +++++ .../Systems/Configuration/AudioBackend.cs | 1 + .../UI/ViewModels/SettingsViewModel.cs | 4 +++ .../UI/Views/Settings/SettingsAudioView.axaml | 3 +++ 10 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Ryujinx.sln b/Ryujinx.sln index b89d5da0a..deddb97a0 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.Apple", "src\Ryujinx.Audio.Backends.Apple\Ryujinx.Audio.Backends.Apple.csproj", "{AC26EFF0-8593-4184-9A09-98E37EFFB32E}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}" @@ -569,6 +571,8 @@ Global {D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x64.Build.0 = Release|Any CPU {D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.ActiveCfg = Release|Any CPU {D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.Build.0 = Release|Any CPU + {AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index aa8937247..3578f689d 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -4850,6 +4850,31 @@ "zh_TW": null } }, + { + "ID": "SettingsTabSystemAudioBackendAudioToolbox", + "Translations": { + "ar_SA": null, + "de_DE": null, + "el_GR": null, + "en_US": "Apple Audio (macOS only)", + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null + } + }, { "ID": "SettingsTabSystemHacks", "Translations": { @@ -24776,4 +24801,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs index 62d81c6cc..2c659f6a0 100644 --- a/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs @@ -86,6 +86,8 @@ namespace Ryujinx.Audio.Backends.Apple private static bool IsSupportedInternal() { + if (!OperatingSystem.IsMacOS()) return false; + try { var format = GetAudioFormat(SampleFormat.PcmInt16, Constants.TargetSampleRate, 2); @@ -238,4 +240,4 @@ namespace Ryujinx.Audio.Backends.Apple return direction != Direction.Input; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs b/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs index 95826b4f4..08aefe4a5 100644 --- a/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs +++ b/src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs @@ -215,7 +215,7 @@ namespace Ryujinx.Audio.Backends.Apple public override void QueueBuffer(AudioBuffer buffer) { _ringBuffer.Write(buffer.Data, 0, buffer.Data.Length); - _queuedBuffers.Enqueue(new AppleAudioBuffer(buffer.HostTag, GetSampleCount(buffer))); + _queuedBuffers.Enqueue(new AppleAudioBuffer(buffer.DataPointer, GetSampleCount(buffer))); } public override void Start() @@ -253,7 +253,7 @@ namespace Ryujinx.Audio.Backends.Apple if (!_queuedBuffers.TryPeek(out AppleAudioBuffer driverBuffer)) return true; - return driverBuffer.DriverIdentifier != buffer.HostTag; + return driverBuffer.DriverIdentifier != buffer.DataPointer; } public override void PrepareToClose() { } diff --git a/src/Ryujinx.Audio.Backends.Apple/Ryujinx.Audio.Backends.Apple.csproj b/src/Ryujinx.Audio.Backends.Apple/Ryujinx.Audio.Backends.Apple.csproj index b7e1b6d84..c27fdee5b 100644 --- a/src/Ryujinx.Audio.Backends.Apple/Ryujinx.Audio.Backends.Apple.csproj +++ b/src/Ryujinx.Audio.Backends.Apple/Ryujinx.Audio.Backends.Apple.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 true diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 28aec175b..5da152501 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -77,12 +77,13 @@ - + + diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index 2eba0d26b..4b1e9cdb5 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -6,6 +6,7 @@ using Avalonia.Threading; using DiscordRPC; using LibHac.Common; using LibHac.Ns; +using Ryujinx.Audio.Backends.Apple; using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL3; @@ -949,6 +950,9 @@ namespace Ryujinx.Ava.Systems AudioBackend.Dummy ]; + if (OperatingSystem.IsMacOS()) + availableBackends.Insert(0, AudioBackend.AudioToolbox); + AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value; if (preferredBackend is AudioBackend.SDL2) @@ -985,6 +989,9 @@ namespace Ryujinx.Ava.Systems deviceDriver = currentBackend switch { +#pragma warning disable CA1416 // Platform compatibility is enforced in AppleHardwareDeviceDriver.IsSupported, before any potentially platform-sensitive code can run. + AudioBackend.AudioToolbox => InitializeAudioBackend(AudioBackend.AudioToolbox, nextBackend), +#pragma warning restore CA1416 AudioBackend.SDL3 => InitializeAudioBackend(AudioBackend.SDL3, nextBackend), AudioBackend.SoundIo => InitializeAudioBackend(AudioBackend.SoundIo, nextBackend), AudioBackend.OpenAl => InitializeAudioBackend(AudioBackend.OpenAl, nextBackend), diff --git a/src/Ryujinx/Systems/Configuration/AudioBackend.cs b/src/Ryujinx/Systems/Configuration/AudioBackend.cs index da75c9f7c..12d87151d 100644 --- a/src/Ryujinx/Systems/Configuration/AudioBackend.cs +++ b/src/Ryujinx/Systems/Configuration/AudioBackend.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Ava.Systems.Configuration OpenAl, SoundIo, SDL3, + AudioToolbox, SDL2 = SDL3 } } diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index d5d9b8218..abb284960 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -5,6 +5,7 @@ using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using LibHac.Tools.FsSystem; +using Ryujinx.Audio.Backends.Apple; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL3; using Ryujinx.Audio.Backends.SoundIo; @@ -277,6 +278,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsOpenAlEnabled { get; set; } public bool IsSoundIoEnabled { get; set; } public bool IsSDL3Enabled { get; set; } + public bool IsAudioToolboxEnabled { get; set; } public bool IsCustomResolutionScaleActive => _resolutionScale == 4; public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr; @@ -524,12 +526,14 @@ namespace Ryujinx.Ava.UI.ViewModels IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported; IsSoundIoEnabled = SoundIoHardwareDeviceDriver.IsSupported; IsSDL3Enabled = SDL3HardwareDeviceDriver.IsSupported; + IsAudioToolboxEnabled = OperatingSystem.IsMacOS() && AppleHardwareDeviceDriver.IsSupported; await Dispatcher.UIThread.InvokeAsync(() => { OnPropertyChanged(nameof(IsOpenAlEnabled)); OnPropertyChanged(nameof(IsSoundIoEnabled)); OnPropertyChanged(nameof(IsSDL3Enabled)); + OnPropertyChanged(nameof(IsAudioToolboxEnabled)); }); } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml index 22dfc57ac..e9b4e7acc 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml @@ -46,6 +46,9 @@ +