aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio/Native
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Audio/Native')
-rw-r--r--Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs23
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIO.cs311
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs15
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs26
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs33
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs77
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs99
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs215
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs9
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOException.cs13
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs26
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs228
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs241
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs61
-rw-r--r--Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs15
-rw-r--r--Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dllbin0 -> 370899 bytes
-rw-r--r--Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dylibbin0 -> 106760 bytes
-rw-r--r--Ryujinx.Audio/Native/libsoundio/libs/libsoundio.sobin0 -> 265888 bytes
-rw-r--r--Ryujinx.Audio/Native/libsoundio/libsoundio-interop.cs638
19 files changed, 2030 insertions, 0 deletions
diff --git a/Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs b/Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs
new file mode 100644
index 00000000..ec3eef37
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/MarshalExtensions.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SoundIOSharp
+{
+ public static class MarshalEx
+ {
+ public static double ReadDouble (IntPtr handle, int offset = 0)
+ {
+ return BitConverter.Int64BitsToDouble (Marshal.ReadInt64 (handle, offset));
+ }
+
+ public static void WriteDouble (IntPtr handle, double value)
+ {
+ WriteDouble (handle, 0, value);
+ }
+
+ public static void WriteDouble (IntPtr handle, int offset, double value)
+ {
+ Marshal.WriteInt64 (handle, offset, BitConverter.DoubleToInt64Bits (value));
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIO.cs b/Ryujinx.Audio/Native/libsoundio/SoundIO.cs
new file mode 100644
index 00000000..e9ab9e6e
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIO.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+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));
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs
new file mode 100644
index 00000000..dfcb0a3f
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOBackend.cs
@@ -0,0 +1,15 @@
+using System;
+namespace SoundIOSharp
+{
+ public enum SoundIOBackend
+ {
+ None = 0,
+ Jack = 1,
+ PulseAudio = 2,
+ Alsa = 3,
+ CoreAudio = 4,
+ Wasapi = 5,
+ Dummy = 6,
+ }
+
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs
new file mode 100644
index 00000000..f30e2bbb
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelArea.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SoundIOSharp
+{
+ public struct SoundIOChannelArea
+ {
+ internal SoundIOChannelArea (Pointer<SoundIoChannelArea> handle)
+ {
+ this.handle = 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 int Step {
+ get { return Marshal.ReadInt32 (handle, step_offset); }
+ }
+ static readonly int step_offset = (int)Marshal.OffsetOf<SoundIoChannelArea> ("step");
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs
new file mode 100644
index 00000000..776d657a
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelAreas.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SoundIOSharp
+{
+ 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;
+ }
+
+ IntPtr head;
+ int channel_count;
+ int frame_count;
+
+ public bool IsEmpty {
+ get { return head == IntPtr.Zero; }
+ }
+
+ public SoundIOChannelArea GetArea (int channel)
+ {
+ return new SoundIOChannelArea (head + native_size * channel);
+ }
+
+ public int ChannelCount => channel_count;
+ public int FrameCount => frame_count;
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs
new file mode 100644
index 00000000..d24508a1
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelId.cs
@@ -0,0 +1,77 @@
+using System;
+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,
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs
new file mode 100644
index 00000000..ee634542
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOChannelLayout.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+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);
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs b/Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs
new file mode 100644
index 00000000..81b78b67
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIODevice.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+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 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));
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs b/Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs
new file mode 100644
index 00000000..9cd45f36
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIODeviceAim.cs
@@ -0,0 +1,9 @@
+using System;
+namespace SoundIOSharp
+{
+ public enum SoundIODeviceAim // soundio.h (228, 6)
+ {
+ Input = 0,
+ Output = 1,
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOException.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOException.cs
new file mode 100644
index 00000000..ff6a0337
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOException.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SoundIOSharp
+{
+ public class SoundIOException : Exception
+ {
+ internal SoundIOException (SoundIoError errorCode)
+ : base (Marshal.PtrToStringAnsi (Natives.soundio_strerror ((int) errorCode)))
+ {
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs
new file mode 100644
index 00000000..59434e1e
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOFormat.cs
@@ -0,0 +1,26 @@
+using System;
+namespace SoundIOSharp
+{
+ 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,
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs
new file mode 100644
index 00000000..fb0b3104
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOInStream.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+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;
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs
new file mode 100644
index 00000000..0b77e1af
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOOutStream.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+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*)((IntPtr)handle + layout_offset), (void*)value.Handle,
+ 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");
+
+ // 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;
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs b/Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs
new file mode 100644
index 00000000..63d796fd
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIORingBuffer.cs
@@ -0,0 +1,61 @@
+using System;
+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);
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs b/Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs
new file mode 100644
index 00000000..28fee458
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/SoundIOSampleRateRange.cs
@@ -0,0 +1,15 @@
+using System;
+namespace SoundIOSharp
+{
+ public struct SoundIOSampleRateRange
+ {
+ internal SoundIOSampleRateRange (int min, int max)
+ {
+ Min = min;
+ Max = max;
+ }
+
+ public readonly int Min;
+ public readonly int Max;
+ }
+}
diff --git a/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dll b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dll
new file mode 100644
index 00000000..53a83f0f
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dll
Binary files differ
diff --git a/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dylib b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dylib
new file mode 100644
index 00000000..f6acabed
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.dylib
Binary files differ
diff --git a/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.so b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.so
new file mode 100644
index 00000000..2b9cf1b3
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/libs/libsoundio.so
Binary files differ
diff --git a/Ryujinx.Audio/Native/libsoundio/libsoundio-interop.cs b/Ryujinx.Audio/Native/libsoundio/libsoundio-interop.cs
new file mode 100644
index 00000000..6eb09370
--- /dev/null
+++ b/Ryujinx.Audio/Native/libsoundio/libsoundio-interop.cs
@@ -0,0 +1,638 @@
+// This source file is generated by nclang PInvokeGenerator.
+using System;
+using System.Runtime.InteropServices;
+using delegate0 = SoundIOSharp.Delegates.delegate0;
+using delegate1 = SoundIOSharp.Delegates.delegate1;
+using delegate2 = SoundIOSharp.Delegates.delegate2;
+using delegate3 = SoundIOSharp.Delegates.delegate3;
+using delegate4 = SoundIOSharp.Delegates.delegate4;
+using delegate5 = SoundIOSharp.Delegates.delegate5;
+using delegate6 = SoundIOSharp.Delegates.delegate6;
+using delegate7 = SoundIOSharp.Delegates.delegate7;
+using delegate8 = SoundIOSharp.Delegates.delegate8;
+using delegate9 = SoundIOSharp.Delegates.delegate9;
+
+namespace SoundIOSharp
+{
+ enum SoundIoError // soundio.h (72, 6)
+ {
+ SoundIoErrorNone = 0,
+ SoundIoErrorNoMem = 1,
+ SoundIoErrorInitAudioBackend = 2,
+ SoundIoErrorSystemResources = 3,
+ SoundIoErrorOpeningDevice = 4,
+ SoundIoErrorNoSuchDevice = 5,
+ SoundIoErrorInvalid = 6,
+ SoundIoErrorBackendUnavailable = 7,
+ SoundIoErrorStreaming = 8,
+ SoundIoErrorIncompatibleDevice = 9,
+ SoundIoErrorNoSuchClient = 10,
+ SoundIoErrorIncompatibleBackend = 11,
+ SoundIoErrorBackendDisconnected = 12,
+ SoundIoErrorInterrupted = 13,
+ SoundIoErrorUnderflow = 14,
+ SoundIoErrorEncodingString = 15,
+ }
+
+ enum SoundIoChannelId // soundio.h (106, 6)
+ {
+ SoundIoChannelIdInvalid = 0,
+ SoundIoChannelIdFrontLeft = 1,
+ SoundIoChannelIdFrontRight = 2,
+ SoundIoChannelIdFrontCenter = 3,
+ SoundIoChannelIdLfe = 4,
+ SoundIoChannelIdBackLeft = 5,
+ SoundIoChannelIdBackRight = 6,
+ SoundIoChannelIdFrontLeftCenter = 7,
+ SoundIoChannelIdFrontRightCenter = 8,
+ SoundIoChannelIdBackCenter = 9,
+ SoundIoChannelIdSideLeft = 10,
+ SoundIoChannelIdSideRight = 11,
+ SoundIoChannelIdTopCenter = 12,
+ SoundIoChannelIdTopFrontLeft = 13,
+ SoundIoChannelIdTopFrontCenter = 14,
+ SoundIoChannelIdTopFrontRight = 15,
+ SoundIoChannelIdTopBackLeft = 16,
+ SoundIoChannelIdTopBackCenter = 17,
+ SoundIoChannelIdTopBackRight = 18,
+ SoundIoChannelIdBackLeftCenter = 19,
+ SoundIoChannelIdBackRightCenter = 20,
+ SoundIoChannelIdFrontLeftWide = 21,
+ SoundIoChannelIdFrontRightWide = 22,
+ SoundIoChannelIdFrontLeftHigh = 23,
+ SoundIoChannelIdFrontCenterHigh = 24,
+ SoundIoChannelIdFrontRightHigh = 25,
+ SoundIoChannelIdTopFrontLeftCenter = 26,
+ SoundIoChannelIdTopFrontRightCenter = 27,
+ SoundIoChannelIdTopSideLeft = 28,
+ SoundIoChannelIdTopSideRight = 29,
+ SoundIoChannelIdLeftLfe = 30,
+ SoundIoChannelIdRightLfe = 31,
+ SoundIoChannelIdLfe2 = 32,
+ SoundIoChannelIdBottomCenter = 33,
+ SoundIoChannelIdBottomLeftCenter = 34,
+ SoundIoChannelIdBottomRightCenter = 35,
+ SoundIoChannelIdMsMid = 36,
+ SoundIoChannelIdMsSide = 37,
+ SoundIoChannelIdAmbisonicW = 38,
+ SoundIoChannelIdAmbisonicX = 39,
+ SoundIoChannelIdAmbisonicY = 40,
+ SoundIoChannelIdAmbisonicZ = 41,
+ SoundIoChannelIdXyX = 42,
+ SoundIoChannelIdXyY = 43,
+ SoundIoChannelIdHeadphonesLeft = 44,
+ SoundIoChannelIdHeadphonesRight = 45,
+ SoundIoChannelIdClickTrack = 46,
+ SoundIoChannelIdForeignLanguage = 47,
+ SoundIoChannelIdHearingImpaired = 48,
+ SoundIoChannelIdNarration = 49,
+ SoundIoChannelIdHaptic = 50,
+ SoundIoChannelIdDialogCentricMix = 51,
+ SoundIoChannelIdAux = 52,
+ SoundIoChannelIdAux0 = 53,
+ SoundIoChannelIdAux1 = 54,
+ SoundIoChannelIdAux2 = 55,
+ SoundIoChannelIdAux3 = 56,
+ SoundIoChannelIdAux4 = 57,
+ SoundIoChannelIdAux5 = 58,
+ SoundIoChannelIdAux6 = 59,
+ SoundIoChannelIdAux7 = 60,
+ SoundIoChannelIdAux8 = 61,
+ SoundIoChannelIdAux9 = 62,
+ SoundIoChannelIdAux10 = 63,
+ SoundIoChannelIdAux11 = 64,
+ SoundIoChannelIdAux12 = 65,
+ SoundIoChannelIdAux13 = 66,
+ SoundIoChannelIdAux14 = 67,
+ SoundIoChannelIdAux15 = 68,
+ }
+
+ enum SoundIoChannelLayoutId // soundio.h (189, 6)
+ {
+ SoundIoChannelLayoutIdMono = 0,
+ SoundIoChannelLayoutIdStereo = 1,
+ SoundIoChannelLayoutId2Point1 = 2,
+ SoundIoChannelLayoutId3Point0 = 3,
+ SoundIoChannelLayoutId3Point0Back = 4,
+ SoundIoChannelLayoutId3Point1 = 5,
+ SoundIoChannelLayoutId4Point0 = 6,
+ SoundIoChannelLayoutIdQuad = 7,
+ SoundIoChannelLayoutIdQuadSide = 8,
+ SoundIoChannelLayoutId4Point1 = 9,
+ SoundIoChannelLayoutId5Point0Back = 10,
+ SoundIoChannelLayoutId5Point0Side = 11,
+ SoundIoChannelLayoutId5Point1 = 12,
+ SoundIoChannelLayoutId5Point1Back = 13,
+ SoundIoChannelLayoutId6Point0Side = 14,
+ SoundIoChannelLayoutId6Point0Front = 15,
+ SoundIoChannelLayoutIdHexagonal = 16,
+ SoundIoChannelLayoutId6Point1 = 17,
+ SoundIoChannelLayoutId6Point1Back = 18,
+ SoundIoChannelLayoutId6Point1Front = 19,
+ SoundIoChannelLayoutId7Point0 = 20,
+ SoundIoChannelLayoutId7Point0Front = 21,
+ SoundIoChannelLayoutId7Point1 = 22,
+ SoundIoChannelLayoutId7Point1Wide = 23,
+ SoundIoChannelLayoutId7Point1WideBack = 24,
+ SoundIoChannelLayoutIdOctagonal = 25,
+ }
+
+ enum SoundIoBackend // soundio.h (218, 6)
+ {
+ SoundIoBackendNone = 0,
+ SoundIoBackendJack = 1,
+ SoundIoBackendPulseAudio = 2,
+ SoundIoBackendAlsa = 3,
+ SoundIoBackendCoreAudio = 4,
+ SoundIoBackendWasapi = 5,
+ SoundIoBackendDummy = 6,
+ }
+
+ enum SoundIoDeviceAim // soundio.h (228, 6)
+ {
+ SoundIoDeviceAimInput = 0,
+ SoundIoDeviceAimOutput = 1,
+ }
+
+ enum SoundIoFormat // soundio.h (235, 6)
+ {
+ SoundIoFormatInvalid = 0,
+ SoundIoFormatS8 = 1,
+ SoundIoFormatU8 = 2,
+ SoundIoFormatS16LE = 3,
+ SoundIoFormatS16BE = 4,
+ SoundIoFormatU16LE = 5,
+ SoundIoFormatU16BE = 6,
+ SoundIoFormatS24LE = 7,
+ SoundIoFormatS24BE = 8,
+ SoundIoFormatU24LE = 9,
+ SoundIoFormatU24BE = 10,
+ SoundIoFormatS32LE = 11,
+ SoundIoFormatS32BE = 12,
+ SoundIoFormatU32LE = 13,
+ SoundIoFormatU32BE = 14,
+ SoundIoFormatFloat32LE = 15,
+ SoundIoFormatFloat32BE = 16,
+ SoundIoFormatFloat64LE = 17,
+ SoundIoFormatFloat64BE = 18,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoChannelLayout // soundio.h (302, 8)
+ {
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @name;
+ public int @channel_count;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
+ [CTypeDetails("ConstArrayOf<SoundIoChannelId>")] public SoundIoChannelId[] @channels;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoSampleRateRange // soundio.h (309, 8)
+ {
+ public int @min;
+ public int @max;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoChannelArea // soundio.h (315, 8)
+ {
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @ptr;
+ public int @step;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIo // soundio.h (324, 8)
+ {
+ [CTypeDetails("Pointer<void>")] public System.IntPtr @userdata;
+ [CTypeDetails("Pointer<void (SoundIo *)>")] public delegate0 @on_devices_change;
+ [CTypeDetails("Pointer<void (SoundIo *, int)>")] public delegate1 @on_backend_disconnect;
+ [CTypeDetails("Pointer<void (SoundIo *)>")] public Delegates.delegate0 @on_events_signal;
+ public SoundIoBackend @current_backend;
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @app_name;
+ [CTypeDetails("Pointer<void ()>")] public delegate2 @emit_rtprio_warning;
+ [CTypeDetails("Pointer<void (const char *)>")] public delegate3 @jack_info_callback;
+ [CTypeDetails("Pointer<void (const char *)>")] public Delegates.delegate3 @jack_error_callback;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoDevice // soundio.h (383, 8)
+ {
+ [CTypeDetails("Pointer<SoundIo>")] public System.IntPtr @soundio;
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @id;
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @name;
+ public SoundIoDeviceAim @aim;
+ [CTypeDetails("Pointer<SoundIoChannelLayout>")] public System.IntPtr @layouts;
+ public int @layout_count;
+ public SoundIoChannelLayout @current_layout;
+ [CTypeDetails("Pointer<SoundIoFormat>")] public System.IntPtr @formats;
+ public int @format_count;
+ public SoundIoFormat @current_format;
+ [CTypeDetails("Pointer<SoundIoSampleRateRange>")] public System.IntPtr @sample_rates;
+ public int @sample_rate_count;
+ public int @sample_rate_current;
+ public double @software_latency_min;
+ public double @software_latency_max;
+ public double @software_latency_current;
+ public bool @is_raw;
+ public int @ref_count;
+ public int @probe_error;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoOutStream // soundio.h (493, 8)
+ {
+ [CTypeDetails("Pointer<SoundIoDevice>")] public System.IntPtr @device;
+ public SoundIoFormat @format;
+ public int @sample_rate;
+ public SoundIoChannelLayout @layout;
+ public double @software_latency;
+ [CTypeDetails("Pointer<void>")] public System.IntPtr @userdata;
+ [CTypeDetails("Pointer<void (SoundIoOutStream *, int, int)>")] public delegate4 @write_callback;
+ [CTypeDetails("Pointer<void (SoundIoOutStream *)>")] public delegate5 @underflow_callback;
+ [CTypeDetails("Pointer<void (SoundIoOutStream *, int)>")] public delegate6 @error_callback;
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @name;
+ public bool @non_terminal_hint;
+ public int @bytes_per_frame;
+ public int @bytes_per_sample;
+ public int @layout_error;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoInStream // soundio.h (595, 8)
+ {
+ [CTypeDetails("Pointer<SoundIoDevice>")] public System.IntPtr @device;
+ public SoundIoFormat @format;
+ public int @sample_rate;
+ public SoundIoChannelLayout @layout;
+ public double @software_latency;
+ [CTypeDetails("Pointer<void>")] public System.IntPtr @userdata;
+ [CTypeDetails("Pointer<void (SoundIoInStream *, int, int)>")] public delegate7 @read_callback;
+ [CTypeDetails("Pointer<void (SoundIoInStream *)>")] public delegate8 @overflow_callback;
+ [CTypeDetails("Pointer<void (SoundIoInStream *, int)>")] public delegate9 @error_callback;
+ [CTypeDetails("Pointer<byte>")] public System.IntPtr @name;
+ public bool @non_terminal_hint;
+ public int @bytes_per_frame;
+ public int @bytes_per_sample;
+ public int @layout_error;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct SoundIoRingBuffer // soundio.h (1167, 8)
+ {
+ }
+
+ partial class Natives
+ {
+ const string LibraryName = "libsoundio";
+ // function soundio_version_string - soundio.h (677, 28)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_version_string();
+
+ // function soundio_version_major - soundio.h (679, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_version_major();
+
+ // function soundio_version_minor - soundio.h (681, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_version_minor();
+
+ // function soundio_version_patch - soundio.h (683, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_version_patch();
+
+ // function soundio_create - soundio.h (689, 32)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_create();
+
+ // function soundio_destroy - soundio.h (690, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_destroy([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_connect - soundio.h (700, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_connect([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_connect_backend - soundio.h (712, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_connect_backend([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, SoundIoBackend @backend);
+
+ // function soundio_disconnect - soundio.h (713, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_disconnect([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_strerror - soundio.h (716, 28)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_strerror(int @error);
+
+ // function soundio_backend_name - soundio.h (718, 28)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_backend_name(SoundIoBackend @backend);
+
+ // function soundio_backend_count - soundio.h (721, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_backend_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_get_backend - soundio.h (724, 36)
+ [DllImport(LibraryName)]
+ internal static extern SoundIoBackend soundio_get_backend([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, int @index);
+
+ // function soundio_have_backend - soundio.h (727, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_have_backend(SoundIoBackend @backend);
+
+ // function soundio_flush_events - soundio.h (751, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_flush_events([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_wait_events - soundio.h (755, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_wait_events([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_wakeup - soundio.h (758, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_wakeup([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_force_device_scan - soundio.h (775, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_force_device_scan([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_channel_layout_equal - soundio.h (782, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_channel_layout_equal([CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @a, [CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @b);
+
+ // function soundio_get_channel_name - soundio.h (786, 28)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_get_channel_name(SoundIoChannelId @id);
+
+ // function soundio_parse_channel_id - soundio.h (790, 38)
+ [DllImport(LibraryName)]
+ internal static extern SoundIoChannelId soundio_parse_channel_id([CTypeDetails("Pointer<byte>")]System.IntPtr @str, int @str_len);
+
+ // function soundio_channel_layout_builtin_count - soundio.h (793, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_channel_layout_builtin_count();
+
+ // function soundio_channel_layout_get_builtin - soundio.h (798, 51)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_channel_layout_get_builtin(int @index);
+
+ // function soundio_channel_layout_get_default - soundio.h (801, 51)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_channel_layout_get_default(int @channel_count);
+
+ // function soundio_channel_layout_find_channel - soundio.h (804, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_channel_layout_find_channel([CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @layout, SoundIoChannelId @channel);
+
+ // function soundio_channel_layout_detect_builtin - soundio.h (809, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_channel_layout_detect_builtin([CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @layout);
+
+ // function soundio_best_matching_channel_layout - soundio.h (814, 51)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_best_matching_channel_layout([CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @preferred_layouts, int @preferred_layout_count, [CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @available_layouts, int @available_layout_count);
+
+ // function soundio_sort_channel_layouts - soundio.h (819, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_sort_channel_layouts([CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @layouts, int @layout_count);
+
+ // function soundio_get_bytes_per_sample - soundio.h (825, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_get_bytes_per_sample(SoundIoFormat @format);
+
+ // function soundio_get_bytes_per_frame - soundio.h (828, 19)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_get_bytes_per_frame(SoundIoFormat @format, int @channel_count);
+
+ // function soundio_get_bytes_per_second - soundio.h (833, 19)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_get_bytes_per_second(SoundIoFormat @format, int @channel_count, int @sample_rate);
+
+ // function soundio_format_string - soundio.h (840, 29)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_format_string(SoundIoFormat @format);
+
+ // function soundio_input_device_count - soundio.h (856, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_input_device_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_output_device_count - soundio.h (859, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_output_device_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_get_input_device - soundio.h (865, 38)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_get_input_device([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, int @index);
+
+ // function soundio_get_output_device - soundio.h (870, 38)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_get_output_device([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, int @index);
+
+ // function soundio_default_input_device_index - soundio.h (875, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_default_input_device_index([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_default_output_device_index - soundio.h (880, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_default_output_device_index([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio);
+
+ // function soundio_device_ref - soundio.h (883, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_device_ref([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device);
+
+ // function soundio_device_unref - soundio.h (886, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_device_unref([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device);
+
+ // function soundio_device_equal - soundio.h (890, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_device_equal([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @a, [CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @b);
+
+ // function soundio_device_sort_channel_layouts - soundio.h (895, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_device_sort_channel_layouts([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device);
+
+ // function soundio_device_supports_format - soundio.h (899, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_device_supports_format([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device, SoundIoFormat @format);
+
+ // function soundio_device_supports_layout - soundio.h (904, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_device_supports_layout([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device, [CTypeDetails("Pointer<SoundIoChannelLayout>")]System.IntPtr @layout);
+
+ // function soundio_device_supports_sample_rate - soundio.h (909, 21)
+ [DllImport(LibraryName)]
+ internal static extern bool soundio_device_supports_sample_rate([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device, int @sample_rate);
+
+ // function soundio_device_nearest_sample_rate - soundio.h (914, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_device_nearest_sample_rate([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device, int @sample_rate);
+
+ // function soundio_outstream_create - soundio.h (924, 41)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_outstream_create([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device);
+
+ // function soundio_outstream_destroy - soundio.h (926, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_outstream_destroy([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream);
+
+ // function soundio_outstream_open - soundio.h (950, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_open([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream);
+
+ // function soundio_outstream_start - soundio.h (961, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_start([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream);
+
+ // function soundio_outstream_begin_write - soundio.h (993, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_begin_write([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream, [CTypeDetails("Pointer<System.IntPtr>")]System.IntPtr @areas, [CTypeDetails("Pointer<int>")]System.IntPtr @frame_count);
+
+ // function soundio_outstream_end_write - soundio.h (1005, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_end_write([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream);
+
+ // function soundio_outstream_clear_buffer - soundio.h (1020, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_clear_buffer([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream);
+
+ // function soundio_outstream_pause - soundio.h (1041, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_pause([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream, bool @pause);
+
+ // function soundio_outstream_get_latency - soundio.h (1054, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_outstream_get_latency([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream, [CTypeDetails("Pointer<double>")]System.IntPtr @out_latency);
+
+ // function soundio_instream_create - soundio.h (1064, 40)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_instream_create([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device);
+
+ // function soundio_instream_destroy - soundio.h (1066, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_instream_destroy([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream);
+
+ // function soundio_instream_open - soundio.h (1086, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_open([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream);
+
+ // function soundio_instream_start - soundio.h (1095, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_start([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream);
+
+ // function soundio_instream_begin_read - soundio.h (1126, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_begin_read([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream, [CTypeDetails("Pointer<System.IntPtr>")]System.IntPtr @areas, [CTypeDetails("Pointer<int>")]System.IntPtr @frame_count);
+
+ // function soundio_instream_end_read - soundio.h (1136, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_end_read([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream);
+
+ // function soundio_instream_pause - soundio.h (1149, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_pause([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream, bool @pause);
+
+ // function soundio_instream_get_latency - soundio.h (1159, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_instream_get_latency([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream, [CTypeDetails("Pointer<double>")]System.IntPtr @out_latency);
+
+ // function soundio_ring_buffer_create - soundio.h (1173, 42)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_ring_buffer_create([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, int @requested_capacity);
+
+ // function soundio_ring_buffer_destroy - soundio.h (1174, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_ring_buffer_destroy([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_capacity - soundio.h (1178, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_ring_buffer_capacity([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_write_ptr - soundio.h (1181, 22)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_ring_buffer_write_ptr([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_advance_write_ptr - soundio.h (1183, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_ring_buffer_advance_write_ptr([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer, int @count);
+
+ // function soundio_ring_buffer_read_ptr - soundio.h (1186, 22)
+ [DllImport(LibraryName)]
+ internal static extern System.IntPtr soundio_ring_buffer_read_ptr([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_advance_read_ptr - soundio.h (1188, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_ring_buffer_advance_read_ptr([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer, int @count);
+
+ // function soundio_ring_buffer_fill_count - soundio.h (1191, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_ring_buffer_fill_count([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_free_count - soundio.h (1194, 20)
+ [DllImport(LibraryName)]
+ internal static extern int soundio_ring_buffer_free_count([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ // function soundio_ring_buffer_clear - soundio.h (1197, 21)
+ [DllImport(LibraryName)]
+ internal static extern void soundio_ring_buffer_clear([CTypeDetails("Pointer<SoundIoRingBuffer>")]System.IntPtr @ring_buffer);
+
+ }
+
+ class Delegates
+ {
+ public delegate void delegate0(System.IntPtr p0);
+ public delegate void delegate1(System.IntPtr p0, int p1);
+ public delegate void delegate2();
+ public delegate void delegate3(System.IntPtr p0);
+ public delegate void delegate4(System.IntPtr p0, int p1, int p2);
+ public delegate void delegate5(System.IntPtr p0);
+ public delegate void delegate6(System.IntPtr p0, int p1);
+ public delegate void delegate7(System.IntPtr p0, int p1, int p2);
+ public delegate void delegate8(System.IntPtr p0);
+ public delegate void delegate9(System.IntPtr p0, int p1);
+ }
+
+ public struct Pointer<T>
+ {
+ public IntPtr Handle;
+ public static implicit operator IntPtr(Pointer<T> value) { return value.Handle; }
+ public static implicit operator Pointer<T>(IntPtr value) { return new Pointer<T>(value); }
+
+ public Pointer(IntPtr handle)
+ {
+ Handle = handle;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Pointer<T> && this == (Pointer<T>)obj;
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)Handle;
+ }
+
+ public static bool operator ==(Pointer<T> p1, Pointer<T> p2)
+ {
+ return p1.Handle == p2.Handle;
+ }
+
+ public static bool operator !=(Pointer<T> p1, Pointer<T> p2)
+ {
+ return p1.Handle != p2.Handle;
+ }
+ }
+ public struct ArrayOf<T> { }
+ public struct ConstArrayOf<T> { }
+ public class CTypeDetailsAttribute : Attribute
+ {
+ public CTypeDetailsAttribute(string value)
+ {
+ Value = value;
+ }
+
+ public string Value { get; set; }
+ }
+
+}