diff options
Diffstat (limited to 'Ryujinx.Audio.Backends.SoundIo/Native/libsoundio')
19 files changed, 2342 insertions, 0 deletions
diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/MarshalExtensions.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/MarshalExtensions.cs new file mode 100644 index 00000000..5e86263e --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/MarshalExtensions.cs @@ -0,0 +1,38 @@ +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)); + } + + public static float ReadFloat(IntPtr handle, int offset = 0) + { + return BitConverter.Int32BitsToSingle(Marshal.ReadInt32(handle, offset)); + } + + public static void WriteFloat(IntPtr handle, float value) + { + WriteFloat(handle, 0, value); + } + + public static void WriteFloat(IntPtr handle, int offset, float value) + { + Marshal.WriteInt32(handle, offset, BitConverter.SingleToInt32Bits(value)); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIO.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIO.cs new file mode 100644 index 00000000..c4ce1887 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIO.cs @@ -0,0 +1,386 @@ +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 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)); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOBackend.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOBackend.cs new file mode 100644 index 00000000..fd105804 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOBackend.cs @@ -0,0 +1,13 @@ +namespace SoundIOSharp +{ + public enum SoundIOBackend + { + None, + Jack, + PulseAudio, + Alsa, + CoreAudio, + Wasapi, + Dummy + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelArea.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelArea.cs new file mode 100644 index 00000000..c15fb744 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelArea.cs @@ -0,0 +1,30 @@ +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"); + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelAreas.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelAreas.cs new file mode 100644 index 00000000..e0f375b9 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelAreas.cs @@ -0,0 +1,34 @@ +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; + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelId.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelId.cs new file mode 100644 index 00000000..002669dc --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelId.cs @@ -0,0 +1,75 @@ +namespace SoundIOSharp +{ + 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 + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelLayout.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelLayout.cs new file mode 100644 index 00000000..cff6114f --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOChannelLayout.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +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); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODevice.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODevice.cs new file mode 100644 index 00000000..6e7c4964 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODevice.cs @@ -0,0 +1,267 @@ +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 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)); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODeviceAim.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODeviceAim.cs new file mode 100644 index 00000000..1e596127 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIODeviceAim.cs @@ -0,0 +1,8 @@ +namespace SoundIOSharp +{ + public enum SoundIODeviceAim // soundio.h (228, 6) + { + Input, + Output + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOException.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOException.cs new file mode 100644 index 00000000..537b6cde --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOException.cs @@ -0,0 +1,10 @@ +using System; +using System.Runtime.InteropServices; + +namespace SoundIOSharp +{ + public class SoundIOException : Exception + { + internal SoundIOException(SoundIoError errorCode) : base (Marshal.PtrToStringAnsi(Natives.soundio_strerror((int) errorCode))) { } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOFormat.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOFormat.cs new file mode 100644 index 00000000..df1b71c6 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOFormat.cs @@ -0,0 +1,25 @@ +namespace SoundIOSharp +{ + public enum SoundIOFormat + { + Invalid, + S8, + U8, + S16LE, + S16BE, + U16LE, + U16BE, + S24LE, + S24BE, + U24LE, + U24BE, + S32LE, + S32BE, + U32LE, + U32BE, + Float32LE, + Float32BE, + Float64LE, + Float64BE + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOInStream.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOInStream.cs new file mode 100644 index 00000000..df97d653 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOInStream.cs @@ -0,0 +1,293 @@ +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 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; + } + } + } +} diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOOutStream.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOOutStream.cs new file mode 100644 index 00000000..432ca42b --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOOutStream.cs @@ -0,0 +1,331 @@ +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 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); + } + } + } +} diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIORingBuffer.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIORingBuffer.cs new file mode 100644 index 00000000..7530da72 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIORingBuffer.cs @@ -0,0 +1,58 @@ +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); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOSampleRateRange.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/SoundIOSampleRateRange.cs new file mode 100644 index 00000000..e01ec2bd --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/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.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dll b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dll Binary files differnew file mode 100644 index 00000000..48804312 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dll diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dylib b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dylib Binary files differnew file mode 100644 index 00000000..10171f4f --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.dylib diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.so b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.so Binary files differnew file mode 100644 index 00000000..87c8b506 --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libs/libsoundio.so diff --git a/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libsoundio-interop.cs b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libsoundio-interop.cs new file mode 100644 index 00000000..5377582f --- /dev/null +++ b/Ryujinx.Audio.Backends.SoundIo/Native/libsoundio/libsoundio-interop.cs @@ -0,0 +1,643 @@ +// 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 (306, 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 (313, 8) + { + public int @min; + public int @max; + } + + [StructLayout(LayoutKind.Sequential)] + struct SoundIoChannelArea // soundio.h (319, 8) + { + [CTypeDetails("Pointer<byte>")] public System.IntPtr @ptr; + public int @step; + } + + [StructLayout(LayoutKind.Sequential)] + struct SoundIo // soundio.h (328, 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 (387, 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 (497, 8) + { + [CTypeDetails("Pointer<SoundIoDevice>")] public System.IntPtr @device; + public SoundIoFormat @format; + public int @sample_rate; + public SoundIoChannelLayout @layout; + public double @software_latency; + public float @volume; + [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 (600, 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 (1170, 8) + { + } + + partial class Natives + { + const string LibraryName = "libsoundio"; + // function soundio_version_string - soundio.h (682, 28) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_version_string(); + + // function soundio_version_major - soundio.h (684, 20) + [DllImport(LibraryName)] + internal static extern int soundio_version_major(); + + // function soundio_version_minor - soundio.h (686, 20) + [DllImport(LibraryName)] + internal static extern int soundio_version_minor(); + + // function soundio_version_patch - soundio.h (688, 20) + [DllImport(LibraryName)] + internal static extern int soundio_version_patch(); + + // function soundio_create - soundio.h (694, 32) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_create(); + + // function soundio_destroy - soundio.h (695, 21) + [DllImport(LibraryName)] + internal static extern void soundio_destroy([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_connect - soundio.h (705, 20) + [DllImport(LibraryName)] + internal static extern int soundio_connect([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_connect_backend - soundio.h (717, 20) + [DllImport(LibraryName)] + internal static extern int soundio_connect_backend([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, SoundIoBackend @backend); + + // function soundio_disconnect - soundio.h (718, 21) + [DllImport(LibraryName)] + internal static extern void soundio_disconnect([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_strerror - soundio.h (721, 28) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_strerror(int @error); + + // function soundio_backend_name - soundio.h (723, 28) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_backend_name(SoundIoBackend @backend); + + // function soundio_backend_count - soundio.h (726, 20) + [DllImport(LibraryName)] + internal static extern int soundio_backend_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_get_backend - soundio.h (729, 36) + [DllImport(LibraryName)] + internal static extern SoundIoBackend soundio_get_backend([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio, int @index); + + // function soundio_have_backend - soundio.h (732, 21) + [DllImport(LibraryName)] + internal static extern bool soundio_have_backend(SoundIoBackend @backend); + + // function soundio_flush_events - soundio.h (756, 21) + [DllImport(LibraryName)] + internal static extern void soundio_flush_events([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_wait_events - soundio.h (760, 21) + [DllImport(LibraryName)] + internal static extern void soundio_wait_events([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_wakeup - soundio.h (763, 21) + [DllImport(LibraryName)] + internal static extern void soundio_wakeup([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_force_device_scan - soundio.h (780, 21) + [DllImport(LibraryName)] + internal static extern void soundio_force_device_scan([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_channel_layout_equal - soundio.h (787, 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 (791, 28) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_get_channel_name(SoundIoChannelId @id); + + // function soundio_parse_channel_id - soundio.h (795, 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 (798, 20) + [DllImport(LibraryName)] + internal static extern int soundio_channel_layout_builtin_count(); + + // function soundio_channel_layout_get_builtin - soundio.h (803, 51) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_channel_layout_get_builtin(int @index); + + // function soundio_channel_layout_get_default - soundio.h (806, 51) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_channel_layout_get_default(int @channel_count); + + // function soundio_channel_layout_find_channel - soundio.h (809, 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 (814, 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 (819, 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 (824, 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 (830, 20) + [DllImport(LibraryName)] + internal static extern int soundio_get_bytes_per_sample(SoundIoFormat @format); + + // function soundio_get_bytes_per_frame - soundio.h (833, 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 (838, 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 (845, 29) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_format_string(SoundIoFormat @format); + + // function soundio_input_device_count - soundio.h (861, 20) + [DllImport(LibraryName)] + internal static extern int soundio_input_device_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_output_device_count - soundio.h (864, 20) + [DllImport(LibraryName)] + internal static extern int soundio_output_device_count([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_get_input_device - soundio.h (870, 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 (875, 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 (880, 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 (885, 20) + [DllImport(LibraryName)] + internal static extern int soundio_default_output_device_index([CTypeDetails("Pointer<SoundIo>")]System.IntPtr @soundio); + + // function soundio_device_ref - soundio.h (888, 21) + [DllImport(LibraryName)] + internal static extern void soundio_device_ref([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device); + + // function soundio_device_unref - soundio.h (891, 21) + [DllImport(LibraryName)] + internal static extern void soundio_device_unref([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device); + + // function soundio_device_equal - soundio.h (895, 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 (900, 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 (904, 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 (909, 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 (914, 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 (919, 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 (929, 41) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_outstream_create([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device); + + // function soundio_outstream_destroy - soundio.h (931, 21) + [DllImport(LibraryName)] + internal static extern void soundio_outstream_destroy([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream); + + // function soundio_outstream_open - soundio.h (954, 20) + [DllImport(LibraryName)] + internal static extern int soundio_outstream_open([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream); + + // function soundio_outstream_start - soundio.h (965, 20) + [DllImport(LibraryName)] + internal static extern int soundio_outstream_start([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream); + + // function soundio_outstream_begin_write - soundio.h (997, 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 (1009, 20) + [DllImport(LibraryName)] + internal static extern int soundio_outstream_end_write([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream); + + // function soundio_outstream_clear_buffer - soundio.h (1024, 20) + [DllImport(LibraryName)] + internal static extern int soundio_outstream_clear_buffer([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream); + + // function soundio_outstream_pause - soundio.h (1045, 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 (1058, 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_outstream_set_volume - soundio.h (1061, 20) + [DllImport(LibraryName)] + internal static extern int soundio_outstream_set_volume([CTypeDetails("Pointer<SoundIoOutStream>")]System.IntPtr @outstream, double @volume); + + // function soundio_instream_create - soundio.h (1071, 40) + [DllImport(LibraryName)] + internal static extern System.IntPtr soundio_instream_create([CTypeDetails("Pointer<SoundIoDevice>")]System.IntPtr @device); + + // function soundio_instream_destroy - soundio.h (1073, 21) + [DllImport(LibraryName)] + internal static extern void soundio_instream_destroy([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream); + + // function soundio_instream_open - soundio.h (1093, 20) + [DllImport(LibraryName)] + internal static extern int soundio_instream_open([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream); + + // function soundio_instream_start - soundio.h (1102, 20) + [DllImport(LibraryName)] + internal static extern int soundio_instream_start([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream); + + // function soundio_instream_begin_read - soundio.h (1133, 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 (1143, 20) + [DllImport(LibraryName)] + internal static extern int soundio_instream_end_read([CTypeDetails("Pointer<SoundIoInStream>")]System.IntPtr @instream); + + // function soundio_instream_pause - soundio.h (1156, 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 (1166, 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 (1181, 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 (1182, 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 (1186, 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 (1189, 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 (1191, 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 (1194, 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 (1196, 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 (1199, 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 (1202, 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 (1205, 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; } + } + +} |
