소스 검색

audio: Cleanup Ryujinx.Audio and fix OpenAL issue (#1746)

* audio: Cleanup SoundIO and fix OpenAL issue

* fix tabs by spaces

* Fix extra spaces

* Fix SoundIO.cs

* Fix ContainsAudioOutBuffer
Ac_K 5 년 전
부모
커밋
7b66cb0d90
25개의 변경된 파일1630개의 추가작업 그리고 1493개의 파일을 삭제
  1. 0 91
      Ryujinx.Audio/Decoders/Adpcm/AdpcmDecoder.cs
  2. 0 10
      Ryujinx.Audio/Decoders/Adpcm/AdpcmDecoderContext.cs
  3. 14 16
      Ryujinx.Audio/Downmixing.cs
  4. 0 16
      Ryujinx.Audio/DspUtils.cs
  5. 6 10
      Ryujinx.Audio/IAalOutput.cs
  6. 1 1
      Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs
  7. 380 305
      Ryujinx.Audio/Native/libsoundio/SoundIO.cs
  8. 12 14
      Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs
  9. 22 18
      Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs
  10. 24 23
      Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs
  11. 74 76
      Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs
  12. 110 93
      Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs
  13. 261 214
      Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs
  14. 7 8
      Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs
  15. 5 8
      Ryujinx.Audio/Native/libsoundio/SoundIOException.cs
  16. 22 23
      Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs
  17. 286 221
      Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs
  18. 324 247
      Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs
  19. 55 58
      Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs
  20. 10 10
      Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs
  21. 1 1
      Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs
  22. 7 3
      Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs
  23. 0 1
      Ryujinx.Audio/Renderers/SoundIo/SoundIoAudioOut.cs
  24. 4 6
      Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs
  25. 5 20
      Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs

+ 0 - 91
Ryujinx.Audio/Decoders/Adpcm/AdpcmDecoder.cs

@@ -1,91 +0,0 @@
-namespace Ryujinx.Audio.Adpcm
-{
-    public static class AdpcmDecoder
-    {
-        private const int SamplesPerFrame = 14;
-        private const int BytesPerFrame   = 8;
-
-        public static int[] Decode(byte[] Buffer, AdpcmDecoderContext Context)
-        {
-            int Samples = GetSamplesCountFromSize(Buffer.Length);
-
-            int[] Pcm = new int[Samples * 2];
-
-            short History0 = Context.History0;
-            short History1 = Context.History1;
-
-            int InputOffset  = 0;
-            int OutputOffset = 0;
-
-            while (InputOffset < Buffer.Length)
-            {
-                byte Header = Buffer[InputOffset++];
-
-                int Scale = 0x800 << (Header & 0xf);
-
-                int CoeffIndex = (Header >> 4) & 7;
-
-                short Coeff0 = Context.Coefficients[CoeffIndex * 2 + 0];
-                short Coeff1 = Context.Coefficients[CoeffIndex * 2 + 1];
-
-                int FrameSamples = SamplesPerFrame;
-
-                if (FrameSamples > Samples)
-                {
-                    FrameSamples = Samples;
-                }
-
-                int Value = 0;
-
-                for (int SampleIndex = 0; SampleIndex < FrameSamples; SampleIndex++)
-                {
-                    int Sample;
-
-                    if ((SampleIndex & 1) == 0)
-                    {
-                        Value = Buffer[InputOffset++];
-
-                        Sample = (Value << 24) >> 28;
-                    }
-                    else
-                    {
-                        Sample = (Value << 28) >> 28;
-                    }
-
-                    int Prediction = Coeff0 * History0 + Coeff1 * History1;
-
-                    Sample = (Sample * Scale + Prediction + 0x400) >> 11;
-
-                    short SaturatedSample = DspUtils.Saturate(Sample);
-
-                    History1 = History0;
-                    History0 = SaturatedSample;
-
-                    Pcm[OutputOffset++] = SaturatedSample;
-                    Pcm[OutputOffset++] = SaturatedSample;
-                }
-
-                Samples -= FrameSamples;
-            }
-
-            Context.History0 = History0;
-            Context.History1 = History1;
-
-            return Pcm;
-        }
-
-        public static long GetSizeFromSamplesCount(int SamplesCount)
-        {
-            int Frames = SamplesCount / SamplesPerFrame;
-
-            return Frames * BytesPerFrame;
-        }
-
-        public static int GetSamplesCountFromSize(long Size)
-        {
-            int Frames = (int)(Size / BytesPerFrame);
-
-            return Frames * SamplesPerFrame;
-        }
-    }
-}

+ 0 - 10
Ryujinx.Audio/Decoders/Adpcm/AdpcmDecoderContext.cs

@@ -1,10 +0,0 @@
-namespace Ryujinx.Audio.Adpcm
-{
-    public class AdpcmDecoderContext
-    {
-        public short[] Coefficients;
-
-        public short History0;
-        public short History1;
-    }
-}

+ 14 - 16
Ryujinx.Audio/Downmixing.cs

@@ -24,27 +24,31 @@ namespace Ryujinx.Audio
             public short Right;
             public short Right;
         }
         }
 
 
-        private const int Q15Bits = 16;
-        private const int RawQ15One = 1 << Q15Bits;
-        private const int RawQ15HalfOne = (int)(0.5f * RawQ15One);
-        private const int Minus3dBInQ15 = (int)(0.707f * RawQ15One);
-        private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
+        private const int Q15Bits        = 16;
+        private const int RawQ15One      = 1 << Q15Bits;
+        private const int RawQ15HalfOne  = (int)(0.5f * RawQ15One);
+        private const int Minus3dBInQ15  = (int)(0.707f * RawQ15One);
+        private const int Minus6dBInQ15  = (int)(0.501f * RawQ15One);
         private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
         private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
 
 
-        private static int[] DefaultSurroundToStereoCoefficients = new int[4]
+        private static readonly int[] DefaultSurroundToStereoCoefficients = new int[4]
         {
         {
             RawQ15One,
             RawQ15One,
             Minus3dBInQ15,
             Minus3dBInQ15,
             Minus12dBInQ15,
             Minus12dBInQ15,
-            Minus3dBInQ15,
+            Minus3dBInQ15
         };
         };
 
 
-        private static int[] DefaultStereoToMonoCoefficients = new int[2]
+        private static readonly int[] DefaultStereoToMonoCoefficients = new int[2]
         {
         {
             Minus6dBInQ15,
             Minus6dBInQ15,
-            Minus6dBInQ15,
+            Minus6dBInQ15
         };
         };
 
 
+        private const int SurroundChannelCount = 6;
+        private const int StereoChannelCount   = 2;
+        private const int MonoChannelCount     = 1;
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static ReadOnlySpan<Channel51FormatPCM16> GetSurroundBuffer(ReadOnlySpan<short> data)
         private static ReadOnlySpan<Channel51FormatPCM16> GetSurroundBuffer(ReadOnlySpan<short> data)
         {
         {
@@ -72,9 +76,6 @@ namespace Ryujinx.Audio
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static short[] DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
         private static short[] DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
         {
         {
-            const int SurroundChannelCount = 6;
-            const int StereoChannelCount = 2;
-
             int samplePerChannelCount = data.Length / SurroundChannelCount;
             int samplePerChannelCount = data.Length / SurroundChannelCount;
 
 
             short[] downmixedBuffer = new short[samplePerChannelCount * StereoChannelCount];
             short[] downmixedBuffer = new short[samplePerChannelCount * StereoChannelCount];
@@ -85,7 +86,7 @@ namespace Ryujinx.Audio
             {
             {
                 Channel51FormatPCM16 channel = channels[i];
                 Channel51FormatPCM16 channel = channels[i];
 
 
-                downmixedBuffer[i * 2] = DownMixSurroundToStereo(coefficients, channel.BackLeft, channel.LowFrequency, channel.FrontCenter, channel.FrontLeft);
+                downmixedBuffer[i * 2]     = DownMixSurroundToStereo(coefficients, channel.BackLeft, channel.LowFrequency, channel.FrontCenter, channel.FrontLeft);
                 downmixedBuffer[i * 2 + 1] = DownMixSurroundToStereo(coefficients, channel.BackRight, channel.LowFrequency, channel.FrontCenter, channel.FrontRight);
                 downmixedBuffer[i * 2 + 1] = DownMixSurroundToStereo(coefficients, channel.BackRight, channel.LowFrequency, channel.FrontCenter, channel.FrontRight);
             }
             }
 
 
@@ -95,9 +96,6 @@ namespace Ryujinx.Audio
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static short[] DownMixStereoToMono(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
         private static short[] DownMixStereoToMono(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
         {
         {
-            const int StereoChannelCount = 2;
-            const int MonoChannelCount = 1;
-
             int samplePerChannelCount = data.Length / StereoChannelCount;
             int samplePerChannelCount = data.Length / StereoChannelCount;
 
 
             short[] downmixedBuffer = new short[samplePerChannelCount * MonoChannelCount];
             short[] downmixedBuffer = new short[samplePerChannelCount * MonoChannelCount];

+ 0 - 16
Ryujinx.Audio/DspUtils.cs

@@ -1,16 +0,0 @@
-namespace Ryujinx.Audio
-{
-    public static class DspUtils
-    {
-        public static short Saturate(int Value)
-        {
-            if (Value > short.MaxValue)
-                Value = short.MaxValue;
-
-            if (Value < short.MinValue)
-                Value = short.MinValue;
-
-            return (short)Value;
-        }
-    }
-}

+ 6 - 10
Ryujinx.Audio/IAalOutput.cs

@@ -13,17 +13,13 @@ namespace Ryujinx.Audio
                 return targetChannelCount;
                 return targetChannelCount;
             }
             }
 
 
-            switch (targetChannelCount)
+            return targetChannelCount switch
             {
             {
-                case 6:
-                    return SelectHardwareChannelCount(2);
-                case 2:
-                    return SelectHardwareChannelCount(1);
-                case 1:
-                    throw new ArgumentException("No valid channel configuration found!");
-                default:
-                    throw new ArgumentException($"Invalid targetChannelCount {targetChannelCount}");
-            }
+                6 => SelectHardwareChannelCount(2),
+                2 => SelectHardwareChannelCount(1),
+                1 => throw new ArgumentException("No valid channel configuration found!"),
+                _ => throw new ArgumentException($"Invalid targetChannelCount {targetChannelCount}"),
+            };
         }
         }
 
 
         int OpenTrack(int sampleRate, int channels, ReleaseCallback callback)
         int OpenTrack(int sampleRate, int channels, ReleaseCallback callback)

+ 1 - 1
Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs

@@ -35,4 +35,4 @@ namespace SoundIOSharp
             Marshal.WriteInt32(handle, offset, BitConverter.SingleToInt32Bits(value));
             Marshal.WriteInt32(handle, offset, BitConverter.SingleToInt32Bits(value));
         }
         }
     }
     }
-}
+}

+ 380 - 305
Ryujinx.Audio/Native/libsoundio/SoundIO.cs

