diff --git a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs index 4481cdc83..c3fd9e1db 100644 --- a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs @@ -5,7 +5,6 @@ using Ryujinx.Memory; using Ryujinx.SDL3.Common; using System; using System.Collections.Concurrent; -using System.Runtime.InteropServices; using System.Threading; using static Ryujinx.Audio.Integration.IHardwareDeviceDriver; using static SDL3.SDL; @@ -54,7 +53,7 @@ namespace Ryujinx.Audio.Backends.SDL3 if (device != 0) { - SDL_CloseAudioDevice(device); + SDL_DestroyAudioStream(device); } return device != 0; @@ -123,15 +122,15 @@ namespace Ryujinx.Audio.Backends.SDL3 }; } - internal static uint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, + internal static nint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount, SDL_AudioStreamCallback callback) - { - SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount, + { + SDL_AudioSpec spec = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount, sampleCount); - SDL_AudioSpec desired2 = default; - var device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, ref desired); - if (device == 0) + var stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, ref spec,null,IntPtr.Zero); + + if (stream == 0) { Logger.Error?.Print(LogClass.Application, $"SDL3 open audio device initialization failed with error \"{SDL_GetError()}\""); @@ -139,22 +138,8 @@ namespace Ryujinx.Audio.Backends.SDL3 return 0; } - bool isValid = false; - if (SDL_GetAudioDeviceFormat(device, out SDL_AudioSpec got, out int i)) - { - isValid = got.format == desired.format && got.freq == desired.freq && - got.channels == desired.channels; - } - // if (!isValid) - // { - // Logger.Error?.Print(LogClass.Application, "SDL3 open audio device is not valid"); - // SDL_CloseAudioDevice(device); - // - // return 0; - // } - - return device; + return stream; } public void Dispose() diff --git a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs index 0c23db989..62670cd0c 100644 --- a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs +++ b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs @@ -6,8 +6,8 @@ using Ryujinx.Memory; using System; using System.Buffers; using System.Collections.Concurrent; +using System.Runtime.InteropServices; using System.Threading; - using static SDL3.SDL; namespace Ryujinx.Audio.Backends.SDL3 @@ -19,7 +19,7 @@ namespace Ryujinx.Audio.Backends.SDL3 private readonly DynamicRingBuffer _ringBuffer; private ulong _playedSampleCount; private readonly ManualResetEvent _updateRequiredEvent; - private uint _outputStream; + private nint _outputStream; private bool _hasSetupError; private readonly SDL_AudioStreamCallback _callbackDelegate; private readonly int _bytesPerFrame; @@ -28,7 +28,9 @@ namespace Ryujinx.Audio.Backends.SDL3 private float _volume; private readonly SDL_AudioFormat _nativeSampleFormat; - public SDL3HardwareDeviceSession(SDL3HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) + public SDL3HardwareDeviceSession(SDL3HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, + SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base( + memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) { _driver = driver; _updateRequiredEvent = _driver.GetUpdateRequiredEvent(); @@ -46,13 +48,15 @@ namespace Ryujinx.Audio.Backends.SDL3 { uint bufferSampleCount = (uint)GetSampleCount(buffer); bool needAudioSetup = (_outputStream == 0 && !_hasSetupError) || - (bufferSampleCount >= Constants.TargetSampleCount && bufferSampleCount < _sampleCount); + (bufferSampleCount >= Constants.TargetSampleCount && + bufferSampleCount < _sampleCount); if (needAudioSetup) { _sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount); - var newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate); + var newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, + RequestedChannelCount, _sampleCount, _callbackDelegate); _hasSetupError = newOutputStream == 0; @@ -60,17 +64,18 @@ namespace Ryujinx.Audio.Backends.SDL3 { if (_outputStream != 0) { - SDL_CloseAudioDevice(_outputStream); + SDL_DestroyAudioStream(_outputStream); } _outputStream = newOutputStream; - SDL_PauseAudioDevice(_outputStream); - - Logger.Info?.Print(LogClass.Audio, $"New audio stream setup with a target sample count of {_sampleCount}"); + SDL_ResumeAudioStreamDevice(_outputStream); + Logger.Info?.Print(LogClass.Audio, + $"New audio stream setup with a target sample count of {_sampleCount}"); } } } - private unsafe void Update(IntPtr userdata, IntPtr stream, int streamLength, int total_amount) + + private unsafe void Update(nint userdata, IntPtr stream, int streamLength, int total_amount) { Console.WriteLine("call"); Console.WriteLine(SDL_GetAudioDeviceName(SDL_GetAudioStreamDevice(stream))); @@ -95,16 +100,20 @@ namespace Ryujinx.Audio.Backends.SDL3 _ringBuffer.Read(samples, 0, samples.Length); - fixed (byte* p = samples) - { - nint pStreamSrc = (nint)p; + // fixed (byte* p = samples) + // { + // nint pStreamSrc = (nint)p; + // + // // Zero the dest buffer + // streamSpan.Clear(); + // + // // Apply volume to written data + // // SDL_MixAudio(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, _driver.Volume * _volume); + // IntPtr unmanagedBuffer = Marshal.AllocHGlobal(samples.Length); + // Marshal.Copy(p, 0, unmanagedBuffer, samples.Length); + // SDL_PutAudioStreamData(_outputStream, unmanagedBuffer,samples.Length); + // } - // Zero the dest buffer - streamSpan.Clear(); - - // Apply volume to written data - // SDL_MixAudio(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, _driver.Volume * _volume); - } ulong sampleCount = GetSampleCount(samples.Length); @@ -117,7 +126,8 @@ namespace Ryujinx.Audio.Backends.SDL3 ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed); ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount); - ulong currentSamplePlayed = Interlocked.Add(ref driverBuffer.SamplePlayed, playedAudioBufferSampleCount); + ulong currentSamplePlayed = + Interlocked.Add(ref driverBuffer.SamplePlayed, playedAudioBufferSampleCount); availaibleSampleCount -= playedAudioBufferSampleCount; if (currentSamplePlayed == driverBuffer.SampleCount) @@ -152,12 +162,27 @@ namespace Ryujinx.Audio.Backends.SDL3 public override void QueueBuffer(AudioBuffer buffer) { EnsureAudioStreamSetup(buffer); - if (_outputStream != 0) { SDL3AudioBuffer driverBuffer = new(buffer.DataPointer, GetSampleCount(buffer)); _ringBuffer.Write(buffer.Data, 0, buffer.Data.Length); + int MinimumAudio = int.MaxValue; // 8000 float samples per second, half a second. + // SDL_ResumeAudioStreamDevice(_outputStream); + Console.WriteLine(SDL_GetAudioStreamAvailable(_outputStream)); + if (SDL_GetAudioStreamAvailable(_outputStream) < MinimumAudio) + { + unsafe + { + fixed (byte* samplesPtr = buffer.Data) + { + IntPtr buffer2 = (IntPtr)samplesPtr; + + SDL_PutAudioStreamData(_outputStream, buffer2, buffer.Data.Length); + + } + } + } _queuedBuffers.Enqueue(driverBuffer); } @@ -180,7 +205,7 @@ namespace Ryujinx.Audio.Backends.SDL3 { if (_outputStream != 0) { - SDL_ResumeAudioDevice(_outputStream); + SDL_ResumeAudioStreamDevice(_outputStream); } _started = true; @@ -193,7 +218,7 @@ namespace Ryujinx.Audio.Backends.SDL3 { if (_outputStream != 0) { - SDL_PauseAudioDevice(_outputStream); + SDL_PauseAudioStreamDevice(_outputStream); } _started = false; @@ -221,7 +246,7 @@ namespace Ryujinx.Audio.Backends.SDL3 if (_outputStream != 0) { - SDL_CloseAudioDevice(_outputStream); + SDL_DestroyAudioStream(_outputStream); } } } diff --git a/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs b/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs index 6c2a69b88..ec2fa14da 100644 --- a/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs +++ b/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs @@ -58,7 +58,7 @@ namespace Ryujinx.Common.Configuration.Hid return backendType switch { InputBackendType.WindowKeyboard => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardKeyboardInputConfig), - InputBackendType.GamepadSDL2 => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardControllerInputConfig), + InputBackendType.GamepadSDL3 => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardControllerInputConfig), _ => throw new InvalidOperationException($"Unknown backend type {backendType}"), }; } @@ -70,7 +70,7 @@ namespace Ryujinx.Common.Configuration.Hid case InputBackendType.WindowKeyboard: JsonSerializer.Serialize(writer, value as StandardKeyboardInputConfig, _serializerContext.StandardKeyboardInputConfig); break; - case InputBackendType.GamepadSDL2: + case InputBackendType.GamepadSDL3: JsonSerializer.Serialize(writer, value as StandardControllerInputConfig, _serializerContext.StandardControllerInputConfig); break; default: diff --git a/src/Ryujinx.SDL3-CS/SDL3.cs b/src/Ryujinx.SDL3-CS/SDL3.cs index 8afa0a94c..1ef410ddf 100644 --- a/src/Ryujinx.SDL3-CS/SDL3.cs +++ b/src/Ryujinx.SDL3-CS/SDL3.cs @@ -968,7 +968,7 @@ public static unsafe partial class SDL [LibraryImport(nativeLibName)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial IntPtr SDL_OpenAudioDeviceStream(uint devid, ref SDL_AudioSpec spec, SDL_AudioStreamCallback callback, IntPtr userdata); + public static partial IntPtr SDL_OpenAudioDeviceStream(uint devid, ref SDL_AudioSpec spec, SDL_AudioStreamCallback? callback, IntPtr userdata); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void SDL_AudioPostmixCallback(IntPtr userdata, SDL_AudioSpec* spec, float* buffer, int buflen); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml index bdaf0eba8..6f31d76ed 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml @@ -49,7 +49,7 @@ - +