@@ -4,308 +4,383 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIO : IDisposable
-	{
-		Pointer<SoundIo> handle;
-
-		public SoundIO ()
-		{
-			handle = Natives.soundio_create ();
-		}
-
-		internal SoundIO (Pointer<SoundIo> handle)
-		{
-			this.handle = handle;
-		}
-
-		public void Dispose ()
-		{
-			foreach (var h in allocated_hglobals)
-				Marshal.FreeHGlobal (h);
-			Natives.soundio_destroy (handle);
-		}
-
-		// Equality (based on handle)
-
-		public override bool Equals (object other)
-		{
-			var d = other as SoundIO;
-			return d != null && this.handle == d.handle;
-		}
-
-		public override int GetHashCode ()
-		{
-			return (int) (IntPtr) handle;
-		}
-
-		public static bool operator == (SoundIO obj1, SoundIO obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 == null : obj1.Equals (obj2);
-		}
-
-		public static bool operator != (SoundIO obj1, SoundIO obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 != null : !obj1.Equals (obj2);
-		}
-
-		// fields
-
-		// FIXME: this should be taken care in more centralized/decent manner... we don't want to write
-		// this kind of code anywhere we need string marshaling.
-		List<IntPtr> allocated_hglobals = new List<IntPtr> ();
-
-		public string ApplicationName {
-			get { return Marshal.PtrToStringAnsi (Marshal.ReadIntPtr (handle, app_name_offset)); }
-			set {
-				unsafe {
-					var existing = Marshal.ReadIntPtr (handle, app_name_offset);
-					if (allocated_hglobals.Contains (existing)) {
-						allocated_hglobals.Remove (existing);
-						Marshal.FreeHGlobal (existing);
-					}
-					var ptr = Marshal.StringToHGlobalAnsi (value);
-					Marshal.WriteIntPtr (handle, app_name_offset, ptr);
-					allocated_hglobals.Add (ptr);
-				}
-			}
-		}
-		static readonly int app_name_offset = (int)Marshal.OffsetOf<SoundIo> ("app_name");
-
-		public SoundIOBackend CurrentBackend {
-			get { return (SoundIOBackend) Marshal.ReadInt32 (handle, current_backend_offset); }
-		}
-		static readonly int current_backend_offset = (int)Marshal.OffsetOf<SoundIo> ("current_backend");
-
-		// emit_rtprio_warning
-		public Action EmitRealtimePriorityWarning {
-			get { return emit_rtprio_warning; }
-			set {
-				emit_rtprio_warning = value;
-				var ptr = Marshal.GetFunctionPointerForDelegate (on_devices_change);
-				Marshal.WriteIntPtr (handle, emit_rtprio_warning_offset, ptr);
-			}
-		}
-		static readonly int emit_rtprio_warning_offset = (int)Marshal.OffsetOf<SoundIo> ("emit_rtprio_warning");
-		Action emit_rtprio_warning;
-
-		// jack_error_callback
-		public Action<string> JackErrorCallback {
-			get { return jack_error_callback; }
-			set {
-				jack_error_callback = value;
-				if (value == null)
-					jack_error_callback = null;
-				else
-					jack_error_callback_native = msg => jack_error_callback (msg);
-				var ptr = Marshal.GetFunctionPointerForDelegate (jack_error_callback_native);
-				Marshal.WriteIntPtr (handle, jack_error_callback_offset, ptr);
-			}
-		}
-		static readonly int jack_error_callback_offset = (int)Marshal.OffsetOf<SoundIo> ("jack_error_callback");
-		Action<string> jack_error_callback;
-		delegate void jack_error_delegate (string message);
-		jack_error_delegate jack_error_callback_native;
-
-		// jack_info_callback
-		public Action<string> JackInfoCallback {
-			get { return jack_info_callback; }
-			set {
-				jack_info_callback = value;
-				if (value == null)
-					jack_info_callback = null;
-				else
-					jack_info_callback_native = msg => jack_info_callback (msg);
-				var ptr = Marshal.GetFunctionPointerForDelegate (jack_info_callback_native);
-				Marshal.WriteIntPtr (handle, jack_info_callback_offset, ptr);
-			}
-		}
-		static readonly int jack_info_callback_offset = (int)Marshal.OffsetOf<SoundIo> ("jack_info_callback");
-		Action<string> jack_info_callback;
-		delegate void jack_info_delegate (string message);
-		jack_info_delegate jack_info_callback_native;
-
-		// on_backend_disconnect
-		public Action<int> OnBackendDisconnect {
-			get { return on_backend_disconnect; }
-			set {
-				on_backend_disconnect = value;
-				if (value == null)
-					on_backend_disconnect_native = null;
-				else
-					on_backend_disconnect_native = (sio, err) => on_backend_disconnect (err);
-				var ptr = Marshal.GetFunctionPointerForDelegate (on_backend_disconnect_native);
-				Marshal.WriteIntPtr (handle, on_backend_disconnect_offset, ptr);
-			}
-		}
-		static readonly int on_backend_disconnect_offset = (int)Marshal.OffsetOf<SoundIo> ("on_backend_disconnect");
-		Action<int> on_backend_disconnect;
-		delegate void on_backend_disconnect_delegate (IntPtr handle, int errorCode);
-		on_backend_disconnect_delegate on_backend_disconnect_native;
-
-		// on_devices_change
-		public Action OnDevicesChange {
-			get { return on_devices_change; }
-			set {
-				on_devices_change = value;
-				if (value == null)
-					on_devices_change_native = null;
-				else
-					on_devices_change_native = sio => on_devices_change ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (on_devices_change_native);
-				Marshal.WriteIntPtr (handle, on_devices_change_offset, ptr);
-			}
-		}
-		static readonly int on_devices_change_offset = (int)Marshal.OffsetOf<SoundIo> ("on_devices_change");
-		Action on_devices_change;
-		delegate void on_devices_change_delegate (IntPtr handle);
-		on_devices_change_delegate on_devices_change_native;
-
-		// on_events_signal
-		public Action OnEventsSignal {
-			get { return on_events_signal; }
-			set {
-				on_events_signal = value;
-				if (value == null)
-					on_events_signal_native = null;
-				else
-					on_events_signal_native = sio => on_events_signal ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (on_events_signal_native);
-				Marshal.WriteIntPtr (handle, on_events_signal_offset, ptr);
-			}
-		}
-		static readonly int on_events_signal_offset = (int)Marshal.OffsetOf<SoundIo> ("on_events_signal");
-		Action on_events_signal;
-		delegate void on_events_signal_delegate (IntPtr handle);
-		on_events_signal_delegate on_events_signal_native;
-
-
-		// functions
-
-		public int BackendCount {
-			get { return Natives.soundio_backend_count (handle); }
-		}
-
-		public int InputDeviceCount {
-			get { return Natives.soundio_input_device_count (handle); }
-		}
-
-		public int OutputDeviceCount {
-			get { return Natives.soundio_output_device_count (handle); }
-		}
-
-		public int DefaultInputDeviceIndex {
-			get { return Natives.soundio_default_input_device_index (handle); }
-		}
-
-		public int DefaultOutputDeviceIndex {
-			get { return Natives.soundio_default_output_device_index (handle); }
-		}
-
-		public SoundIOBackend GetBackend (int index)
-		{
-			return (SoundIOBackend) Natives.soundio_get_backend (handle, index);
-		}
-
-		public SoundIODevice GetInputDevice (int index)
-		{
-			return new SoundIODevice (Natives.soundio_get_input_device (handle, index));
-		}
-
-		public SoundIODevice GetOutputDevice (int index)
-		{
-			return new SoundIODevice (Natives.soundio_get_output_device (handle, index));
-		}
-
-		public void Connect ()
-		{
-			var ret = (SoundIoError) Natives.soundio_connect (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void ConnectBackend (SoundIOBackend backend)
-		{
-			var ret = (SoundIoError) Natives.soundio_connect_backend (handle, (SoundIoBackend) backend);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void Disconnect ()
-		{
-			Natives.soundio_disconnect (handle);
-		}
-
-		public void FlushEvents ()
-		{
-			Natives.soundio_flush_events (handle);
-		}
-
-		public void WaitEvents ()
-		{
-			Natives.soundio_wait_events (handle);
-		}
-
-		public void Wakeup ()
-		{
-			Natives.soundio_wakeup (handle);
-		}
-
-		public void ForceDeviceScan ()
-		{
-			Natives.soundio_force_device_scan (handle);
-		}
-
-		public SoundIORingBuffer CreateRingBuffer (int capacity)
-		{
-			return new SoundIORingBuffer (Natives.soundio_ring_buffer_create (handle, capacity));
-		}
-
-		// static methods
-
-		public static string VersionString {
-			get { return Marshal.PtrToStringAnsi (Natives.soundio_version_string ()); }
-		}
-
-		public static int VersionMajor {
-			get { return Natives.soundio_version_major (); }
-		}
-
-		public static int VersionMinor {
-			get { return Natives.soundio_version_minor (); }
-		}
-
-		public static int VersionPatch {
-			get { return Natives.soundio_version_patch (); }
-		}
-
-		public static string GetBackendName (SoundIOBackend backend)
-		{
-			return Marshal.PtrToStringAnsi (Natives.soundio_backend_name ((SoundIoBackend) backend));
-		}
-
-		public static bool HaveBackend (SoundIOBackend backend)
-		{
-			return Natives.soundio_have_backend ((SoundIoBackend) backend);
-		}
-
-		public static int GetBytesPerSample (SoundIOFormat format)
-		{
-			return Natives.soundio_get_bytes_per_sample ((SoundIoFormat) format);
-		}
-
-		public static int GetBytesPerFrame (SoundIOFormat format, int channelCount)
-		{
-			return Natives.soundio_get_bytes_per_frame ((SoundIoFormat) format, channelCount);
-		}
-
-		public static int GetBytesPerSecond (SoundIOFormat format, int channelCount, int sampleRate)
-		{
-			return Natives.soundio_get_bytes_per_second ((SoundIoFormat) format, channelCount, sampleRate);
-		}
-
-		public static string GetSoundFormatName (SoundIOFormat format)
-		{
-			return Marshal.PtrToStringAnsi (Natives.soundio_format_string ((SoundIoFormat) format));
-		}
-	}
-}
+    public class SoundIO : IDisposable
+    {
+        Pointer<SoundIo> handle;
+
+        public SoundIO()
+        {
+            handle = Natives.soundio_create();
+        }
+
+        internal SoundIO(Pointer<SoundIo> handle)
+        {
+            this.handle = handle;
+        }
+
+        public void Dispose ()
+        {
+            foreach (var h in allocated_hglobals)
+            {
+                Marshal.FreeHGlobal(h);
+            }
+
+            Natives.soundio_destroy(handle);
+        }
+
+        // Equality (based on handle)
+
+        public override bool Equals(object other)
+        {
+            var d = other as SoundIO;
+
+            return d != null && this.handle == d.handle;
+        }
+
+        public override int GetHashCode()
+        {
+            return (int)(IntPtr)handle;
+        }
+
+        public static bool operator == (SoundIO obj1, SoundIO obj2)
+        {
+            return obj1 is null ? obj2 is null : obj1.Equals(obj2);
+        }
+
+        public static bool operator != (SoundIO obj1, SoundIO obj2)
+        {
+            return obj1 is null ? obj2 is object : !obj1.Equals(obj2);
+        }
+
+        // fields
+
+        // FIXME: this should be taken care in more centralized/decent manner... we don't want to write
+        // this kind of code anywhere we need string marshaling.
+        List<IntPtr> allocated_hglobals = new List<IntPtr>();
+
+        public string ApplicationName {
+            get { return Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(handle, app_name_offset)); }
+            set
+            {
+                unsafe
+                {
+                    var existing = Marshal.ReadIntPtr(handle, app_name_offset);
+                    if (allocated_hglobals.Contains (existing))
+                    {
+                        allocated_hglobals.Remove(existing);
+                        Marshal.FreeHGlobal(existing);
+                    }
+
+                    var ptr = Marshal.StringToHGlobalAnsi(value);
+                    Marshal.WriteIntPtr(handle, app_name_offset, ptr);
+                    allocated_hglobals.Add(ptr);
+                }
+            }
+        }
+
+        static readonly int app_name_offset = (int)Marshal.OffsetOf<SoundIo>("app_name");
+
+        public SoundIOBackend CurrentBackend
+        {
+            get { return (SoundIOBackend)Marshal.ReadInt32(handle, current_backend_offset); }
+        }
+
+        static readonly int current_backend_offset = (int)Marshal.OffsetOf<SoundIo>("current_backend");
+
+        // emit_rtprio_warning
+        public Action EmitRealtimePriorityWarning
+        {
+            get { return emit_rtprio_warning; }
+            set
+            {
+                emit_rtprio_warning = value;
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(on_devices_change);
+
+                Marshal.WriteIntPtr(handle, emit_rtprio_warning_offset, ptr);
+            }
+        }
+
+        static readonly int emit_rtprio_warning_offset = (int)Marshal.OffsetOf<SoundIo>("emit_rtprio_warning");
+
+        Action emit_rtprio_warning;
+
+        // jack_error_callback
+        public Action<string> JackErrorCallback
+        {
+            get { return jack_error_callback; }
+            set
+            {
+                jack_error_callback = value;
+                if (value == null)
+                {
+                    jack_error_callback = null;
+                }
+                else
+                {
+                    jack_error_callback_native = msg => jack_error_callback(msg);
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(jack_error_callback_native);
+                Marshal.WriteIntPtr(handle, jack_error_callback_offset, ptr);
+            }
+        }
+
+        static readonly int jack_error_callback_offset = (int)Marshal.OffsetOf<SoundIo>("jack_error_callback");
+
+        Action<string> jack_error_callback;
+        delegate void jack_error_delegate(string message);
+        jack_error_delegate jack_error_callback_native;
+
+        // jack_info_callback
+        public Action<string> JackInfoCallback
+        {
+            get { return jack_info_callback; }
+            set
+            {
+                jack_info_callback = value;
+                if (value == null)
+                {
+                    jack_info_callback = null;
+                }
+                else
+                {
+                    jack_info_callback_native = msg => jack_info_callback(msg);
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(jack_info_callback_native);
+                Marshal.WriteIntPtr(handle, jack_info_callback_offset, ptr);
+            }
+        }
+
+        static readonly int jack_info_callback_offset = (int)Marshal.OffsetOf<SoundIo>("jack_info_callback");
+
+        Action<string> jack_info_callback;
+        delegate void jack_info_delegate(string message);
+        jack_info_delegate jack_info_callback_native;
+
+        // on_backend_disconnect
+        public Action<int> OnBackendDisconnect
+        {
+            get { return on_backend_disconnect; }
+            set
+            {
+                on_backend_disconnect = value;
+                if (value == null)
+                {
+                    on_backend_disconnect_native = null;
+                }
+                else
+                {
+                    on_backend_disconnect_native = (sio, err) => on_backend_disconnect(err);
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(on_backend_disconnect_native);
+                Marshal.WriteIntPtr(handle, on_backend_disconnect_offset, ptr);
+            }
+        }
+
+        static readonly int on_backend_disconnect_offset = (int)Marshal.OffsetOf<SoundIo>("on_backend_disconnect");
+
+        Action<int> on_backend_disconnect;
+        delegate void on_backend_disconnect_delegate(IntPtr handle, int errorCode);
+        on_backend_disconnect_delegate on_backend_disconnect_native;
+
+        // on_devices_change
+        public Action OnDevicesChange
+        {
+            get { return on_devices_change; }
+            set
+            {
+                on_devices_change = value;
+                if (value == null)
+                {
+                    on_devices_change_native = null;
+                }
+                else
+                {
+                    on_devices_change_native = sio => on_devices_change();
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(on_devices_change_native);
+                Marshal.WriteIntPtr(handle, on_devices_change_offset, ptr);
+            }
+        }
+
+        static readonly int on_devices_change_offset = (int)Marshal.OffsetOf<SoundIo>("on_devices_change");
+
+        Action on_devices_change;
+        delegate void on_devices_change_delegate(IntPtr handle);
+        on_devices_change_delegate on_devices_change_native;
+
+        // on_events_signal
+        public Action OnEventsSignal
+        {
+            get { return on_events_signal; }
+            set
+            {
+                on_events_signal = value;
+                if (value == null)
+                {
+                    on_events_signal_native = null;
+                }
+                else
+                {
+                    on_events_signal_native = sio => on_events_signal();
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(on_events_signal_native);
+                Marshal.WriteIntPtr(handle, on_events_signal_offset, ptr);
+            }
+        }
+
+        static readonly int on_events_signal_offset = (int)Marshal.OffsetOf<SoundIo>("on_events_signal");
+
+        Action on_events_signal;
+        delegate void on_events_signal_delegate(IntPtr handle);
+        on_events_signal_delegate on_events_signal_native;
+
+
+        // functions
+
+        public int BackendCount
+        {
+            get { return Natives.soundio_backend_count(handle); }
+        }
+
+        public int InputDeviceCount
+        {
+            get { return Natives.soundio_input_device_count(handle); }
+        }
+
+        public int OutputDeviceCount
+        {
+            get { return Natives.soundio_output_device_count(handle); }
+        }
+
+        public int DefaultInputDeviceIndex
+        {
+            get { return Natives.soundio_default_input_device_index(handle); }
+        }
+
+        public int DefaultOutputDeviceIndex
+        {
+            get { return Natives.soundio_default_output_device_index(handle); }
+        }
+
+        public SoundIOBackend GetBackend(int index)
+        {
+            return (SoundIOBackend)Natives.soundio_get_backend(handle, index);
+        }
+
+        public SoundIODevice GetInputDevice(int index)
+        {
+            return new SoundIODevice(Natives.soundio_get_input_device(handle, index));
+        }
+
+        public SoundIODevice GetOutputDevice(int index)
+        {
+            return new SoundIODevice(Natives.soundio_get_output_device(handle, index));
+        }
+
+        public void Connect()
+        {
+            var ret = (SoundIoError)Natives.soundio_connect(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void ConnectBackend(SoundIOBackend backend)
+        {
+            var ret = (SoundIoError)Natives.soundio_connect_backend(handle, (SoundIoBackend)backend);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void Disconnect()
+        {
+            Natives.soundio_disconnect(handle);
+        }
+
+        public void FlushEvents()
+        {
+            Natives.soundio_flush_events(handle);
+        }
+
+        public void WaitEvents()
+        {
+            Natives.soundio_wait_events(handle);
+        }
+
+        public void Wakeup()
+        {
+            Natives.soundio_wakeup(handle);
+        }
+
+        public void ForceDeviceScan()
+        {
+            Natives.soundio_force_device_scan(handle);
+        }
+
+        public SoundIORingBuffer CreateRingBuffer(int capacity)
+        {
+            return new SoundIORingBuffer(Natives.soundio_ring_buffer_create(handle, capacity));
+        }
+
+        // static methods
+
+        public static string VersionString
+        {
+            get { return Marshal.PtrToStringAnsi(Natives.soundio_version_string()); }
+        }
+
+        public static int VersionMajor
+        {
+            get { return Natives.soundio_version_major(); }
+        }
+
+        public static int VersionMinor
+        {
+            get { return Natives.soundio_version_minor(); }
+        }
+
+        public static int VersionPatch
+        {
+            get { return Natives.soundio_version_patch(); }
+        }
+
+        public static string GetBackendName(SoundIOBackend backend)
+        {
+            return Marshal.PtrToStringAnsi(Natives.soundio_backend_name((SoundIoBackend)backend));
+        }
+
+        public static bool HaveBackend(SoundIOBackend backend)
+        {
+            return Natives.soundio_have_backend((SoundIoBackend)backend);
+        }
+
+        public static int GetBytesPerSample(SoundIOFormat format)
+        {
+            return Natives.soundio_get_bytes_per_sample((SoundIoFormat)format);
+        }
+
+        public static int GetBytesPerFrame(SoundIOFormat format, int channelCount)
+        {
+            return Natives.soundio_get_bytes_per_frame((SoundIoFormat)format, channelCount);
+        }
+
+        public static int GetBytesPerSecond(SoundIOFormat format, int channelCount, int sampleRate)
+        {
+            return Natives.soundio_get_bytes_per_second((SoundIoFormat)format, channelCount, sampleRate);
+        }
+
+        public static string GetSoundFormatName(SoundIOFormat format)
+        {
+            return Marshal.PtrToStringAnsi(Natives.soundio_format_string((SoundIoFormat)format));
+        }
+    }
+}

+ 12 - 14
Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs

@@ -1,15 +1,13 @@
-using System;
-namespace SoundIOSharp
+namespace SoundIOSharp
 {
 {
-	public enum SoundIOBackend
-	{
-		None = 0,
-		Jack = 1,
-		PulseAudio = 2,
-		Alsa = 3,
-		CoreAudio = 4,
-		Wasapi = 5,
-		Dummy = 6,
-	}
-
-}
+    public enum SoundIOBackend
+    {
+        None,
+        Jack,
+        PulseAudio,
+        Alsa,
+        CoreAudio,
+        Wasapi,
+        Dummy
+    }
+}

+ 22 - 18
Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs

@@ -3,24 +3,28 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public struct SoundIOChannelArea
-	{
-		internal SoundIOChannelArea (Pointer<SoundIoChannelArea> handle)
-		{
-			this.handle = handle;
-		}
+    public struct SoundIOChannelArea
+    {
+        internal SoundIOChannelArea(Pointer<SoundIoChannelArea> handle)
+        {
+            this.handle = handle;
+        }
 
 
-		Pointer<SoundIoChannelArea> handle;
+        Pointer<SoundIoChannelArea> handle;
 
 
-		public IntPtr Pointer {
-			get { return Marshal.ReadIntPtr (handle, ptr_offset); }
-			set { Marshal.WriteIntPtr (handle, ptr_offset, value); }
-		}
-		static readonly int ptr_offset = (int) Marshal.OffsetOf<SoundIoChannelArea> ("ptr");
+        public IntPtr Pointer
+        {
+            get { return Marshal.ReadIntPtr(handle, ptr_offset); }
+            set { Marshal.WriteIntPtr(handle, ptr_offset, value); }
+        }
 
 
-		public int Step {
-			get { return Marshal.ReadInt32 (handle, step_offset); }
-		}
-		static readonly int step_offset = (int)Marshal.OffsetOf<SoundIoChannelArea> ("step");
-	}
-}
+        static readonly int ptr_offset = (int)Marshal.OffsetOf<SoundIoChannelArea>("ptr");
+
+        public int Step
+        {
+            get { return Marshal.ReadInt32(handle, step_offset); }
+        }
+
+        static readonly int step_offset = (int)Marshal.OffsetOf<SoundIoChannelArea>("step");
+    }
+}

+ 24 - 23
Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs

@@ -3,31 +3,32 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public struct SoundIOChannelAreas
-	{
-		static readonly int native_size = Marshal.SizeOf<SoundIoChannelArea> ();
+    public struct SoundIOChannelAreas
+    {
+        static readonly int native_size = Marshal.SizeOf<SoundIoChannelArea>();
 
 
-		internal SoundIOChannelAreas (IntPtr head, int channelCount, int frameCount)
-		{
-			this.head = head;
-			this.channel_count = channelCount;
-			this.frame_count = frameCount;
-		}
+        internal SoundIOChannelAreas(IntPtr head, int channelCount, int frameCount)
+        {
+            this.head          = head;
+            this.channel_count = channelCount;
+            this.frame_count   = frameCount;
+        }
 
 
-		IntPtr head;
-		int channel_count;
-		int frame_count;
+        IntPtr head;
+        int    channel_count;
+        int    frame_count;
 
 
-		public bool IsEmpty {
-			get { return head == IntPtr.Zero; }
-		}
+        public bool IsEmpty
+        {
+            get { return head == IntPtr.Zero; }
+        }
 
 
-		public SoundIOChannelArea GetArea (int channel)
-		{
-			return new SoundIOChannelArea (head + native_size * channel);
-		}
+        public SoundIOChannelArea GetArea(int channel)
+        {
+            return new SoundIOChannelArea(head + native_size * channel);
+        }
 
 
-		public int ChannelCount => channel_count;
-		public int FrameCount => frame_count;
-	}
-}
+        public int ChannelCount => channel_count;
+        public int FrameCount => frame_count;
+    }
+}

+ 74 - 76
Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs

@@ -1,77 +1,75 @@
-using System;
-namespace SoundIOSharp
+namespace SoundIOSharp
 {
 {
-
-	public enum SoundIOChannelId
-	{
-		Invalid = 0,
-		FrontLeft = 1,
-		FrontRight = 2,
-		FrontCenter = 3,
-		Lfe = 4,
-		BackLeft = 5,
-		BackRight = 6,
-		FrontLeftCenter = 7,
-		FrontRightCenter = 8,
-		BackCenter = 9,
-		SideLeft = 10,
-		SideRight = 11,
-		TopCenter = 12,
-		TopFrontLeft = 13,
-		TopFrontCenter = 14,
-		TopFrontRight = 15,
-		TopBackLeft = 16,
-		TopBackCenter = 17,
-		TopBackRight = 18,
-		BackLeftCenter = 19,
-		BackRightCenter = 20,
-		FrontLeftWide = 21,
-		FrontRightWide = 22,
-		FrontLeftHigh = 23,
-		FrontCenterHigh = 24,
-		FrontRightHigh = 25,
-		TopFrontLeftCenter = 26,
-		TopFrontRightCenter = 27,
-		TopSideLeft = 28,
-		TopSideRight = 29,
-		LeftLfe = 30,
-		RightLfe = 31,
-		Lfe2 = 32,
-		BottomCenter = 33,
-		BottomLeftCenter = 34,
-		BottomRightCenter = 35,
-		MsMid = 36,
-		MsSide = 37,
-		AmbisonicW = 38,
-		AmbisonicX = 39,
-		AmbisonicY = 40,
-		AmbisonicZ = 41,
-		XyX = 42,
-		XyY = 43,
-		HeadphonesLeft = 44,
-		HeadphonesRight = 45,
-		ClickTrack = 46,
-		ForeignLanguage = 47,
-		HearingImpaired = 48,
-		Narration = 49,
-		Haptic = 50,
-		DialogCentricMix = 51,
-		Aux = 52,
-		Aux0 = 53,
-		Aux1 = 54,
-		Aux2 = 55,
-		Aux3 = 56,
-		Aux4 = 57,
-		Aux5 = 58,
-		Aux6 = 59,
-		Aux7 = 60,
-		Aux8 = 61,
-		Aux9 = 62,
-		Aux10 = 63,
-		Aux11 = 64,
-		Aux12 = 65,
-		Aux13 = 66,
-		Aux14 = 67,
-		Aux15 = 68,
-	}
-}
+    public enum SoundIOChannelId
+    {
+        Invalid,
+        FrontLeft,
+        FrontRight,
+        FrontCenter,
+        Lfe,
+        BackLeft,
+        BackRight,
+        FrontLeftCenter,
+        FrontRightCenter,
+        BackCenter,
+        SideLeft,
+        SideRight,
+        TopCenter,
+        TopFrontLeft,
+        TopFrontCenter,
+        TopFrontRight,
+        TopBackLeft,
+        TopBackCenter,
+        TopBackRight,
+        BackLeftCenter,
+        BackRightCenter,
+        FrontLeftWide,
+        FrontRightWide,
+        FrontLeftHigh,
+        FrontCenterHigh,
+        FrontRightHigh,
+        TopFrontLeftCenter,
+        TopFrontRightCenter,
+        TopSideLeft,
+        TopSideRight,
+        LeftLfe,
+        RightLfe,
+        Lfe2,
+        BottomCenter,
+        BottomLeftCenter,
+        BottomRightCenter,
+        MsMid,
+        MsSide,
+        AmbisonicW,
+        AmbisonicX,
+        AmbisonicY,
+        AmbisonicZ,
+        XyX,
+        XyY,
+        HeadphonesLeft,
+        HeadphonesRight,
+        ClickTrack,
+        ForeignLanguage,
+        HearingImpaired,
+        Narration,
+        Haptic,
+        DialogCentricMix,
+        Aux,
+        Aux0,
+        Aux1,
+        Aux2,
+        Aux3,
+        Aux4,
+        Aux5,
+        Aux6,
+        Aux7,
+        Aux8,
+        Aux9,
+        Aux10,
+        Aux11,
+        Aux12,
+        Aux13,
+        Aux14,
+        Aux15
+    }
+}

+ 110 - 93
Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs

@@ -1,99 +1,116 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public struct SoundIOChannelLayout
-	{
-		public static int BuiltInCount {
-			get { return Natives.soundio_channel_layout_builtin_count (); }
-		}
-
-		public static SoundIOChannelLayout GetBuiltIn (int index)
-		{
-			return new SoundIOChannelLayout (Natives.soundio_channel_layout_get_builtin (index));
-		}
-
-		public static SoundIOChannelLayout GetDefault (int channelCount)
-		{
-			var handle = Natives.soundio_channel_layout_get_default (channelCount);
-			return new SoundIOChannelLayout (handle);
-		}
-
-		public static SoundIOChannelId ParseChannelId (string name)
-		{
-			var ptr = Marshal.StringToHGlobalAnsi (name);
-			try {
-				return (SoundIOChannelId)Natives.soundio_parse_channel_id (ptr, name.Length);
-			} finally {
-				Marshal.FreeHGlobal (ptr);
-			}
-		}
-
-		// instance members
-
-		internal SoundIOChannelLayout (Pointer<SoundIoChannelLayout> handle)
-		{
-			this.handle = handle;
-		}
-
-		readonly Pointer<SoundIoChannelLayout> handle;
-
-		public bool IsNull {
-			get { return handle.Handle == IntPtr.Zero;  }
-		}
-
-		internal IntPtr Handle {
-			get { return handle; }
-		}
-
-		public int ChannelCount {
-			get { return IsNull ? 0 : Marshal.ReadInt32 ((IntPtr) handle + channel_count_offset); }
-		}
-		static readonly int channel_count_offset = (int) Marshal.OffsetOf<SoundIoChannelLayout> ("channel_count");
-
-		public string Name {
-			get { return IsNull ? null : Marshal.PtrToStringAnsi (Marshal.ReadIntPtr ((IntPtr) handle + name_offset)); }
-		}
-		static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoChannelLayout> ("name");
-
-		public IEnumerable<SoundIOChannelId> Channels {
-			get {
-				if (IsNull)
-					yield break;
-				for (int i = 0; i < 24; i++)
-					yield return (SoundIOChannelId) Marshal.ReadInt32 ((IntPtr) handle + channels_offset + sizeof (SoundIoChannelId) * i);
-			}
-		}
-		static readonly int channels_offset = (int)Marshal.OffsetOf<SoundIoChannelLayout> ("channels");
-
-		public override bool Equals (object other)
-		{
-			if (!(other is SoundIOChannelLayout))
-				return false;
-			var s = (SoundIOChannelLayout) other;
-			return handle == s.handle || Natives.soundio_channel_layout_equal (handle, s.handle);
-		}
-
-		public override int GetHashCode ()
-		{
-			return handle.GetHashCode ();
-		}
-
-		public string DetectBuiltInName ()
-		{
-			if (IsNull)
-				throw new InvalidOperationException ();
-			return Natives.soundio_channel_layout_detect_builtin (handle) ? Name : null;
-		}
-
-		public int FindChannel (SoundIOChannelId channel)
-		{
-			if (IsNull)
-				throw new InvalidOperationException ();
-			return Natives.soundio_channel_layout_find_channel (handle, (SoundIoChannelId) channel);
-		}
-	}
-}
+    public struct SoundIOChannelLayout
+    {
+        public static int BuiltInCount
+        {
+            get { return Natives.soundio_channel_layout_builtin_count(); }
+        }
+
+        public static SoundIOChannelLayout GetBuiltIn(int index)
+        {
+            return new SoundIOChannelLayout(Natives.soundio_channel_layout_get_builtin(index));
+        }
+
+        public static SoundIOChannelLayout GetDefault(int channelCount)
+        {
+            var handle = Natives.soundio_channel_layout_get_default(channelCount);
+
+            return new SoundIOChannelLayout (handle);
+        }
+
+        public static SoundIOChannelId ParseChannelId(string name)
+        {
+            var ptr = Marshal.StringToHGlobalAnsi(name);
+
+            try 
+            {
+                return (SoundIOChannelId)Natives.soundio_parse_channel_id(ptr, name.Length);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(ptr);
+            }
+        }
+
+        // instance members
+
+        internal SoundIOChannelLayout(Pointer<SoundIoChannelLayout> handle)
+        {
+            this.handle = handle;
+        }
+
+        readonly Pointer<SoundIoChannelLayout> handle;
+
+        public bool IsNull
+        {
+            get { return handle.Handle == IntPtr.Zero; }
+        }
+
+        internal IntPtr Handle
+        {
+            get { return handle; }
+        }
+
+        public int ChannelCount
+        {
+            get { return IsNull ? 0 : Marshal.ReadInt32((IntPtr)handle + channel_count_offset); }
+        }
+
+        static readonly int channel_count_offset = (int)Marshal.OffsetOf<SoundIoChannelLayout>("channel_count");
+
+        public string Name
+        {
+            get { return IsNull ? null : Marshal.PtrToStringAnsi(Marshal.ReadIntPtr((IntPtr)handle + name_offset)); }
+        }
+
+        static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoChannelLayout>("name");
+
+        public IEnumerable<SoundIOChannelId> Channels
+        {
+            get
+            {
+                if (IsNull) yield break;
+
+                for (int i = 0; i < 24; i++)
+                {
+                    yield return (SoundIOChannelId)Marshal.ReadInt32((IntPtr)handle + channels_offset + sizeof(SoundIoChannelId) * i);
+                }
+            }
+        }
+
+        static readonly int channels_offset = (int)Marshal.OffsetOf<SoundIoChannelLayout>("channels");
+
+        public override bool Equals(object other)
+        {
+            if (!(other is SoundIOChannelLayout)) return false;
+
+            var s = (SoundIOChannelLayout) other;
+
+            return handle == s.handle || Natives.soundio_channel_layout_equal(handle, s.handle);
+        }
+
+        public override int GetHashCode()
+        {
+            return handle.GetHashCode();
+        }
+
+        public string DetectBuiltInName()
+        {
+            if (IsNull) throw new InvalidOperationException();
+
+            return Natives.soundio_channel_layout_detect_builtin(handle) ? Name : null;
+        }
+
+        public int FindChannel(SoundIOChannelId channel)
+        {
+            if (IsNull) throw new InvalidOperationException();
+
+            return Natives.soundio_channel_layout_find_channel(handle, (SoundIoChannelId)channel);
+        }
+    }
+}

+ 261 - 214
Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs

@@ -4,217 +4,264 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIODevice
-	{
-		public static SoundIOChannelLayout BestMatchingChannelLayout (SoundIODevice device1, SoundIODevice device2)
-		{
-			var ptr1 = Marshal.ReadIntPtr (device1.handle, layouts_offset);
-			var ptr2 = Marshal.ReadIntPtr (device2.handle, layouts_offset);
-			return new SoundIOChannelLayout (Natives.soundio_best_matching_channel_layout (ptr1, device1.LayoutCount, ptr2, device2.LayoutCount));
-		}
-
-		internal SoundIODevice (Pointer<SoundIoDevice> handle)
-		{
-			this.handle = handle;
-		}
-
-		readonly Pointer<SoundIoDevice> handle;
-
-		// Equality (based on handle and native func)
-
-		public override bool Equals (object other)
-		{
-			var d = other as SoundIODevice;
-			return d != null && (this.handle == d.handle || Natives.soundio_device_equal (this.handle, d.handle));
-		}
-
-		public override int GetHashCode ()
-		{
-			return (int) (IntPtr) handle;
-		}
-
-		public static bool operator == (SoundIODevice obj1, SoundIODevice obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 == null : obj1.Equals (obj2);
-		}
-
-		public static bool operator != (SoundIODevice obj1, SoundIODevice obj2)
-		{
-			return (object)obj1 == null ? (object) obj2 != null : !obj1.Equals (obj2);
-		}
-
-		// fields
-
-		public SoundIODeviceAim Aim {
-			get { return (SoundIODeviceAim) Marshal.ReadInt32 (handle, aim_offset); }
-		}
-		static readonly int aim_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("aim");
-
-		public SoundIOFormat CurrentFormat {
-			get { return (SoundIOFormat) Marshal.ReadInt32 (handle, current_format_offset); }
-		}
-		static readonly int current_format_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("current_format");
-
-		public SoundIOChannelLayout CurrentLayout {
-			get { return new SoundIOChannelLayout ((IntPtr) handle + current_layout_offset);
-			}
-		}
-		static readonly int current_layout_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("current_layout");
-
-		public int FormatCount {
-			get { return Marshal.ReadInt32 (handle, format_count_offset); }
-		}
-		static readonly int format_count_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("format_count");
-
-		public IEnumerable<SoundIOFormat> Formats {
-			get {
-				var ptr = Marshal.ReadIntPtr (handle, formats_offset);
-				for (int i = 0; i < FormatCount; i++)
-					yield return (SoundIOFormat) Marshal.ReadInt32 (ptr, i);
-			}
-		}
-		static readonly int formats_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("formats");
-
-		public string Id {
-			get { return Marshal.PtrToStringAnsi (Marshal.ReadIntPtr (handle, id_offset)); }
-		}
-		static readonly int id_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("id");
-
-		public bool IsRaw {
-			get { return Marshal.ReadInt32 (handle, is_raw_offset) != 0; }
-		}
-		static readonly int is_raw_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("is_raw");
-
-		public int LayoutCount {
-			get { return Marshal.ReadInt32 (handle, layout_count_offset); }
-		}
-		static readonly int layout_count_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("layout_count");
-
-		public IEnumerable<SoundIOChannelLayout> Layouts {
-			get {
-				var ptr = Marshal.ReadIntPtr (handle, layouts_offset);
-				for (int i = 0; i < LayoutCount; i++)
-					yield return new SoundIOChannelLayout (ptr + i * Marshal.SizeOf<SoundIoChannelLayout> ());
-			}
-		}
-		static readonly int layouts_offset = (int) Marshal.OffsetOf<SoundIoDevice> ("layouts");
-
-		public string Name {
-			get { return Marshal.PtrToStringAnsi (Marshal.ReadIntPtr (handle, name_offset)); }
-		}
-		static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("name");
-
-		public int ProbeError {
-			get { return Marshal.ReadInt32 (handle, probe_error_offset); }
-		}
-		static readonly int probe_error_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("probe_error");
-
-		public int ReferenceCount {
-			get { return Marshal.ReadInt32 (handle, ref_count_offset); }
-		}
-		static readonly int ref_count_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("ref_count");
-
-		public int SampleRateCount {
-			get { return Marshal.ReadInt32 (handle, sample_rate_count_offset); }
-		}
-		static readonly int sample_rate_count_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("sample_rate_count");
-
-		public IEnumerable<SoundIOSampleRateRange> SampleRates {
-			get {
-				var ptr = Marshal.ReadIntPtr (handle, sample_rates_offset);
-				for (int i = 0; i < SampleRateCount; i++)
-					yield return new SoundIOSampleRateRange (
-						Marshal.ReadInt32 (ptr, i * 2),
-						Marshal.ReadInt32 (ptr, i * 2 + 1));
-			}
-		}
-		static readonly int sample_rates_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("sample_rates");
-
-		public double SoftwareLatencyCurrent {
-			get { return MarshalEx.ReadDouble (handle, software_latency_current_offset); }
-			set { MarshalEx.WriteDouble (handle, software_latency_current_offset, value); }
-		}
-		static readonly int software_latency_current_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("software_latency_current");
-
-		public double SoftwareLatencyMin {
-			get { return MarshalEx.ReadDouble (handle, software_latency_min_offset); }
-			set { MarshalEx.WriteDouble (handle, software_latency_min_offset, value); }
-		}
-		static readonly int software_latency_min_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("software_latency_min");
-
-		public double SoftwareLatencyMax {
-			get { return MarshalEx.ReadDouble (handle, software_latency_max_offset); }
-			set { MarshalEx.WriteDouble (handle, software_latency_max_offset, value); }
-		}
-		static readonly int software_latency_max_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("software_latency_max");
-
-		public SoundIO SoundIO {
-			get { return new SoundIO (Marshal.ReadIntPtr (handle, soundio_offset)); }
-		}
-		static readonly int soundio_offset = (int)Marshal.OffsetOf<SoundIoDevice> ("soundio");
-
-		// functions
-
-		public void AddReference ()
-		{
-			Natives.soundio_device_ref (handle);
-		}
-
-		public void RemoveReference ()
-		{
-			Natives.soundio_device_unref (handle);
-		}
-
-		public void SortDeviceChannelLayouts ()
-		{
-			Natives.soundio_device_sort_channel_layouts (handle);
-		}
-
-		public static readonly SoundIOFormat S16NE = BitConverter.IsLittleEndian ? SoundIOFormat.S16LE : SoundIOFormat.S16BE;
-		public static readonly SoundIOFormat U16NE = BitConverter.IsLittleEndian ? SoundIOFormat.U16LE : SoundIOFormat.U16BE;
-		public static readonly SoundIOFormat S24NE = BitConverter.IsLittleEndian ? SoundIOFormat.S24LE : SoundIOFormat.S24BE;
-		public static readonly SoundIOFormat U24NE = BitConverter.IsLittleEndian ? SoundIOFormat.U24LE : SoundIOFormat.U24BE;
-		public static readonly SoundIOFormat S32NE = BitConverter.IsLittleEndian ? SoundIOFormat.S32LE : SoundIOFormat.S32BE;
-		public static readonly SoundIOFormat U32NE = BitConverter.IsLittleEndian ? SoundIOFormat.U32LE : SoundIOFormat.U32BE;
-		public static readonly SoundIOFormat Float32NE = BitConverter.IsLittleEndian ? SoundIOFormat.Float32LE : SoundIOFormat.Float32BE;
-		public static readonly SoundIOFormat Float64NE = BitConverter.IsLittleEndian ? SoundIOFormat.Float64LE : SoundIOFormat.Float64BE;
-		public static readonly SoundIOFormat S16FE = !BitConverter.IsLittleEndian ? SoundIOFormat.S16LE : SoundIOFormat.S16BE;
-		public static readonly SoundIOFormat U16FE = !BitConverter.IsLittleEndian ? SoundIOFormat.U16LE : SoundIOFormat.U16BE;
-		public static readonly SoundIOFormat S24FE = !BitConverter.IsLittleEndian ? SoundIOFormat.S24LE : SoundIOFormat.S24BE;
-		public static readonly SoundIOFormat U24FE = !BitConverter.IsLittleEndian ? SoundIOFormat.U24LE : SoundIOFormat.U24BE;
-		public static readonly SoundIOFormat S32FE = !BitConverter.IsLittleEndian ? SoundIOFormat.S32LE : SoundIOFormat.S32BE;
-		public static readonly SoundIOFormat U32FE = !BitConverter.IsLittleEndian ? SoundIOFormat.U32LE : SoundIOFormat.U32BE;
-		public static readonly SoundIOFormat Float32FE = !BitConverter.IsLittleEndian ? SoundIOFormat.Float32LE : SoundIOFormat.Float32BE;
-		public static readonly SoundIOFormat Float64FE = !BitConverter.IsLittleEndian ? SoundIOFormat.Float64LE : SoundIOFormat.Float64BE;
-
-		public bool SupportsFormat (SoundIOFormat format)
-		{
-			return Natives.soundio_device_supports_format (handle, (SoundIoFormat) format);
-		}
-
-		public bool SupportsSampleRate (int sampleRate)
-		{
-			return Natives.soundio_device_supports_sample_rate (handle, sampleRate);
-		}
-
-		public bool SupportsChannelCount(int channelCount)
-		{
-			return Natives.soundio_device_supports_layout(handle, SoundIOChannelLayout.GetDefault(channelCount).Handle);
-		}
-
-		public int GetNearestSampleRate (int sampleRate)
-		{
-			return Natives.soundio_device_nearest_sample_rate (handle, sampleRate);
-		}
-
-		public SoundIOInStream CreateInStream ()
-		{
-			return new SoundIOInStream (Natives.soundio_instream_create (handle));
-		}
-
-		public SoundIOOutStream CreateOutStream ()
-		{
-			return new SoundIOOutStream (Natives.soundio_outstream_create (handle));
-		}
-	}
-}
+    public class SoundIODevice
+    {
+        public static SoundIOChannelLayout BestMatchingChannelLayout(SoundIODevice device1, SoundIODevice device2)
+        {
+            var ptr1 = Marshal.ReadIntPtr(device1.handle, layouts_offset);
+            var ptr2 = Marshal.ReadIntPtr(device2.handle, layouts_offset);
+
+            return new SoundIOChannelLayout(Natives.soundio_best_matching_channel_layout(ptr1, device1.LayoutCount, ptr2, device2.LayoutCount));
+        }
+
+        internal SoundIODevice(Pointer<SoundIoDevice> handle)
+        {
+            this.handle = handle;
+        }
+
+        readonly Pointer<SoundIoDevice> handle;
+
+        // Equality (based on handle and native func)
+
+        public override bool Equals(object other)
+        {
+            var d = other as SoundIODevice;
+
+            return d != null && (this.handle == d.handle || Natives.soundio_device_equal (this.handle, d.handle));
+        }
+
+        public override int GetHashCode()
+        {
+            return (int)(IntPtr)handle;
+        }
+
+        public static bool operator == (SoundIODevice obj1, SoundIODevice obj2)
+        {
+            return obj1 is null ? obj2 is null : obj1.Equals(obj2);
+        }
+
+        public static bool operator != (SoundIODevice obj1, SoundIODevice obj2)
+        {
+            return obj1 is null ? obj2 is object : !obj1.Equals(obj2);
+        }
+
+        // fields
+
+        public SoundIODeviceAim Aim
+        {
+            get { return (SoundIODeviceAim)Marshal.ReadInt32(handle, aim_offset); }
+        }
+
+        static readonly int aim_offset = (int)Marshal.OffsetOf<SoundIoDevice>("aim");
+
+        public SoundIOFormat CurrentFormat
+        {
+            get { return (SoundIOFormat)Marshal.ReadInt32(handle, current_format_offset); }
+        }
+
+        static readonly int current_format_offset = (int)Marshal.OffsetOf<SoundIoDevice>("current_format");
+
+        public SoundIOChannelLayout CurrentLayout
+        {
+            get { return new SoundIOChannelLayout((IntPtr)handle + current_layout_offset); }
+        }
+
+        static readonly int current_layout_offset = (int)Marshal.OffsetOf<SoundIoDevice>("current_layout");
+
+        public int FormatCount
+        {
+            get { return Marshal.ReadInt32(handle, format_count_offset); }
+        }
+
+        static readonly int format_count_offset = (int)Marshal.OffsetOf<SoundIoDevice>("format_count");
+
+        public IEnumerable<SoundIOFormat> Formats
+        {
+            get
+            {
+                var ptr = Marshal.ReadIntPtr(handle, formats_offset);
+
+                for (int i = 0; i < FormatCount; i++)
+                {
+                    yield return (SoundIOFormat)Marshal.ReadInt32(ptr, i);
+                }
+            }
+        }
+
+        static readonly int formats_offset = (int)Marshal.OffsetOf<SoundIoDevice>("formats");
+
+        public string Id
+        {
+            get { return Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(handle, id_offset)); }
+        }
+
+        static readonly int id_offset = (int)Marshal.OffsetOf<SoundIoDevice>("id");
+
+        public bool IsRaw
+        {
+            get { return Marshal.ReadInt32(handle, is_raw_offset) != 0; }
+        }
+
+        static readonly int is_raw_offset = (int)Marshal.OffsetOf<SoundIoDevice>("is_raw");
+
+        public int LayoutCount
+        {
+            get { return Marshal.ReadInt32(handle, layout_count_offset); }
+        }
+
+        static readonly int layout_count_offset = (int)Marshal.OffsetOf<SoundIoDevice>("layout_count");
+
+        public IEnumerable<SoundIOChannelLayout> Layouts
+        {
+            get
+            {
+                var ptr = Marshal.ReadIntPtr (handle, layouts_offset);
+
+                for (int i = 0; i < LayoutCount; i++)
+                {
+                    yield return new SoundIOChannelLayout(ptr + i * Marshal.SizeOf<SoundIoChannelLayout>());
+                }
+            }
+        }
+
+        static readonly int layouts_offset = (int)Marshal.OffsetOf<SoundIoDevice>("layouts");
+
+        public string Name
+        {
+            get { return Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(handle, name_offset)); }
+        }
+
+        static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoDevice>("name");
+
+        public int ProbeError
+        {
+            get { return Marshal.ReadInt32(handle, probe_error_offset); }
+        }
+
+        static readonly int probe_error_offset = (int)Marshal.OffsetOf<SoundIoDevice>("probe_error");
+
+        public int ReferenceCount
+        {
+            get { return Marshal.ReadInt32(handle, ref_count_offset); }
+        }
+
+        static readonly int ref_count_offset = (int)Marshal.OffsetOf<SoundIoDevice>("ref_count");
+
+        public int SampleRateCount
+        {
+            get { return Marshal.ReadInt32(handle, sample_rate_count_offset); }
+        }
+
+        static readonly int sample_rate_count_offset = (int)Marshal.OffsetOf<SoundIoDevice>("sample_rate_count");
+
+        public IEnumerable<SoundIOSampleRateRange> SampleRates
+        {
+            get
+            {
+                var ptr = Marshal.ReadIntPtr(handle, sample_rates_offset);
+
+                for (int i = 0; i < SampleRateCount; i++)
+                {
+                    yield return new SoundIOSampleRateRange(Marshal.ReadInt32(ptr, i * 2), Marshal.ReadInt32(ptr, i * 2 + 1));
+                }
+            }
+        }
+
+        static readonly int sample_rates_offset = (int)Marshal.OffsetOf<SoundIoDevice>("sample_rates");
+
+        public double SoftwareLatencyCurrent
+        {
+            get { return MarshalEx.ReadDouble(handle, software_latency_current_offset); }
+            set { MarshalEx.WriteDouble(handle, software_latency_current_offset, value); }
+        }
+
+        static readonly int software_latency_current_offset = (int)Marshal.OffsetOf<SoundIoDevice>("software_latency_current");
+
+        public double SoftwareLatencyMin
+        {
+            get { return MarshalEx.ReadDouble(handle, software_latency_min_offset); }
+            set { MarshalEx.WriteDouble(handle, software_latency_min_offset, value); }
+        }
+
+        static readonly int software_latency_min_offset = (int)Marshal.OffsetOf<SoundIoDevice>("software_latency_min");
+
+        public double SoftwareLatencyMax
+        {
+            get { return MarshalEx.ReadDouble(handle, software_latency_max_offset); }
+            set { MarshalEx.WriteDouble(handle, software_latency_max_offset, value); }
+        }
+
+        static readonly int software_latency_max_offset = (int)Marshal.OffsetOf<SoundIoDevice>("software_latency_max");
+
+        public SoundIO SoundIO
+        {
+            get { return new SoundIO(Marshal.ReadIntPtr(handle, soundio_offset)); }
+        }
+
+        static readonly int soundio_offset = (int)Marshal.OffsetOf<SoundIoDevice>("soundio");
+
+        // functions
+
+        public void AddReference()
+        {
+            Natives.soundio_device_ref(handle);
+        }
+
+        public void RemoveReference()
+        {
+            Natives.soundio_device_unref(handle);
+        }
+
+        public void SortDeviceChannelLayouts()
+        {
+            Natives.soundio_device_sort_channel_layouts(handle);
+        }
+
+        public static readonly SoundIOFormat S16NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.S16LE     : SoundIOFormat.S16BE;
+        public static readonly SoundIOFormat U16NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.U16LE     : SoundIOFormat.U16BE;
+        public static readonly SoundIOFormat S24NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.S24LE     : SoundIOFormat.S24BE;
+        public static readonly SoundIOFormat U24NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.U24LE     : SoundIOFormat.U24BE;
+        public static readonly SoundIOFormat S32NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.S32LE     : SoundIOFormat.S32BE;
+        public static readonly SoundIOFormat U32NE     =  BitConverter.IsLittleEndian ? SoundIOFormat.U32LE     : SoundIOFormat.U32BE;
+        public static readonly SoundIOFormat Float32NE =  BitConverter.IsLittleEndian ? SoundIOFormat.Float32LE : SoundIOFormat.Float32BE;
+        public static readonly SoundIOFormat Float64NE =  BitConverter.IsLittleEndian ? SoundIOFormat.Float64LE : SoundIOFormat.Float64BE;
+        public static readonly SoundIOFormat S16FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.S16LE     : SoundIOFormat.S16BE;
+        public static readonly SoundIOFormat U16FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.U16LE     : SoundIOFormat.U16BE;
+        public static readonly SoundIOFormat S24FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.S24LE     : SoundIOFormat.S24BE;
+        public static readonly SoundIOFormat U24FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.U24LE     : SoundIOFormat.U24BE;
+        public static readonly SoundIOFormat S32FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.S32LE     : SoundIOFormat.S32BE;
+        public static readonly SoundIOFormat U32FE     = !BitConverter.IsLittleEndian ? SoundIOFormat.U32LE     : SoundIOFormat.U32BE;
+        public static readonly SoundIOFormat Float32FE = !BitConverter.IsLittleEndian ? SoundIOFormat.Float32LE : SoundIOFormat.Float32BE;
+        public static readonly SoundIOFormat Float64FE = !BitConverter.IsLittleEndian ? SoundIOFormat.Float64LE : SoundIOFormat.Float64BE;
+
+        public bool SupportsFormat(SoundIOFormat format)
+        {
+            return Natives.soundio_device_supports_format(handle, (SoundIoFormat)format);
+        }
+
+        public bool SupportsSampleRate(int sampleRate)
+        {
+            return Natives.soundio_device_supports_sample_rate(handle, sampleRate);
+        }
+
+        public bool SupportsChannelCount(int channelCount)
+        {
+            return Natives.soundio_device_supports_layout(handle, SoundIOChannelLayout.GetDefault(channelCount).Handle);
+        }
+
+        public int GetNearestSampleRate(int sampleRate)
+        {
+            return Natives.soundio_device_nearest_sample_rate(handle, sampleRate);
+        }
+
+        public SoundIOInStream CreateInStream()
+        {
+            return new SoundIOInStream(Natives.soundio_instream_create(handle));
+        }
+
+        public SoundIOOutStream CreateOutStream()
+        {
+            return new SoundIOOutStream(Natives.soundio_outstream_create(handle));
+        }
+    }
+}

+ 7 - 8
Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs

@@ -1,9 +1,8 @@
-using System;
-namespace SoundIOSharp
+namespace SoundIOSharp
 {
 {
-	public enum SoundIODeviceAim // soundio.h (228, 6)
-	{
-		Input = 0,
-		Output = 1,
-	}
-}
+    public enum SoundIODeviceAim // soundio.h (228, 6)
+    {
+        Input,
+        Output
+    }
+}

+ 5 - 8
Ryujinx.Audio/Native/libsoundio/SoundIOException.cs

@@ -3,11 +3,8 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIOException : Exception
-	{
-		internal SoundIOException (SoundIoError errorCode)
-			: base (Marshal.PtrToStringAnsi (Natives.soundio_strerror ((int) errorCode)))
-		{
-		}
-	}
-}
+    public class SoundIOException : Exception
+    {
+        internal SoundIOException(SoundIoError errorCode) : base (Marshal.PtrToStringAnsi(Natives.soundio_strerror((int) errorCode))) { }
+    }
+}

+ 22 - 23
Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs

@@ -1,26 +1,25 @@
-using System;
-namespace SoundIOSharp
+namespace SoundIOSharp
 {
 {
-	public enum SoundIOFormat
+    public enum SoundIOFormat
 	{
 	{
-		Invalid = 0,
-		S8 = 1,
-		U8 = 2,
-		S16LE = 3,
-		S16BE = 4,
-		U16LE = 5,
-		U16BE = 6,
-		S24LE = 7,
-		S24BE = 8,
-		U24LE = 9,
-		U24BE = 10,
-		S32LE = 11,
-		S32BE = 12,
-		U32LE = 13,
-		U32BE = 14,
-		Float32LE = 15,
-		Float32BE = 16,
-		Float64LE = 17,
-		Float64BE = 18,
+		Invalid,
+		S8,
+		U8,
+		S16LE,
+		S16BE,
+		U16LE,
+		U16BE,
+		S24LE,
+		S24BE,
+		U24LE,
+		U24BE,
+		S32LE,
+		S32BE,
+		U32LE,
+		U32BE,
+		Float32LE,
+		Float32BE,
+		Float64LE,
+		Float64BE
 	}
 	}
-}
+}

+ 286 - 221
Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs

@@ -4,225 +4,290 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIOInStream : IDisposable
-	{
-		internal SoundIOInStream (Pointer<SoundIoInStream> handle)
-		{
-			this.handle = handle;
-		}
-
-		Pointer<SoundIoInStream> handle;
-
-		public void Dispose ()
-		{
-			Natives.soundio_instream_destroy (handle);
-		}
-
-		// Equality (based on handle)
-
-		public override bool Equals (object other)
-		{
-			var d = other as SoundIOInStream;
-			return d != null && (this.handle == d.handle);
-		}
-
-		public override int GetHashCode ()
-		{
-			return (int)(IntPtr)handle;
-		}
-
-		public static bool operator == (SoundIOInStream obj1, SoundIOInStream obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 == null : obj1.Equals (obj2);
-		}
-
-		public static bool operator != (SoundIOInStream obj1, SoundIOInStream obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 != null : !obj1.Equals (obj2);
-		}
-
-		// fields
-
-		public SoundIODevice Device {
-			get { return new SoundIODevice (Marshal.ReadIntPtr (handle, device_offset)); }
-		}
-		static readonly int device_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("device");
-
-		public SoundIOFormat Format {
-			get { return (SoundIOFormat) Marshal.ReadInt32 (handle, format_offset); }
-			set { Marshal.WriteInt32 (handle, format_offset, (int) value); }
-		}
-		static readonly int format_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("format");
-
-		public int SampleRate {
-			get { return Marshal.ReadInt32 (handle, sample_rate_offset); }
-			set { Marshal.WriteInt32 (handle, sample_rate_offset, value); }
-		}
-		static readonly int sample_rate_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("sample_rate");
-
-		public SoundIOChannelLayout Layout {
-			get { return new SoundIOChannelLayout ((IntPtr) handle + layout_offset); }
-			set {
-				unsafe {
-					Buffer.MemoryCopy ((void*) ((IntPtr) handle + layout_offset), (void*)value.Handle,
-							   Marshal.SizeOf<SoundIoChannelLayout> (), Marshal.SizeOf<SoundIoChannelLayout> ());
-				}
-			}
-		}
-		static readonly int layout_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("layout");
-
-
-		public double SoftwareLatency {
-			get { return MarshalEx.ReadDouble (handle, software_latency_offset); }
-			set { MarshalEx.WriteDouble (handle, software_latency_offset, value); }
-		}
-		static readonly int software_latency_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("software_latency");
-
-		// error_callback
-		public Action ErrorCallback {
-			get { return error_callback; }
-			set {
-				error_callback = value;
-				error_callback_native = _ => error_callback ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (error_callback_native);
-				Marshal.WriteIntPtr (handle, error_callback_offset, ptr);
-			}
-		}
-		static readonly int error_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("error_callback");
-		Action error_callback;
-		delegate void error_callback_delegate (IntPtr handle);
-		error_callback_delegate error_callback_native;
-
-		// read_callback
-		public Action<int,int> ReadCallback {
-			get { return read_callback; }
-			set {
-				read_callback = value;
-				read_callback_native = (_, minFrameCount, maxFrameCount) => read_callback (minFrameCount, maxFrameCount);
-				var ptr = Marshal.GetFunctionPointerForDelegate (read_callback_native);
-				Marshal.WriteIntPtr (handle, read_callback_offset, ptr);
-			}
-		}
-		static readonly int read_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("read_callback");
-		Action<int, int> read_callback;
-		delegate void read_callback_delegate (IntPtr handle, int min, int max);
-		read_callback_delegate read_callback_native;
-
-		// overflow_callback
-		public Action OverflowCallback {
-			get { return overflow_callback; }
-			set {
-				overflow_callback = value;
-				overflow_callback_native = _ => overflow_callback ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (overflow_callback_native);
-				Marshal.WriteIntPtr (handle, overflow_callback_offset, ptr);
-			}
-		}
-		static readonly int overflow_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("overflow_callback");
-		Action overflow_callback;
-		delegate void overflow_callback_delegate (IntPtr handle);
-		overflow_callback_delegate overflow_callback_native;
-
-		// FIXME: this should be taken care in more centralized/decent manner... we don't want to write
-		// this kind of code anywhere we need string marshaling.
-		List<IntPtr> allocated_hglobals = new List<IntPtr> ();
-
-		public string Name {
-			get { return Marshal.PtrToStringAnsi (Marshal.ReadIntPtr (handle, name_offset)); }
-			set {
-				unsafe {
-					var existing = Marshal.ReadIntPtr (handle, name_offset);
-					if (allocated_hglobals.Contains (existing)) {
-						allocated_hglobals.Remove (existing);
-						Marshal.FreeHGlobal (existing);
-					}
-					var ptr = Marshal.StringToHGlobalAnsi (value);
-					Marshal.WriteIntPtr (handle, name_offset, ptr);
-					allocated_hglobals.Add (ptr);
-				}
-			}
-		}
-		static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("name");
-
-		public bool NonTerminalHint {
-			get { return Marshal.ReadInt32 (handle, non_terminal_hint_offset) != 0; }
-		}
-		static readonly int non_terminal_hint_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("non_terminal_hint");
-
-		public int BytesPerFrame {
-			get { return Marshal.ReadInt32 (handle, bytes_per_frame_offset); }
-		}
-		static readonly int bytes_per_frame_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("bytes_per_frame");
-
-		public int BytesPerSample {
-			get { return Marshal.ReadInt32 (handle, bytes_per_sample_offset); }
-		}
-		static readonly int bytes_per_sample_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("bytes_per_sample");
-
-		public string LayoutErrorMessage {
-			get {
-				var code = (SoundIoError) Marshal.ReadInt32 (handle, layout_error_offset);
-				return code == SoundIoError.SoundIoErrorNone ? null : Marshal.PtrToStringAnsi (Natives.soundio_strerror ((int) code));
-			}
-		}
-		static readonly int layout_error_offset = (int)Marshal.OffsetOf<SoundIoInStream> ("layout_error");
-
-		// functions
-
-		public void Open ()
-		{
-			var ret = (SoundIoError) Natives.soundio_instream_open (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void Start ()
-		{
-			var ret = (SoundIoError)Natives.soundio_instream_start (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public SoundIOChannelAreas BeginRead (ref int frameCount)
-		{
-			IntPtr ptrs = default (IntPtr);
-			int nativeFrameCount = frameCount;
-			unsafe {
-				var frameCountPtr = &nativeFrameCount;
-				var ptrptr = &ptrs;
-				var ret = (SoundIoError) Natives.soundio_instream_begin_read (handle, (IntPtr)ptrptr, (IntPtr)frameCountPtr);
-				frameCount = *frameCountPtr;
-				if (ret != SoundIoError.SoundIoErrorNone)
-					throw new SoundIOException (ret);
-				return new SoundIOChannelAreas (ptrs, Layout.ChannelCount, frameCount);
-			}
-		}
-
-		public void EndRead ()
-		{
-			var ret = (SoundIoError) Natives.soundio_instream_end_read (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void Pause (bool pause)
-		{
-			var ret = (SoundIoError) Natives.soundio_instream_pause (handle, pause);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public double GetLatency ()
-		{
-			unsafe {
-				double* dptr = null;
-				IntPtr p = new IntPtr (dptr);
-				var ret = (SoundIoError) Natives.soundio_instream_get_latency (handle, p);
-				if (ret != SoundIoError.SoundIoErrorNone)
-					throw new SoundIOException (ret);
-				dptr = (double*) p;
-				return *dptr;
-			}
-		}
-	}
+    public class SoundIOInStream : IDisposable
+    {
+        internal SoundIOInStream(Pointer<SoundIoInStream> handle)
+        {
+            this.handle = handle;
+        }
+
+        Pointer<SoundIoInStream> handle;
+
+        public void Dispose()
+        {
+            Natives.soundio_instream_destroy(handle);
+        }
+
+        // Equality (based on handle)
+
+        public override bool Equals(object other)
+        {
+            var d = other as SoundIOInStream;
+
+            return d != null && (this.handle == d.handle);
+        }
+
+        public override int GetHashCode()
+        {
+            return (int)(IntPtr)handle;
+        }
+
+        public static bool operator == (SoundIOInStream obj1, SoundIOInStream obj2)
+        {
+            return obj1 is null ? obj2 is null : obj1.Equals(obj2);
+        }
+
+        public static bool operator != (SoundIOInStream obj1, SoundIOInStream obj2)
+        {
+            return obj1 is null ? obj2 is object : !obj1.Equals(obj2);
+        }
+
+        // fields
+
+        public SoundIODevice Device
+        {
+            get { return new SoundIODevice(Marshal.ReadIntPtr(handle, device_offset)); }
+        }
+
+        static readonly int device_offset = (int)Marshal.OffsetOf<SoundIoInStream>("device");
+
+        public SoundIOFormat Format
+        {
+            get { return (SoundIOFormat)Marshal.ReadInt32(handle, format_offset); }
+            set { Marshal.WriteInt32(handle, format_offset, (int) value); }
+        }
+
+        static readonly int format_offset = (int)Marshal.OffsetOf<SoundIoInStream>("format");
+
+        public int SampleRate
+        {
+            get { return Marshal.ReadInt32(handle, sample_rate_offset); }
+            set { Marshal.WriteInt32(handle, sample_rate_offset, value); }
+        }
+
+        static readonly int sample_rate_offset = (int)Marshal.OffsetOf<SoundIoInStream>("sample_rate");
+
+        public SoundIOChannelLayout Layout
+        {
+            get { return new SoundIOChannelLayout ((IntPtr) handle + layout_offset); }
+            set 
+            {
+                unsafe
+                {
+                    Buffer.MemoryCopy((void*)((IntPtr)handle + layout_offset), (void*)value.Handle, Marshal.SizeOf<SoundIoChannelLayout>(), Marshal.SizeOf<SoundIoChannelLayout>());
+                }
+            }
+        }
+
+        static readonly int layout_offset = (int)Marshal.OffsetOf<SoundIoInStream>("layout");
+
+        public double SoftwareLatency
+        {
+            get { return MarshalEx.ReadDouble(handle, software_latency_offset); }
+            set { MarshalEx.WriteDouble(handle, software_latency_offset, value); }
+        }
+
+        static readonly int software_latency_offset = (int)Marshal.OffsetOf<SoundIoInStream>("software_latency");
+
+        // error_callback
+        public Action ErrorCallback
+        {
+            get { return error_callback; }
+            set
+            {
+                error_callback = value;
+                error_callback_native = _ => error_callback();
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(error_callback_native);
+
+                Marshal.WriteIntPtr(handle, error_callback_offset, ptr);
+            }
+        }
+
+        static readonly int error_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream>("error_callback");
+
+        Action error_callback;
+        delegate void error_callback_delegate(IntPtr handle);
+        error_callback_delegate error_callback_native;
+
+        // read_callback
+        public Action<int,int> ReadCallback
+        {
+            get { return read_callback; }
+            set
+            {
+                read_callback = value;
+                read_callback_native = (_, minFrameCount, maxFrameCount) => read_callback(minFrameCount, maxFrameCount);
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(read_callback_native);
+
+                Marshal.WriteIntPtr(handle, read_callback_offset, ptr);
+            }
+        }
+
+        static readonly int read_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream>("read_callback");
+
+        Action<int, int> read_callback;
+        delegate void read_callback_delegate(IntPtr handle, int min, int max);
+        read_callback_delegate read_callback_native;
+
+        // overflow_callback
+        public Action OverflowCallback
+        {
+            get { return overflow_callback; }
+            set
+            {
+                overflow_callback = value;
+                overflow_callback_native = _ => overflow_callback();
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(overflow_callback_native);
+
+                Marshal.WriteIntPtr(handle, overflow_callback_offset, ptr);
+            }
+        }
+        static readonly int overflow_callback_offset = (int)Marshal.OffsetOf<SoundIoInStream>("overflow_callback");
+
+        Action overflow_callback;
+        delegate void overflow_callback_delegate(IntPtr handle);
+        overflow_callback_delegate overflow_callback_native;
+
+        // FIXME: this should be taken care in more centralized/decent manner... we don't want to write
+        // this kind of code anywhere we need string marshaling.
+        List<IntPtr> allocated_hglobals = new List<IntPtr>();
+
+        public string Name
+        {
+            get { return Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(handle, name_offset)); }
+            set
+            {
+                unsafe
+                {
+                    var existing = Marshal.ReadIntPtr(handle, name_offset);
+                    if (allocated_hglobals.Contains(existing))
+                    {
+                        allocated_hglobals.Remove(existing);
+                        Marshal.FreeHGlobal(existing);
+                    }
+
+                    var ptr = Marshal.StringToHGlobalAnsi(value);
+                    Marshal.WriteIntPtr(handle, name_offset, ptr);
+                    allocated_hglobals.Add(ptr);
+                }
+            }
+        }
+
+        static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoInStream>("name");
+
+        public bool NonTerminalHint
+        {
+            get { return Marshal.ReadInt32(handle, non_terminal_hint_offset) != 0; }
+        }
+
+        static readonly int non_terminal_hint_offset = (int)Marshal.OffsetOf<SoundIoInStream>("non_terminal_hint");
+
+        public int BytesPerFrame
+        {
+            get { return Marshal.ReadInt32(handle, bytes_per_frame_offset); }
+        }
+
+        static readonly int bytes_per_frame_offset = (int)Marshal.OffsetOf<SoundIoInStream>("bytes_per_frame");
+
+        public int BytesPerSample
+        {
+            get { return Marshal.ReadInt32(handle, bytes_per_sample_offset); }
+        }
+
+        static readonly int bytes_per_sample_offset = (int)Marshal.OffsetOf<SoundIoInStream>("bytes_per_sample");
+
+        public string LayoutErrorMessage
+        {
+            get 
+            {
+                var code = (SoundIoError)Marshal.ReadInt32(handle, layout_error_offset);
+
+                return code == SoundIoError.SoundIoErrorNone ? null : Marshal.PtrToStringAnsi(Natives.soundio_strerror((int)code));
+            }
+        }
+
+        static readonly int layout_error_offset = (int)Marshal.OffsetOf<SoundIoInStream>("layout_error");
+
+        // functions
+
+        public void Open()
+        {
+            var ret = (SoundIoError)Natives.soundio_instream_open(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void Start()
+        {
+            var ret = (SoundIoError)Natives.soundio_instream_start(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public SoundIOChannelAreas BeginRead(ref int frameCount)
+        {
+            IntPtr ptrs             = default;
+            int    nativeFrameCount = frameCount;
+
+            unsafe
+            {
+                var frameCountPtr = &nativeFrameCount;
+                var ptrptr        = &ptrs;
+                var ret           = (SoundIoError)Natives.soundio_instream_begin_read(handle, (IntPtr)ptrptr, (IntPtr)frameCountPtr);
+
+                frameCount = *frameCountPtr;
+
+                if (ret != SoundIoError.SoundIoErrorNone)
+                {
+                    throw new SoundIOException(ret);
+                }
+
+                return new SoundIOChannelAreas(ptrs, Layout.ChannelCount, frameCount);
+            }
+        }
+
+        public void EndRead()
+        {
+            var ret = (SoundIoError)Natives.soundio_instream_end_read(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void Pause(bool pause)
+        {
+            var ret = (SoundIoError)Natives.soundio_instream_pause(handle, pause);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public double GetLatency()
+        {
+            unsafe
+            {
+                double* dptr = null;
+                IntPtr  p    = new IntPtr(dptr);
+
+                var ret = (SoundIoError)Natives.soundio_instream_get_latency(handle, p);
+                if (ret != SoundIoError.SoundIoErrorNone)
+                {
+                    throw new SoundIOException(ret);
+                }
+
+                dptr = (double*)p;
+
+                return *dptr;
+            }
+        }
+    }
 }
 }

+ 324 - 247
Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs

@@ -4,251 +4,328 @@ using System.Runtime.InteropServices;
 
 
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIOOutStream : IDisposable
-	{
-		internal SoundIOOutStream (Pointer<SoundIoOutStream> handle)
-		{
-			this.handle = handle;
-		}
-
-		Pointer<SoundIoOutStream> handle;
-
-		public void Dispose ()
-		{
-			Natives.soundio_outstream_destroy (handle);
-		}
-		// Equality (based on handle)
-
-		public override bool Equals (object other)
-		{
-			var d = other as SoundIOOutStream;
-			return d != null && (this.handle == d.handle);
-		}
-
-		public override int GetHashCode ()
-		{
-			return (int)(IntPtr)handle;
-		}
-
-		public static bool operator == (SoundIOOutStream obj1, SoundIOOutStream obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 == null : obj1.Equals (obj2);
-		}
-
-		public static bool operator != (SoundIOOutStream obj1, SoundIOOutStream obj2)
-		{
-			return (object)obj1 == null ? (object)obj2 != null : !obj1.Equals (obj2);
-		}
-
-		// fields
-
-		public SoundIODevice Device {
-			get { return new SoundIODevice (Marshal.ReadIntPtr (handle, device_offset)); }
-		}
-		static readonly int device_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("device");
-
-		public SoundIOFormat Format {
-			get { return (SoundIOFormat) Marshal.ReadInt32 (handle, format_offset); }
-			set { Marshal.WriteInt32 (handle, format_offset, (int) value); }
-		}
-		static readonly int format_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("format");
-
-		public int SampleRate {
-			get { return Marshal.ReadInt32 (handle, sample_rate_offset); }
-			set { Marshal.WriteInt32 (handle, sample_rate_offset, value); }
-		}
-		static readonly int sample_rate_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("sample_rate");
-
-
-		public SoundIOChannelLayout Layout {
-			get { unsafe { return new SoundIOChannelLayout ((IntPtr) ((void*) ((IntPtr) handle + layout_offset))); } }
-			set {
-				unsafe {
-					Buffer.MemoryCopy ((void*)value.Handle, (void*)((IntPtr)handle + layout_offset),
-							   Marshal.SizeOf<SoundIoChannelLayout> (), Marshal.SizeOf<SoundIoChannelLayout> ());
-				}
-			}
-		}
-		static readonly int layout_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("layout");
-
-		public double SoftwareLatency {
-			get { return MarshalEx.ReadDouble (handle, software_latency_offset); }
-			set { MarshalEx.WriteDouble (handle, software_latency_offset, value); }
-		}
-		static readonly int software_latency_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("software_latency");
-
-		public float Volume {
-			get { return MarshalEx.ReadFloat (handle, volume_offset); }
-			set { MarshalEx.WriteFloat (handle, volume_offset, value); }
-		}
-		static readonly int volume_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("volume");
-
-		// error_callback
-		public Action ErrorCallback {
-			get { return error_callback; }
-			set {
-				error_callback = value;
-				if (value == null)
-					error_callback_native = null;
-				else
-					error_callback_native = stream => error_callback ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (error_callback_native);
-				Marshal.WriteIntPtr (handle, error_callback_offset, ptr);
-			}
-		}
-		static readonly int error_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("error_callback");
-		Action error_callback;
-		delegate void error_callback_delegate (IntPtr handle);
-		error_callback_delegate error_callback_native;
-
-		// write_callback
-		public Action<int, int> WriteCallback {
-			get { return write_callback; }
-			set {
-				write_callback = value;
-				if (value == null)
-					write_callback_native = null;
-				else
-					write_callback_native = (h, frame_count_min, frame_count_max) => write_callback (frame_count_min, frame_count_max);
-				var ptr = Marshal.GetFunctionPointerForDelegate (write_callback_native);
-				Marshal.WriteIntPtr (handle, write_callback_offset, ptr);
-			}
-		}
-		static readonly int write_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("write_callback");
-		Action<int, int> write_callback;
-		delegate void write_callback_delegate (IntPtr handle, int min, int max);
-		write_callback_delegate write_callback_native;
-
-		// underflow_callback
-		public Action UnderflowCallback {
-			get { return underflow_callback; }
-			set {
-				underflow_callback = value;
-				if (value == null)
-					underflow_callback_native = null;
-				else
-					underflow_callback_native = h => underflow_callback ();
-				var ptr = Marshal.GetFunctionPointerForDelegate (underflow_callback_native);
-				Marshal.WriteIntPtr (handle, underflow_callback_offset, ptr);
-			}
-		}
-		static readonly int underflow_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("underflow_callback");
-		Action underflow_callback;
-		delegate void underflow_callback_delegate (IntPtr handle);
-		underflow_callback_delegate underflow_callback_native;
-
-		// FIXME: this should be taken care in more centralized/decent manner... we don't want to write
-		// this kind of code anywhere we need string marshaling.
-		List<IntPtr> allocated_hglobals = new List<IntPtr> ();
-
-		public string Name {
-			get { return Marshal.PtrToStringAnsi (Marshal.ReadIntPtr (handle, name_offset)); }
-			set {
-				unsafe {
-					var existing = Marshal.ReadIntPtr (handle, name_offset);
-					if (allocated_hglobals.Contains (existing)) {
-						allocated_hglobals.Remove (existing);
-						Marshal.FreeHGlobal (existing);
-					}
-					var ptr = Marshal.StringToHGlobalAnsi (value);
-					Marshal.WriteIntPtr (handle, name_offset, ptr);
-					allocated_hglobals.Add (ptr);
-				}
-			}
-		}
-		static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("name");
-
-		public bool NonTerminalHint {
-			get { return Marshal.ReadInt32 (handle, non_terminal_hint_offset) != 0; }
-		}
-		static readonly int non_terminal_hint_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("non_terminal_hint");
-
-		public int BytesPerFrame {
-			get { return Marshal.ReadInt32 (handle, bytes_per_frame_offset); }
-		}
-		static readonly int bytes_per_frame_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("bytes_per_frame");
-
-		public int BytesPerSample {
-			get { return Marshal.ReadInt32 (handle, bytes_per_sample_offset); }
-		}
-		static readonly int bytes_per_sample_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("bytes_per_sample");
-
-		public string LayoutErrorMessage {
-			get {
-				var code = (SoundIoError) Marshal.ReadInt32 (handle, layout_error_offset);
-				return code == SoundIoError.SoundIoErrorNone ? null : Marshal.PtrToStringAnsi (Natives.soundio_strerror ((int) code));
-			}
-		}
-		static readonly int layout_error_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("layout_error");
-
-		// functions
-
-		public void Open ()
-		{
-			var ret = (SoundIoError) Natives.soundio_outstream_open (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void Start ()
-		{
-			var ret = (SoundIoError)Natives.soundio_outstream_start (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public SoundIOChannelAreas BeginWrite (ref int frameCount)
-		{
-			IntPtr ptrs = default (IntPtr);
-			int nativeFrameCount = frameCount;
-			unsafe {
-				var frameCountPtr = &nativeFrameCount;
-				var ptrptr = &ptrs;
-				var ret = (SoundIoError)Natives.soundio_outstream_begin_write (handle, (IntPtr) ptrptr, (IntPtr) frameCountPtr);
-				frameCount = *frameCountPtr;
-				if (ret != SoundIoError.SoundIoErrorNone)
-					throw new SoundIOException (ret);
-				return new SoundIOChannelAreas (ptrs, Layout.ChannelCount, frameCount);
-			}
-		}
-
-		public void EndWrite ()
-		{
-			var ret = (SoundIoError) Natives.soundio_outstream_end_write (handle);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public void ClearBuffer ()
-		{
-			Natives.soundio_outstream_clear_buffer (handle);
-		}
-
-		public void Pause (bool pause)
-		{
-			var ret = (SoundIoError) Natives.soundio_outstream_pause (handle, pause);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-
-		public double GetLatency ()
-		{
-			unsafe {
-				double* dptr = null;
-				IntPtr p = new IntPtr (dptr);
-				var ret = (SoundIoError) Natives.soundio_outstream_get_latency (handle, p);
-				if (ret != SoundIoError.SoundIoErrorNone)
-					throw new SoundIOException (ret);
-				dptr = (double*) p;
-				return *dptr;
-			}
-		}
-
-		public void SetVolume (double volume)
-		{
-			var ret = (SoundIoError) Natives.soundio_outstream_set_volume (handle, volume);
-			if (ret != SoundIoError.SoundIoErrorNone)
-				throw new SoundIOException (ret);
-		}
-	}
+    public class SoundIOOutStream : IDisposable
+    {
+        internal SoundIOOutStream (Pointer<SoundIoOutStream> handle)
+        {
+            this.handle = handle;
+        }
+
+        Pointer<SoundIoOutStream> handle;
+
+        public void Dispose ()
+        {
+            Natives.soundio_outstream_destroy (handle);
+        }
+        // Equality (based on handle)
+
+        public override bool Equals (object other)
+        {
+            var d = other as SoundIOOutStream;
+
+            return d != null && (this.handle == d.handle);
+        }
+
+        public override int GetHashCode ()
+        {
+            return (int)(IntPtr)handle;
+        }
+
+        public static bool operator == (SoundIOOutStream obj1, SoundIOOutStream obj2)
+        {
+            return obj1 is null ? obj2 is null : obj1.Equals(obj2);
+        }
+
+        public static bool operator != (SoundIOOutStream obj1, SoundIOOutStream obj2)
+        {
+            return obj1 is null ? obj2 is object : !obj1.Equals(obj2);
+        }
+
+        // fields
+
+        public SoundIODevice Device
+        {
+            get { return new SoundIODevice(Marshal.ReadIntPtr(handle, device_offset)); }
+        }
+
+        static readonly int device_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("device");
+
+        public SoundIOFormat Format
+        {
+            get { return (SoundIOFormat) Marshal.ReadInt32(handle, format_offset); }
+            set { Marshal.WriteInt32(handle, format_offset, (int) value); }
+        }
+
+        static readonly int format_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("format");
+
+        public int SampleRate
+        {
+            get { return Marshal.ReadInt32(handle, sample_rate_offset); }
+            set { Marshal.WriteInt32(handle, sample_rate_offset, value); }
+        }
+
+        static readonly int sample_rate_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("sample_rate");
+
+        public SoundIOChannelLayout Layout
+        {
+            get { unsafe { return new SoundIOChannelLayout((IntPtr) (void*)((IntPtr)handle + layout_offset)); } }
+            set
+            {
+                unsafe
+                {
+                    Buffer.MemoryCopy((void*)value.Handle, (void*)((IntPtr)handle + layout_offset), Marshal.SizeOf<SoundIoChannelLayout>(), Marshal.SizeOf<SoundIoChannelLayout>());
+                }
+            }
+        }
+        static readonly int layout_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("layout");
+
+        public double SoftwareLatency
+        {
+            get { return MarshalEx.ReadDouble (handle, software_latency_offset); }
+            set { MarshalEx.WriteDouble (handle, software_latency_offset, value); }
+        }
+
+        static readonly int software_latency_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("software_latency");
+
+        public float Volume
+        {
+            get { return MarshalEx.ReadFloat(handle, volume_offset); }
+            set { MarshalEx.WriteFloat(handle, volume_offset, value); }
+        }
+
+        static readonly int volume_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("volume");
+
+        // error_callback
+        public Action ErrorCallback
+        {
+            get { return error_callback; }
+            set
+            {
+                error_callback = value;
+                if (value == null)
+                {
+                    error_callback_native = null;
+                }
+                else
+                {
+                    error_callback_native = stream => error_callback();
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate(error_callback_native);
+                Marshal.WriteIntPtr(handle, error_callback_offset, ptr);
+            }
+        }
+
+        static readonly int error_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("error_callback");
+
+        Action error_callback;
+        delegate void error_callback_delegate (IntPtr handle);
+        error_callback_delegate error_callback_native;
+
+        // write_callback
+        public Action<int, int> WriteCallback
+        {
+            get { return write_callback; }
+            set
+            {
+                write_callback = value;
+                if (value == null)
+                {
+                    write_callback_native = null;
+                }
+                else
+                {
+                    write_callback_native = (h, frame_count_min, frame_count_max) => write_callback(frame_count_min, frame_count_max);
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate (write_callback_native);
+                Marshal.WriteIntPtr (handle, write_callback_offset, ptr);
+            }
+        }
+
+        static readonly int write_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("write_callback");
+
+        Action<int, int> write_callback;
+        delegate void write_callback_delegate(IntPtr handle, int min, int max);
+        write_callback_delegate write_callback_native;
+
+        // underflow_callback
+        public Action UnderflowCallback
+        {
+            get { return underflow_callback; }
+            set
+            {
+                underflow_callback = value;
+                if (value == null)
+                {
+                    underflow_callback_native = null;
+                }
+                else
+                {
+                    underflow_callback_native = h => underflow_callback();
+                }
+
+                var ptr = Marshal.GetFunctionPointerForDelegate (underflow_callback_native);
+                Marshal.WriteIntPtr (handle, underflow_callback_offset, ptr);
+            }
+        }
+
+        static readonly int underflow_callback_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("underflow_callback");
+        
+        Action underflow_callback;
+        delegate void underflow_callback_delegate(IntPtr handle);
+        underflow_callback_delegate underflow_callback_native;
+
+        // FIXME: this should be taken care in more centralized/decent manner... we don't want to write
+        // this kind of code anywhere we need string marshaling.
+        List<IntPtr> allocated_hglobals = new List<IntPtr>();
+
+        public string Name {
+            get { return Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(handle, name_offset)); }
+            set
+            {
+                unsafe
+                {
+                    var existing = Marshal.ReadIntPtr(handle, name_offset);
+                    if (allocated_hglobals.Contains(existing))
+                    {
+                        allocated_hglobals.Remove(existing);
+                        Marshal.FreeHGlobal(existing);
+                    }
+
+                    var ptr = Marshal.StringToHGlobalAnsi(value);
+                    Marshal.WriteIntPtr(handle, name_offset, ptr);
+                    allocated_hglobals.Add(ptr);
+                }
+            }
+        }
+
+        static readonly int name_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("name");
+
+        public bool NonTerminalHint
+        {
+            get { return Marshal.ReadInt32(handle, non_terminal_hint_offset) != 0; }
+        }
+
+        static readonly int non_terminal_hint_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("non_terminal_hint");
+
+        public int BytesPerFrame
+        {
+            get { return Marshal.ReadInt32(handle, bytes_per_frame_offset); }
+        }
+
+        static readonly int bytes_per_frame_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("bytes_per_frame");
+
+        public int BytesPerSample
+        {
+            get { return Marshal.ReadInt32(handle, bytes_per_sample_offset); }
+        }
+
+        static readonly int bytes_per_sample_offset = (int)Marshal.OffsetOf<SoundIoOutStream>("bytes_per_sample");
+
+        public string LayoutErrorMessage
+        {
+            get
+            {
+                var code = (SoundIoError)Marshal.ReadInt32(handle, layout_error_offset);
+
+                return code == SoundIoError.SoundIoErrorNone ? null : Marshal.PtrToStringAnsi(Natives.soundio_strerror((int)code));
+            }
+        }
+
+        static readonly int layout_error_offset = (int)Marshal.OffsetOf<SoundIoOutStream> ("layout_error");
+
+        // functions
+
+        public void Open ()
+        {
+            var ret = (SoundIoError)Natives.soundio_outstream_open(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void Start ()
+        {
+            var ret = (SoundIoError)Natives.soundio_outstream_start(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public SoundIOChannelAreas BeginWrite(ref int frameCount)
+        {
+            IntPtr ptrs             = default;
+            int    nativeFrameCount = frameCount;
+
+            unsafe
+            {
+                var frameCountPtr = &nativeFrameCount;
+                var ptrptr        = &ptrs;
+                var ret           = (SoundIoError)Natives.soundio_outstream_begin_write(handle, (IntPtr)ptrptr, (IntPtr)frameCountPtr);
+
+                frameCount = *frameCountPtr;
+
+                if (ret != SoundIoError.SoundIoErrorNone)
+                {
+                    throw new SoundIOException(ret);
+                }
+
+                return new SoundIOChannelAreas(ptrs, Layout.ChannelCount, frameCount);
+            }
+        }
+
+        public void EndWrite ()
+        {
+            var ret = (SoundIoError)Natives.soundio_outstream_end_write(handle);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public void ClearBuffer ()
+        {
+            _ = Natives.soundio_outstream_clear_buffer(handle);
+        }
+
+        public void Pause (bool pause)
+        {
+            var ret = (SoundIoError)Natives.soundio_outstream_pause(handle, pause);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+
+        public double GetLatency ()
+        {
+            unsafe
+            {
+                double* dptr = null;
+                IntPtr  p    = new IntPtr(dptr);
+
+                var ret = (SoundIoError)Natives.soundio_outstream_get_latency(handle, p);
+                if (ret != SoundIoError.SoundIoErrorNone)
+                {
+                    throw new SoundIOException(ret);
+                }
+
+                dptr = (double*)p;
+
+                return *dptr;
+            }
+        }
+
+        public void SetVolume (double volume)
+        {
+            var ret = (SoundIoError)Natives.soundio_outstream_set_volume(handle, volume);
+            if (ret != SoundIoError.SoundIoErrorNone)
+            {
+                throw new SoundIOException(ret);
+            }
+        }
+    }
 }
 }

+ 55 - 58
Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs

@@ -1,61 +1,58 @@
 using System;
 using System;
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public class SoundIORingBuffer : IDisposable
-	{
-		internal SoundIORingBuffer (IntPtr handle)
-		{
-			this.handle = handle;
-		}
-
-		IntPtr handle;
-
-		public int Capacity {
-			get { return Natives.soundio_ring_buffer_capacity (handle); }
-		}
-
-		public void Clear ()
-		{
-			Natives.soundio_ring_buffer_clear (handle);
-		}
-
-		public void Dispose ()
-		{
-			Natives.soundio_ring_buffer_destroy (handle);
-		}
-
-		public int FillCount {
-			get {
-				return Natives.soundio_ring_buffer_fill_count (handle);
-			}
-		}
-
-		public int FreeCount {
-			get {
-				return Natives.soundio_ring_buffer_free_count (handle);
-			}
-		}
-
-		public IntPtr ReadPointer {
-			get {
-				return Natives.soundio_ring_buffer_read_ptr (handle);
-			}
-		}
-
-		public IntPtr WritePointer {
-			get {
-				return Natives.soundio_ring_buffer_write_ptr (handle);
-			}
-		}
-
-		public void AdvanceReadPointer (int count)
-		{
-			Natives.soundio_ring_buffer_advance_read_ptr (handle, count);
-		}
-
-		public void AdvanceWritePointer (int count)
-		{
-			Natives.soundio_ring_buffer_advance_write_ptr (handle, count);
-		}
-	}
-}
+    public class SoundIORingBuffer : IDisposable
+    {
+        internal SoundIORingBuffer(IntPtr handle)
+        {
+            this.handle = handle;
+        }
+
+        IntPtr handle;
+
+        public int Capacity
+        {
+            get { return Natives.soundio_ring_buffer_capacity(handle); }
+        }
+
+        public void Clear()
+        {
+            Natives.soundio_ring_buffer_clear(handle);
+        }
+
+        public void Dispose()
+        {
+            Natives.soundio_ring_buffer_destroy(handle);
+        }
+
+        public int FillCount
+        {
+            get { return Natives.soundio_ring_buffer_fill_count(handle); }
+        }
+
+        public int FreeCount
+        {
+            get { return Natives.soundio_ring_buffer_free_count(handle); }
+        }
+
+        public IntPtr ReadPointer
+        {
+            get { return Natives.soundio_ring_buffer_read_ptr(handle); }
+        }
+
+        public IntPtr WritePointer
+        {
+            get { return Natives.soundio_ring_buffer_write_ptr(handle); }
+        }
+
+        public void AdvanceReadPointer(int count)
+        {
+            Natives.soundio_ring_buffer_advance_read_ptr(handle, count);
+        }
+
+        public void AdvanceWritePointer(int count)
+        {
+            Natives.soundio_ring_buffer_advance_write_ptr(handle, count);
+        }
+    }
+}

+ 10 - 10
Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs

@@ -1,15 +1,15 @@
 using System;
 using System;
 namespace SoundIOSharp
 namespace SoundIOSharp
 {
 {
-	public struct SoundIOSampleRateRange
-	{
-		internal SoundIOSampleRateRange (int min, int max)
-		{
-			Min = min;
-			Max = max;
-		}
+    public struct SoundIOSampleRateRange
+    {
+        internal SoundIOSampleRateRange(int min, int max)
+        {
+            Min = min;
+            Max = max;
+        }
 
 
-		public readonly int Min;
-		public readonly int Max;
-	}
+        public readonly int Min;
+        public readonly int Max;
+    }
 }
 }

+ 1 - 1
Ryujinx.Audio/Renderers/OpenAL/OpenALAudioOut.cs

@@ -367,7 +367,7 @@ namespace Ryujinx.Audio
             {
             {
                 lock (track)
                 lock (track)
                 {
                 {
-                    return track.Volume;
+                    return track.GetVolume();
                 }
                 }
             }
             }
 
 

+ 7 - 3
Ryujinx.Audio/Renderers/OpenAL/OpenALAudioTrack.cs

@@ -11,7 +11,6 @@ namespace Ryujinx.Audio
         public int           SampleRate { get; private set; }
         public int           SampleRate { get; private set; }
         public ALFormat      Format     { get; private set; }
         public ALFormat      Format     { get; private set; }
         public PlaybackState State      { get; set; }
         public PlaybackState State      { get; set; }
-        public float         Volume     { get; private set; }
 
 
         public int HardwareChannels { get; }
         public int HardwareChannels { get; }
         public int VirtualChannels { get; }
         public int VirtualChannels { get; }
@@ -151,9 +150,14 @@ namespace Ryujinx.Audio
 
 
         public void SetVolume(float volume)
         public void SetVolume(float volume)
         {
         {
-            Volume = volume;
+            AL.Source(SourceId, ALSourcef.Gain, volume);
+        }
+
+        public float GetVolume()
+        {
+            AL.GetSource(SourceId, ALSourcef.Gain, out float volume);
 
 
-            AL.Source(SourceId, ALSourcef.Gain, Volume);
+            return volume;
         }
         }
 
 
         public void Dispose()
         public void Dispose()

+ 0 - 1
Ryujinx.Audio/Renderers/SoundIo/SoundIoAudioOut.cs

@@ -1,6 +1,5 @@
 using Ryujinx.Audio.SoundIo;
 using Ryujinx.Audio.SoundIo;
 using SoundIOSharp;
 using SoundIOSharp;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
 namespace Ryujinx.Audio
 namespace Ryujinx.Audio

+ 4 - 6
Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs

@@ -85,16 +85,16 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager
         {
         {
             long tag = context.RequestData.ReadInt64();
             long tag = context.RequestData.ReadInt64();
 
 
-            context.ResponseData.Write(_audioOut.ContainsBuffer(_track, tag) ? 1 : 0);
+            context.ResponseData.Write(_audioOut.ContainsBuffer(_track, tag));
 
 
-            return 0;
+            return ResultCode.Success;
         }
         }
 
 
         [Command(7)] // 3.0.0+
         [Command(7)] // 3.0.0+
         // AppendAudioOutBufferAuto(u64 tag, buffer<nn::audio::AudioOutBuffer, 0x21>)
         // AppendAudioOutBufferAuto(u64 tag, buffer<nn::audio::AudioOutBuffer, 0x21>)
         public ResultCode AppendAudioOutBufferAuto(ServiceCtx context)
         public ResultCode AppendAudioOutBufferAuto(ServiceCtx context)
         {
         {
-            (long position, long size) = context.Request.GetBufferType0x21();
+            (long position, _) = context.Request.GetBufferType0x21();
 
 
             return AppendAudioOutBufferImpl(context, position);
             return AppendAudioOutBufferImpl(context, position);
         }
         }
@@ -103,9 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager
         {
         {
             long tag = context.RequestData.ReadInt64();
             long tag = context.RequestData.ReadInt64();
 
 
-            AudioOutData data = MemoryHelper.Read<AudioOutData>(
-                context.Memory,
-                position);
+            AudioOutData data = MemoryHelper.Read<AudioOutData>(context.Memory, position);
 
 
             // NOTE: Assume PCM16 all the time, change if new format are found.
             // NOTE: Assume PCM16 all the time, change if new format are found.
             short[] buffer = new short[data.SampleBufferSize / sizeof(short)];
             short[] buffer = new short[data.SampleBufferSize / sizeof(short)];

+ 5 - 20
Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs

@@ -20,10 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
         // ListAudioOuts() -> (u32 count, buffer<bytes, 6>)
         // ListAudioOuts() -> (u32 count, buffer<bytes, 6>)
         public ResultCode ListAudioOuts(ServiceCtx context)
         public ResultCode ListAudioOuts(ServiceCtx context)
         {
         {
-            return ListAudioOutsImpl(
-                context,
-                context.Request.ReceiveBuff[0].Position,
-                context.Request.ReceiveBuff[0].Size);
+            return ListAudioOutsImpl(context, context.Request.ReceiveBuff[0].Position, context.Request.ReceiveBuff[0].Size);
         }
         }
 
 
         [Command(1)]
         [Command(1)]
@@ -31,12 +28,8 @@ namespace Ryujinx.HLE.HOS.Services.Audio
         // -> (u32 sample_rate, u32 channel_count, u32 pcm_format, u32, object<nn::audio::detail::IAudioOut>, buffer<bytes, 6> name_out)
         // -> (u32 sample_rate, u32 channel_count, u32 pcm_format, u32, object<nn::audio::detail::IAudioOut>, buffer<bytes, 6> name_out)
         public ResultCode OpenAudioOut(ServiceCtx context)
         public ResultCode OpenAudioOut(ServiceCtx context)
         {
         {
-            return OpenAudioOutImpl(
-                context,
-                context.Request.SendBuff[0].Position,
-                context.Request.SendBuff[0].Size,
-                context.Request.ReceiveBuff[0].Position,
-                context.Request.ReceiveBuff[0].Size);
+            return OpenAudioOutImpl(context, context.Request.SendBuff[0].Position,    context.Request.SendBuff[0].Size,
+                                             context.Request.ReceiveBuff[0].Position, context.Request.ReceiveBuff[0].Size);
         }
         }
 
 
         [Command(2)] // 3.0.0+
         [Command(2)] // 3.0.0+
@@ -56,12 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
             (long sendPosition, long sendSize) = context.Request.GetBufferType0x21();
             (long sendPosition, long sendSize) = context.Request.GetBufferType0x21();
             (long recvPosition, long recvSize) = context.Request.GetBufferType0x22();
             (long recvPosition, long recvSize) = context.Request.GetBufferType0x22();
 
 
-            return OpenAudioOutImpl(
-                context,
-                sendPosition,
-                sendSize,
-                recvPosition,
-                recvSize);
+            return OpenAudioOutImpl(context, sendPosition, sendSize, recvPosition, recvSize);
         }
         }
 
 
         private ResultCode ListAudioOutsImpl(ServiceCtx context, long position, long size)
         private ResultCode ListAudioOutsImpl(ServiceCtx context, long position, long size)
@@ -88,10 +76,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
 
 
         private ResultCode OpenAudioOutImpl(ServiceCtx context, long sendPosition, long sendSize, long receivePosition, long receiveSize)
         private ResultCode OpenAudioOutImpl(ServiceCtx context, long sendPosition, long sendSize, long receivePosition, long receiveSize)
         {
         {
-            string deviceName = MemoryHelper.ReadAsciiString(
-                context.Memory,
-                sendPosition,
-                sendSize);
+            string deviceName = MemoryHelper.ReadAsciiString(context.Memory, sendPosition, sendSize);
 
 
             if (deviceName == string.Empty)
             if (deviceName == string.Empty)
             {
             {