using System;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
using static Vanara.PInvoke.Winmm;

namespace Vanara.PInvoke
{
	/// <summary>Functions, structures and constants from Windows Core Audio Api.</summary>
	public static partial class CoreAudio
	{
		/// <summary>The <c>_AUDCLNT_BUFFERFLAGS</c> enumeration defines flags that indicate the status of an audio endpoint buffer.</summary>
		/// <remarks>
		/// The IAudioCaptureClient::GetBuffer and IAudioRenderClient::ReleaseBuffer methods use the constants defined in the
		/// <c>_AUDCLNT_BUFFERFLAGS</c> enumeration.
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/ne-audioclient-_audclnt_bufferflags typedef enum
		// _AUDCLNT_BUFFERFLAGS { AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY, AUDCLNT_BUFFERFLAGS_SILENT, AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR } ;
		[PInvokeData("audioclient.h", MSDNShortId = "ac4ec901-b1e2-4c4e-b9fc-1808d5338d15")]
		[Flags]
		public enum AUDCLNT_BUFFERFLAGS
		{
			/// <summary>
			/// The data in the packet is not correlated with the previous packet's device position; this is possibly due to a stream state
			/// transition or timing glitch.
			/// </summary>
			AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY = 0x01,

			/// <summary>
			/// Treat all of the data in the packet as silence and ignore the actual data values. For more information about the use of this
			/// flag, see Rendering a Stream and Capturing a Stream.
			/// </summary>
			AUDCLNT_BUFFERFLAGS_SILENT = 0x02,

			/// <summary>
			/// The time at which the device's stream position was recorded is uncertain. Thus, the client might be unable to accurately set
			/// the time stamp for the current data packet.
			/// </summary>
			AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR = 0x04,
		}

		/// <summary>Defines values that describe the characteristics of an audio stream.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/ne-audioclient-audclnt_streamoptions typedef enum
		// AUDCLNT_STREAMOPTIONS { AUDCLNT_STREAMOPTIONS_NONE, AUDCLNT_STREAMOPTIONS_RAW, AUDCLNT_STREAMOPTIONS_MATCH_FORMAT,
		// AUDCLNT_STREAMOPTIONS_AMBISONICS } ;
		[PInvokeData("audioclient.h", MSDNShortId = "C9A51FB2-46F5-4F20-B9F2-63EC53CAB3D7")]
		[Flags]
		public enum AUDCLNT_STREAMOPTIONS
		{
			/// <summary>No stream options.</summary>
			AUDCLNT_STREAMOPTIONS_NONE = 0x00,

			/// <summary>
			/// The audio stream is a 'raw' stream that bypasses all signal processing except for endpoint specific, always-on processing in
			/// the Audio Processing Object (APO), driver, and hardware.
			/// </summary>
			AUDCLNT_STREAMOPTIONS_RAW = 0x01,

			/// <summary>
			/// The audio client is requesting that the audio engine match the format proposed by the client. The audio enginewill match
			/// this format only if the format is supported by the audio driver and associated APOs. Supported in Windows 10 and later.
			/// </summary>
			AUDCLNT_STREAMOPTIONS_MATCH_FORMAT = 0x02,

			/// <summary/>
			AUDCLNT_STREAMOPTIONS_AMBISONIC = 0x04,
		}

		//[ComImport, Guid("28724C91-DF35-4856-9F76-D6A26413F3DF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		//public interface IAudioAmbisonicsControl
		//{
		//	HRESULT SetData([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] AMBISONICS_PARAMS[] pAmbisonicsParams, uint cbAmbisonicsParams);
		//	HRESULT SetHeadTracking([MarshalAs(UnmanagedType.Bool)] bool bEnableHeadTracking);
		//	HRESULT GetHeadTracking([MarshalAs(UnmanagedType.Bool)] out bool pbEnableHeadTracking);
		//	HRESULT SetRotation(float X, float Y, float Z, float W);
		//}

		/// <summary>
		/// <para>
		/// The <c>IAudioCaptureClient</c> interface enables a client to read input data from a capture endpoint buffer. The client obtains
		/// a reference to the <c>IAudioCaptureClient</c> interface on a stream object by calling the IAudioClient::GetService method with
		/// parameter riid set to REFIID IID_IAudioCaptureClient.
		/// </para>
		/// <para>
		/// The methods in this interface manage the movement of data packets that contain capture data. The length of a data packet is
		/// expressed as the number of audio frames in the packet. The size of an audio frame is specified by the <c>nBlockAlign</c> member
		/// of the W <c>AVEFORMATEX (or WAVEFORMATEXTENSIBLE)</c> structure that the client obtains by calling the
		/// IAudioClient::GetMixFormat method. The size in bytes of an audio frame equals the number of channels in the stream multiplied by
		/// the sample size per channel. For example, the frame size is four bytes for a stereo (2-channel) stream with 16-bit samples. A
		/// packet always contains an integral number of audio frames.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioCaptureClient</c> interface instance, the client must call the <c>Release</c> method of the instance
		/// from the same thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// <para>For a code example that uses the <c>IAudioCaptureClient</c> interface, see Capturing a Stream.</para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiocaptureclient
		[PInvokeData("audioclient.h", MSDNShortId = "c0fa6841-56bf-421e-9949-c6a037cf9fd4")]
		[ComImport, Guid("C8ADBD64-E71E-48a0-A4DE-185C395CD317"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioCaptureClient
		{
			/// <summary>Retrieves a pointer to the next available packet of data in the capture endpoint buffer.</summary>
			/// <param name="ppData">
			/// Pointer to a pointer variable into which the method writes the starting address of the next data packet that is available
			/// for the client to read.
			/// </param>
			/// <param name="pNumFramesToRead">
			/// Pointer to a <c>UINT32</c> variable into which the method writes the frame count (the number of audio frames available in
			/// the data packet). The client should either read the entire data packet or none of it.
			/// </param>
			/// <param name="pdwFlags">
			/// <para>
			/// Pointer to a <c>DWORD</c> variable into which the method writes the buffer-status flags. The method writes either 0 or the
			/// bitwise-OR combination of one or more of the following _AUDCLNT_BUFFERFLAGS enumeration values:
			/// </para>
			/// <para>AUDCLNT_BUFFERFLAGS_SILENT</para>
			/// <para>AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY</para>
			/// <para>AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR</para>
			/// <para>
			/// <c>Note</c> The AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY flag is not supported in Windows Vista.In Windows 7 and later OS
			/// releases, this flag can be used for glitch detection. To start the capture stream, the client application must call
			/// IAudioClient::Start followed by calls to <c>GetBuffer</c> in a loop to read data packets until all of the available packets
			/// in the endpoint buffer have been read. <c>GetBuffer</c> sets the AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY flag to indicate a
			/// glitch in the buffer pointed by ppData.
			/// </para>
			/// </param>
			/// <param name="pu64DevicePosition">
			/// Pointer to a <c>UINT64</c> variable into which the method writes the device position of the first audio frame in the data
			/// packet. The device position is expressed as the number of audio frames from the start of the stream. This parameter can be
			/// <c>NULL</c> if the client does not require the device position. For more information, see Remarks.
			/// </param>
			/// <param name="pu64QPCPosition">
			/// Pointer to a <c>UINT64</c> variable into which the method writes the value of the performance counter at the time that the
			/// audio endpoint device recorded the device position of the first audio frame in the data packet. The method converts the
			/// counter value to 100-nanosecond units before writing it to *pu64QPCPosition. This parameter can be <c>NULL</c> if the client
			/// does not require the performance counter value. For more information, see Remarks.
			/// </param>
			/// <returns>
			/// <para>Possible return codes include, but are not limited to, the values shown in the following table.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>S_OK</term>
			/// <term>The call succeeded and *pNumFramesToRead is nonzero, indicating that a packet is ready to be read.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_S_BUFFER_EMPTY</term>
			/// <term>The call succeeded and *pNumFramesToRead is 0, indicating that no capture data is available to be read.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_ERROR</term>
			/// <term>
			/// Windows 7 and later: GetBuffer failed to retrieve a data buffer and *ppData points to NULL. For more information, see Remarks.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_OUT_OF_ORDER</term>
			/// <term>A previous IAudioCaptureClient::GetBuffer call is still in effect.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_OPERATION_PENDING</term>
			/// <term>Buffer cannot be accessed because a stream reset is in progress.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter ppData, pNumFramesToRead, or pdwFlags is NULL.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method retrieves the next data packet from the capture endpoint buffer. At a particular time, the buffer might contain
			/// zero, one, or more packets that are ready to read. Typically, a buffer-processing thread that reads data from a capture
			/// endpoint buffer reads all of the available packets each time the thread executes.
			/// </para>
			/// <para>
			/// During processing of an audio capture stream, the client application alternately calls <c>GetBuffer</c> and the
			/// IAudioCaptureClient::ReleaseBuffer method. The client can read no more than a single data packet with each <c>GetBuffer</c>
			/// call. Following each <c>GetBuffer</c> call, the client must call <c>ReleaseBuffer</c> to release the packet before the
			/// client can call <c>GetBuffer</c> again to get the next packet.
			/// </para>
			/// <para>
			/// Two or more consecutive calls either to <c>GetBuffer</c> or to <c>ReleaseBuffer</c> are not permitted and will fail with
			/// error code AUDCLNT_E_OUT_OF_ORDER. To ensure the correct ordering of calls, a <c>GetBuffer</c> call and its corresponding
			/// <c>ReleaseBuffer</c> call must occur in the same thread.
			/// </para>
			/// <para>
			/// During each <c>GetBuffer</c> call, the caller must either obtain the entire packet or none of it. Before reading the packet,
			/// the caller can check the packet size (available through the pNumFramesToRead parameter) to make sure that it has enough room
			/// to store the entire packet.
			/// </para>
			/// <para>
			/// During each <c>ReleaseBuffer</c> call, the caller reports the number of audio frames that it read from the buffer. This
			/// number must be either the (nonzero) packet size or 0. If the number is 0, then the next <c>GetBuffer</c> call will present
			/// the caller with the same packet as in the previous <c>GetBuffer</c> call.
			/// </para>
			/// <para>
			/// Following each <c>GetBuffer</c> call, the data in the packet remains valid until the next <c>ReleaseBuffer</c> call releases
			/// the buffer.
			/// </para>
			/// <para>
			/// The client must call <c>ReleaseBuffer</c> after a <c>GetBuffer</c> call that successfully obtains a packet of any size other
			/// than 0. The client has the option of calling or not calling <c>ReleaseBuffer</c> to release a packet of size 0.
			/// </para>
			/// <para>
			/// The method outputs the device position and performance counter through the pu64DevicePosition and pu64QPCPosition output
			/// parameters. These values provide a time stamp for the first audio frame in the data packet. Through the pdwFlags output
			/// parameter, the method indicates whether the reported device position is valid.
			/// </para>
			/// <para>
			/// The device position that the method writes to *pu64DevicePosition is the stream-relative position of the audio frame that is
			/// currently playing through the speakers (for a rendering stream) or being recorded through the microphone (for a capture
			/// stream). The position is expressed as the number of frames from the start of the stream. The size of a frame in an audio
			/// stream is specified by the <c>nBlockAlign</c> member of the <c>WAVEFORMATEX</c> (or <c>WAVEFORMATEXTENSIBLE</c>) structure
			/// that specifies the stream format. The size, in bytes, of an audio frame equals the number of channels in the stream
			/// multiplied by the sample size per channel. For example, for a stereo (2-channel) stream with 16-bit samples, the frame size
			/// is four bytes.
			/// </para>
			/// <para>
			/// The performance counter value that <c>GetBuffer</c> writes to *pu64QPCPosition is not the raw counter value obtained from
			/// the <c>QueryPerformanceCounter</c> function. If t is the raw counter value, and if f is the frequency obtained from the
			/// <c>QueryPerformanceFrequency</c> function, <c>GetBuffer</c> calculates the performance counter value as follows:
			/// </para>
			/// <para>*pu64QPCPosition = 10,000,000t/f</para>
			/// <para>
			/// The result is expressed in 100-nanosecond units. For more information about <c>QueryPerformanceCounter</c> and
			/// <c>QueryPerformanceFrequency</c>, see the Windows SDK documentation.
			/// </para>
			/// <para>
			/// If no new packet is currently available, the method sets *pNumFramesToRead = 0 and returns status code
			/// AUDCLNT_S_BUFFER_EMPTY. In this case, the method does not write to the variables that are pointed to by the ppData,
			/// pu64DevicePosition, and pu64QPCPosition parameters.
			/// </para>
			/// <para>
			/// Clients should avoid excessive delays between the <c>GetBuffer</c> call that acquires a packet and the <c>ReleaseBuffer</c>
			/// call that releases the packet. The implementation of the audio engine assumes that the <c>GetBuffer</c> call and the
			/// corresponding <c>ReleaseBuffer</c> call occur within the same buffer-processing period. Clients that delay releasing a
			/// packet for more than one period risk losing sample data.
			/// </para>
			/// <para>
			/// In Windows 7 and later, <c>GetBuffer</c> can return the <c>AUDCLNT_E_BUFFER_ERROR</c> error code for an audio client that
			/// uses the endpoint buffer in the exclusive mode. This error indicates that the data buffer was not retrieved because a data
			/// packet wasn't available (*ppData received <c>NULL</c>).
			/// </para>
			/// <para>
			/// If <c>GetBuffer</c> returns <c>AUDCLNT_E_BUFFER_ERROR</c>, the thread consuming the audio samples must wait for the next
			/// processing pass. The client might benefit from keeping a count of the failed <c>GetBuffer</c> calls. If <c>GetBuffer</c>
			/// returns this error repeatedly, the client can start a new processing loop after shutting down the current client by calling
			/// IAudioClient::Stop, IAudioClient::Reset, and releasing the audio client.
			/// </para>
			/// <para>Examples</para>
			/// <para>For a code example that calls the <c>GetBuffer</c> method, see Capturing a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiocaptureclient-getbuffer HRESULT
			// GetBuffer( BYTE **ppData, UINT32 *pNumFramesToRead, DWORD *pdwFlags, UINT64 *pu64DevicePosition, UINT64 *pu64QPCPosition );
			[PreserveSig]
			HRESULT GetBuffer(out IntPtr ppData, out uint pNumFramesToRead, out AUDCLNT_BUFFERFLAGS pdwFlags, out ulong pu64DevicePosition, out ulong pu64QPCPosition);

			/// <summary>The <c>ReleaseBuffer</c> method releases the buffer.</summary>
			/// <param name="NumFramesRead">
			/// The number of audio frames that the client read from the capture buffer. This parameter must be either equal to the number
			/// of frames in the previously acquired data packet or 0.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_INVALID_SIZE</term>
			/// <term>The NumFramesRead parameter is set to a value other than the data packet size or 0.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_OUT_OF_ORDER</term>
			/// <term>This call was not preceded by a corresponding IAudioCaptureClient::GetBuffer call.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The client should call this method when it finishes reading a data packet that it obtained previously by calling the
			/// IAudioCaptureClient::GetBuffer method.
			/// </para>
			/// <para>
			/// The data in the packet that the client obtained from a GetBuffer call is guaranteed to remain valid until the client calls
			/// <c>ReleaseBuffer</c> to release the packet.
			/// </para>
			/// <para>
			/// Between each GetBuffer call and its corresponding <c>ReleaseBuffer</c> call, the client must either read the entire data
			/// packet or none of it. If the client reads the entire packet following the <c>GetBuffer</c> call, then it should call
			/// <c>ReleaseBuffer</c> with NumFramesRead set to the total number of frames in the data packet. In this case, the next call to
			/// <c>GetBuffer</c> will produce a new data packet. If the client reads none of the data from the packet following the call to
			/// <c>GetBuffer</c>, then it should call <c>ReleaseBuffer</c> with NumFramesRead set to 0. In this case, the next
			/// <c>GetBuffer</c> call will produce the same data packet as in the previous <c>GetBuffer</c> call.
			/// </para>
			/// <para>
			/// If the client calls <c>ReleaseBuffer</c> with NumFramesRead set to any value other than the packet size or 0, then the call
			/// fails and returns error code AUDCLNT_E_INVALID_SIZE.
			/// </para>
			/// <para>
			/// Clients should avoid excessive delays between the GetBuffer call that acquires a buffer and the <c>ReleaseBuffer</c> call
			/// that releases the buffer. The implementation of the audio engine assumes that the <c>GetBuffer</c> call and the
			/// corresponding <c>ReleaseBuffer</c> call occur within the same buffer-processing period. Clients that delay releasing a
			/// buffer for more than one period risk losing sample data.
			/// </para>
			/// <para>For a code example that calls the <c>ReleaseBuffer</c> method, see Capturing a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiocaptureclient-releasebuffer HRESULT
			// ReleaseBuffer( UINT32 NumFramesRead );
			[PreserveSig]
			HRESULT ReleaseBuffer([In] uint NumFramesRead);

			/// <summary>
			/// The <c>GetNextPacketSize</c> method retrieves the number of frames in the next data packet in the capture endpoint buffer.
			/// </summary>
			/// <param name="pNumFramesInNextPacket">
			/// Pointer to a <c>UINT32</c> variable into which the method writes the frame count (the number of audio frames in the next
			/// capture packet).
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pNumFramesInNextPacket is NULL.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>Use this method only with shared-mode streams. It does not work with exclusive-mode streams.</para>
			/// <para>
			/// Before calling the IAudioCaptureClient::GetBuffer method to retrieve the next data packet, the client can call
			/// <c>GetNextPacketSize</c> to retrieve the number of audio frames in the next packet. The count reported by
			/// <c>GetNextPacketSize</c> matches the count retrieved in the <c>GetBuffer</c> call (through the pNumFramesToRead output
			/// parameter) that follows the <c>GetNextPacketSize</c> call.
			/// </para>
			/// <para>A packet always consists of an integral number of audio frames.</para>
			/// <para>
			/// <c>GetNextPacketSize</c> must be called in the same thread as the GetBuffer and IAudioCaptureClient::ReleaseBuffer method
			/// calls that get and release the packets in the capture endpoint buffer.
			/// </para>
			/// <para>For a code example that uses the <c>GetNextPacketSize</c> method, see Capturing a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiocaptureclient-getnextpacketsize HRESULT
			// GetNextPacketSize( UINT32 *pNumFramesInNextPacket );
			[PreserveSig]
			HRESULT GetNextPacketSize(out uint pNumFramesInNextPacket);
		}

		/// <summary>
		/// <para>
		/// The <c>IAudioClient</c> interface enables a client to create and initialize an audio stream between an audio application and the
		/// audio engine (for a shared-mode stream) or the hardware buffer of an audio endpoint device (for an exclusive-mode stream). A
		/// client obtains a reference to an <c>IAudioClient</c> interface for an audio endpoint device by following these steps:
		/// </para>
		/// <list type="number">
		/// <item>
		/// <term>
		/// By using one of the techniques described in IMMDevice Interface, obtain a reference to the <c>IMMDevice</c> interface for an
		/// audio endpoint device.
		/// </term>
		/// </item>
		/// <item>
		/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient.</term>
		/// </item>
		/// </list>
		/// <para>
		/// The application thread that uses this interface must be initialized for COM. For more information about COM initialization, see
		/// the description of the <c>CoInitializeEx</c> function in the Windows SDK documentation.
		/// </para>
		/// <para>For code examples that use the <c>IAudioClient</c> interface, see the following topics:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Capturing a Stream</term>
		/// </item>
		/// <item>
		/// <term>Exclusive-Mode Streams</term>
		/// </item>
		/// </list>
		/// </summary>
		/// <remarks>
		/// <c>Note</c> In Windows 8, the first use of <c>IAudioClient</c> to access the audio device should be on the STA thread. Calls
		/// from an MTA thread may result in undefined behavior.
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclient
		[PInvokeData("audioclient.h", MSDNShortId = "5088a3f1-5001-4ed9-a495-9e91df613ab0")]
		[ComImport, Guid("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClient
		{
			/// <summary>The <c>Initialize</c> method initializes the audio stream.</summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the connection. Through this parameter, the client tells the audio engine whether it wants to share the
			/// audio endpoint device with other clients. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="StreamFlags">
			/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of
			/// the AUDCLNT_STREAMFLAGS_XXX Constants or the AUDCLNT_SESSIONFLAGS_XXX Constants.
			/// </param>
			/// <param name="hnsBufferDuration">
			/// The buffer capacity as a time value. This parameter is of type <c>REFERENCE_TIME</c> and is expressed in 100-nanosecond
			/// units. This parameter contains the buffer size that the caller requests for the buffer that the audio application will share
			/// with the audio engine (in shared mode) or with the endpoint device (in exclusive mode). If the call succeeds, the method
			/// allocates a buffer that is a least this large. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK
			/// documentation. For more information about buffering requirements, see Remarks.
			/// </param>
			/// <param name="hnsPeriodicity">
			/// The device period. This parameter can be nonzero only in exclusive mode. In shared mode, always set this parameter to 0. In
			/// exclusive mode, this parameter specifies the requested scheduling period for successive buffer accesses by the audio
			/// endpoint device. If the requested device period lies outside the range that is set by the device's minimum period and the
			/// system's maximum period, then the method clamps the period to that range. If this parameter is 0, the method sets the device
			/// period to its default value. To obtain the default device period, call the IAudioClient::GetDevicePeriod method. If the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK stream flag is set and AUDCLNT_SHAREMODE_EXCLUSIVE is set as the ShareMode, then
			/// hnsPeriodicity must be nonzero and equal to hnsBufferDuration.
			/// </param>
			/// <param name="pFormat">
			/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>). For more information, see Remarks.
			/// </param>
			/// <param name="AudioSessionGuid">
			/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs
			/// to. If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the
			/// GUID does not identify an existing session, the method opens a new session and adds the stream to that session. The stream
			/// remains a member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a
			/// pointer to a GUID_NULL value.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_ALREADY_INITIALIZED</term>
			/// <term>The IAudioClient object is already initialized.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_WRONG_ENDPOINT_TYPE</term>
			/// <term>The AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but the endpoint device is a capture device, not a rendering device.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</term>
			/// <term>
			/// The requested buffer size is not aligned. This code can be returned for a render or a capture device if the caller specified
			/// AUDCLNT_SHAREMODE_EXCLUSIVE and the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flags. The caller must call Initialize again with the
			/// aligned buffer size. For more information, see Remarks.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
			/// <term>
			/// Indicates that the buffer duration value requested by an exclusive-mode client is out of range. The requested duration value
			/// for pull mode must not be greater than 500 milliseconds; for push mode the duration value must not be greater than 2 seconds.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_CPUUSAGE_EXCEEDED</term>
			/// <term>
			/// Indicates that the process-pass duration exceeded the maximum CPU usage. The audio engine keeps track of CPU usage by
			/// maintaining the number of times the process-pass duration exceeds the maximum CPU usage. The maximum CPU usage is calculated
			/// as a percent of the engine's periodicity. The percentage value is the system's CPU throttle value (within the range of 10%
			/// and 90%). If this value is not found, then the default value of 40% is used to calculate the maximum CPU usage.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_IN_USE</term>
			/// <term>
			/// The endpoint device is already in use. Either the device is being used in exclusive mode, or the device is being used in
			/// shared mode and the caller asked to use the device in exclusive mode.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_ENDPOINT_CREATE_FAILED</term>
			/// <term>
			/// The method failed to create the audio endpoint for the render or the capture device. This can occur if the audio endpoint
			/// device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured, disabled, removed,
			/// or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_INVALID_DEVICE_PERIOD</term>
			/// <term>Indicates that the device period requested by an exclusive-mode client is greater than 500 milliseconds.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>The audio engine (shared mode) or audio endpoint device (exclusive mode) does not support the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED</term>
			/// <term>
			/// The caller is requesting exclusive-mode use of the endpoint device, but the user has disabled exclusive-mode use of the device.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL</term>
			/// <term>The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is set but parameters hnsBufferDuration and hnsPeriodicity are not equal.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>
			/// Parameter pFormat points to an invalid format description; or the AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but ShareMode is
			/// not equal to AUDCLNT_SHAREMODE_SHARED; or the AUDCLNT_STREAMFLAGS_CROSSPROCESS flag is set but ShareMode is equal to
			/// AUDCLNT_SHAREMODE_EXCLUSIVE. A prior call to SetClientProperties was made with an invalid category for audio/render streams.
			/// </term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// After activating an IAudioClient interface on an audio endpoint device, the client must successfully call <c>Initialize</c>
			/// once and only once to initialize the audio stream between the client and the device. The client can either connect directly
			/// to the audio hardware (exclusive mode) or indirectly through the audio engine (shared mode). In the <c>Initialize</c> call,
			/// the client specifies the audio data format, the buffer size, and audio session for the stream.
			/// </para>
			/// <para>
			/// <c>Note</c> In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from
			/// an MTA thread may result in undefined behavior.
			/// </para>
			/// <para>
			/// An attempt to create a shared-mode stream can succeed only if the audio device is already operating in shared mode or the
			/// device is currently unused. An attempt to create a shared-mode stream fails if the device is already operating in exclusive mode.
			/// </para>
			/// <para>
			/// If a stream is initialized to be event driven and in shared mode, ShareMode is set to AUDCLNT_SHAREMODE_SHARED and one of
			/// the stream flags that are set includes AUDCLNT_STREAMFLAGS_EVENTCALLBACK. For such a stream, the associated application must
			/// also obtain a handle by making a call to IAudioClient::SetEventHandle. When it is time to retire the stream, the audio
			/// engine can then use the handle to release the stream objects. Failure to call <c>IAudioClient::SetEventHandle</c> before
			/// releasing the stream objects can cause a delay of several seconds (a time-out period) while the audio engine waits for an
			/// available handle. After the time-out period expires, the audio engine then releases the stream objects.
			/// </para>
			/// <para>
			/// Whether an attempt to create an exclusive-mode stream succeeds depends on several factors, including the availability of the
			/// device and the user-controlled settings that govern exclusive-mode operation of the device. For more information, see
			/// Exclusive-Mode Streams.
			/// </para>
			/// <para>
			/// An <c>IAudioClient</c> object supports exactly one connection to the audio engine or audio hardware. This connection lasts
			/// for the lifetime of the <c>IAudioClient</c> object.
			/// </para>
			/// <para>The client should call the following methods only after calling <c>Initialize</c>:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetBufferSize</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetCurrentPadding</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetService</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetStreamLatency</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Reset</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::SetEventHandle</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Start</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Stop</term>
			/// </item>
			/// </list>
			/// <para>The following methods do not require that <c>Initialize</c> be called first:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetDevicePeriod</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetMixFormat</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::IsFormatSupported</term>
			/// </item>
			/// </list>
			/// <para>These methods can be called any time after activating the <c>IAudioClient</c> interface.</para>
			/// <para>
			/// Before calling <c>Initialize</c> to set up a shared-mode or exclusive-mode connection, the client can call the
			/// IAudioClient::IsFormatSupported method to discover whether the audio engine or audio endpoint device supports a particular
			/// format in that mode. Before opening a shared-mode connection, the client can obtain the audio engine's mix format by calling
			/// the IAudioClient::GetMixFormat method.
			/// </para>
			/// <para>
			/// The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from
			/// occurring in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client
			/// thread periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a
			/// capture endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the
			/// buffer. In either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough
			/// to accommodate the longer of the two periods without allowing glitches to occur.
			/// </para>
			/// <para>
			/// The client specifies a buffer size through the hnsBufferDuration parameter. The client is responsible for requesting a
			/// buffer that is large enough to ensure that glitches cannot occur between the periodic processing passes that it performs on
			/// the buffer. Similarly, the <c>Initialize</c> method ensures that the buffer is never smaller than the minimum buffer size
			/// needed to ensure that glitches do not occur between the periodic processing passes that the engine thread performs on the
			/// buffer. If the client requests a buffer size that is smaller than the audio engine's minimum required buffer size, the
			/// method sets the buffer size to this minimum buffer size rather than to the buffer size requested by the client.
			/// </para>
			/// <para>
			/// If the client requests a buffer size (through the hnsBufferDuration parameter) that is not an integral number of audio
			/// frames, the method rounds up the requested buffer size to the next integral number of frames.
			/// </para>
			/// <para>
			/// Following the <c>Initialize</c> call, the client should call the IAudioClient::GetBufferSize method to get the precise size
			/// of the endpoint buffer. During each processing pass, the client will need the actual buffer size to calculate how much data
			/// to transfer to or from the buffer. The client calls the IAudioClient::GetCurrentPadding method to determine how much of the
			/// data in the buffer is currently available for processing.
			/// </para>
			/// <para>
			/// To achieve the minimum stream latency between the client application and audio endpoint device, the client thread should run
			/// at the same period as the audio engine thread. The period of the engine thread is fixed and cannot be controlled by the
			/// client. Making the client's period smaller than the engine's period unnecessarily increases the client thread's load on the
			/// processor without improving latency or decreasing the buffer size. To determine the period of the engine thread, the client
			/// can call the IAudioClient::GetDevicePeriod method. To set the buffer to the minimum size required by the engine thread, the
			/// client should call <c>Initialize</c> with the hnsBufferDuration parameter set to 0. Following the <c>Initialize</c> call,
			/// the client can get the size of the resulting buffer by calling <c>IAudioClient::GetBufferSize</c>.
			/// </para>
			/// <para>
			/// A client has the option of requesting a buffer size that is larger than what is strictly necessary to make timing glitches
			/// rare or nonexistent. Increasing the buffer size does not necessarily increase the stream latency. For a rendering stream,
			/// the latency through the buffer is determined solely by the separation between the client's write pointer and the engine's
			/// read pointer. For a capture stream, the latency through the buffer is determined solely by the separation between the
			/// engine's write pointer and the client's read pointer.
			/// </para>
			/// <para>
			/// The loopback flag (AUDCLNT_STREAMFLAGS_LOOPBACK) enables audio loopback. A client can enable audio loopback only on a
			/// rendering endpoint with a shared-mode stream. Audio loopback is provided primarily to support acoustic echo cancellation (AEC).
			/// </para>
			/// <para>
			/// An AEC client requires both a rendering endpoint and the ability to capture the output stream from the audio engine. The
			/// engine's output stream is the global mix that the audio device plays through the speakers. If audio loopback is enabled, a
			/// client can open a capture buffer for the global audio mix by calling the IAudioClient::GetService method to obtain an
			/// IAudioCaptureClient interface on the rendering stream object. If audio loopback is not enabled, then an attempt to open a
			/// capture buffer on a rendering stream will fail. The loopback data in the capture buffer is in the device format, which the
			/// client can obtain by querying the device's PKEY_AudioEngine_DeviceFormat property.
			/// </para>
			/// <para>
			/// On Windows versions prior to Windows 10, a pull-mode capture client will not receive any events when a stream is initialized
			/// with event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) and is loopback-enabled (AUDCLNT_STREAMFLAGS_LOOPBACK). If
			/// the stream is opened with this configuration, the <c>Initialize</c> call succeeds, but relevant events are not raised to
			/// notify the capture client each time a buffer becomes ready for processing. To work around this, initialize a render stream
			/// in event-driven mode. Each time the client receives an event for the render stream, it must signal the capture client to run
			/// the capture thread that reads the next set of samples from the capture endpoint buffer. As of Windows 10 the relevant event
			/// handles are now set for loopback-enabled streams that are active.
			/// </para>
			/// <para>
			/// Note that all streams must be opened in share mode because exclusive-mode streams cannot operate in loopback mode. For more
			/// information about audio loopback, see Loopback Recording.
			/// </para>
			/// <para>
			/// The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag indicates that processing of the audio buffer by the client will be event driven.
			/// WASAPI supports event-driven buffering to enable low-latency processing of both shared-mode and exclusive-mode streams.
			/// </para>
			/// <para>
			/// The initial release of Windows Vista supports event-driven buffering (that is, the use of the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag) for rendering streams only.
			/// </para>
			/// <para>
			/// In the initial release of Windows Vista, for capture streams, the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is supported only
			/// in shared mode. Setting this flag has no effect for exclusive-mode capture streams. That is, although the application
			/// specifies this flag in exclusive mode through the <c>Initialize</c> call, the application will not receive any events that
			/// are usually required to capture the audio stream. In the Windows Vista Service Pack 1 release, this flag is functional in
			/// shared-mode and exclusive mode; an application can set this flag to enable event-buffering for capture streams. For more
			/// information about capturing an audio stream, see Capturing a Stream.
			/// </para>
			/// <para>
			/// To enable event-driven buffering, the client must provide an event handle to the system. Following the <c>Initialize</c>
			/// call and before calling the IAudioClient::Start method to start the stream, the client must call the
			/// IAudioClient::SetEventHandle method to set the event handle. While the stream is running, the system periodically signals
			/// the event to indicate to the client that audio data is available for processing. Between processing passes, the client
			/// thread waits on the event handle by calling a synchronization function such as <c>WaitForSingleObject</c>. For more
			/// information about synchronization functions, see the Windows SDK documentation.
			/// </para>
			/// <para>
			/// For a shared-mode stream that uses event-driven buffering, the caller must set both hnsPeriodicity and hnsBufferDuration to
			/// 0. The <c>Initialize</c> method determines how large a buffer to allocate based on the scheduling period of the audio
			/// engine. Although the client's buffer processing thread is event driven, the basic buffer management process, as described
			/// previously, is unaltered. Each time the thread awakens, it should call IAudioClient::GetCurrentPadding to determine how much
			/// data to write to a rendering buffer or read from a capture buffer. In contrast to the two buffers that the <c>Initialize</c>
			/// method allocates for an exclusive-mode stream that uses event-driven buffering, a shared-mode stream requires a single buffer.
			/// </para>
			/// <para>
			/// For an exclusive-mode stream that uses event-driven buffering, the caller must specify nonzero values for hnsPeriodicity and
			/// hnsBufferDuration, and the values of these two parameters must be equal. The <c>Initialize</c> method allocates two buffers
			/// for the stream. Each buffer is equal in duration to the value of the hnsBufferDuration parameter. Following the
			/// <c>Initialize</c> call for a rendering stream, the caller should fill the first of the two buffers before starting the
			/// stream. For a capture stream, the buffers are initially empty, and the caller should assume that each buffer remains empty
			/// until the event for that buffer is signaled. While the stream is running, the system alternately sends one buffer or the
			/// other to the client—this form of double buffering is referred to as "ping-ponging". Each time the client receives a buffer
			/// from the system (which the system indicates by signaling the event), the client must process the entire buffer. For example,
			/// if the client requests a packet size from the IAudioRenderClient::GetBuffer method that does not match the buffer size, the
			/// method fails. Calls to the <c>IAudioClient::GetCurrentPadding</c> method are unnecessary because the packet size must always
			/// equal the buffer size. In contrast to the buffering modes discussed previously, the latency for an event-driven,
			/// exclusive-mode stream depends directly on the buffer size.
			/// </para>
			/// <para>
			/// As explained in Audio Sessions, the default behavior for a session that contains rendering streams is that its volume and
			/// mute settings persist across system restarts. The AUDCLNT_STREAMFLAGS_NOPERSIST flag overrides the default behavior and
			/// makes the settings nonpersistent. This flag has no effect on sessions that contain capture streams—the settings for those
			/// sessions are never persistent. In addition, the settings for a session that contains a loopback stream (a stream that is
			/// initialized with the AUDCLNT_STREAMFLAGS_LOOPBACK flag) are not persistent.
			/// </para>
			/// <para>
			/// Only a session that connects to a rendering endpoint device can have persistent volume and mute settings. The first stream
			/// to be added to the session determines whether the session's settings are persistent. Thus, if the
			/// AUDCLNT_STREAMFLAGS_NOPERSIST or AUDCLNT_STREAMFLAGS_LOOPBACK flag is set during initialization of the first stream, the
			/// session's settings are not persistent. Otherwise, they are persistent. Their persistence is unaffected by additional streams
			/// that might be subsequently added or removed during the lifetime of the session object.
			/// </para>
			/// <para>
			/// After a call to <c>Initialize</c> has successfully initialized an <c>IAudioClient</c> interface instance, a subsequent
			/// <c>Initialize</c> call to initialize the same interface instance will fail and return error code E_ALREADY_INITIALIZED.
			/// </para>
			/// <para>
			/// If the initial call to <c>Initialize</c> fails, subsequent <c>Initialize</c> calls might fail and return error code
			/// E_ALREADY_INITIALIZED, even though the interface has not been initialized. If this occurs, release the <c>IAudioClient</c>
			/// interface and obtain a new <c>IAudioClient</c> interface from the MMDevice API before calling <c>Initialize</c> again.
			/// </para>
			/// <para>For code examples that call the <c>Initialize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// <item>
			/// <term>Exclusive-Mode Streams</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 7, <c>Initialize</c> can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render or a capture device.
			/// This indicates that the buffer size, specified by the caller in the hnsBufferDuration parameter, is not aligned. This error
			/// code is returned only if the caller requested an exclusive-mode stream (AUDCLNT_SHAREMODE_EXCLUSIVE) and event-driven
			/// buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).
			/// </para>
			/// <para>
			/// If <c>Initialize</c> returns AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, the caller must call <c>Initialize</c> again and specify the
			/// aligned buffer size. Use the following steps:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Call IAudioClient::GetBufferSize and receive the next-highest-aligned buffer size (in frames).</term>
			/// </item>
			/// <item>
			/// <term>Call <c>IAudioClient::Release</c> to release the audio client used in the previous call that returned AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.</term>
			/// </item>
			/// <item>
			/// <term>
			/// Calculate the aligned buffer size in 100-nansecond units (hns). The buffer size is . In this formula, is the buffer size
			/// retrieved by GetBufferSize.
			/// </term>
			/// </item>
			/// <item>
			/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient to create a new audio client.</term>
			/// </item>
			/// <item>
			/// <term>Call <c>Initialize</c> again on the created audio client and specify the new buffer size and periodicity.</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
			/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must specify
			/// the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to <c>IAudioClient::Initialize</c>.
			/// </para>
			/// <para>Examples</para>
			/// <para>The following example code shows how to respond to the <c>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</c> return code.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize HRESULT Initialize(
			// AUDCLNT_SHAREMODE ShareMode, DWORD StreamFlags, REFERENCE_TIME hnsBufferDuration, REFERENCE_TIME hnsPeriodicity, const
			// WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid );
			[PreserveSig]
			HRESULT Initialize([In] AUDCLNT_SHAREMODE ShareMode, AUDCLNT_STREAMFLAGS StreamFlags, long hnsBufferDuration, long hnsPeriodicity, [In] IntPtr pFormat, [In, Optional] in Guid AudioSessionGuid);

			/// <summary>The <c>GetBufferSize</c> method retrieves the size (maximum capacity) of the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the number of audio frames that the buffer can hold.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the length of the endpoint buffer shared between the client application and the audio engine. The
			/// length is expressed as the number of audio frames the buffer can hold. The size in bytes of an audio frame is calculated as
			/// the number of channels in the stream multiplied by the sample size per channel. For example, the frame size is four bytes
			/// for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// The IAudioClient::Initialize method allocates the buffer. The client specifies the buffer length in the hnsBufferDuration
			/// parameter value that it passes to the <c>Initialize</c> method. For rendering clients, the buffer length determines the
			/// maximum amount of rendering data that the application can write to the endpoint buffer during a single processing pass. For
			/// capture clients, the buffer length determines the maximum amount of capture data that the audio engine can read from the
			/// endpoint buffer during a single processing pass. The client should always call <c>GetBufferSize</c> after calling
			/// <c>Initialize</c> to determine the actual size of the allocated buffer, which might differ from the requested size.
			/// </para>
			/// <para>
			/// Rendering clients can use this value to calculate the largest rendering buffer size that can be requested from
			/// IAudioRenderClient::GetBuffer during each processing pass.
			/// </para>
			/// <para>For code examples that call the <c>GetBufferSize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getbuffersize HRESULT
			// GetBufferSize( UINT32 *pNumBufferFrames );
			uint GetBufferSize();

			/// <summary>
			/// The <c>GetStreamLatency</c> method retrieves the maximum latency for the current stream and can be called any time after the
			/// stream has been initialized.
			/// </summary>
			/// <returns>
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value representing the latency. The time is
			/// expressed in 100-nanosecond units. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the maximum latency for the current stream. The value will not change for the lifetime of the
			/// IAudioClient object.
			/// </para>
			/// <para>
			/// Rendering clients can use this latency value to compute the minimum amount of data that they can write during any single
			/// processing pass. To write less than this minimum is to risk introducing glitches into the audio stream. For more
			/// information, see IAudioRenderClient::GetBuffer.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getstreamlatency HRESULT
			// GetStreamLatency( REFERENCE_TIME *phnsLatency );
			long GetStreamLatency();

			/// <summary>The <c>GetCurrentPadding</c> method retrieves the number of frames of padding in the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the frame count (the number of audio frames of padding in
			/// the buffer).
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves a padding value that indicates the amount of valid, unread data that the endpoint buffer currently
			/// contains. A rendering application can use the padding value to determine how much new data it can safely write to the
			/// endpoint buffer without overwriting previously written data that the audio engine has not yet read from the buffer. A
			/// capture application can use the padding value to determine how much new data it can safely read from the endpoint buffer
			/// without reading invalid data from a region of the buffer to which the audio engine has not yet written valid data.
			/// </para>
			/// <para>
			/// The padding value is expressed as a number of audio frames. The size of an audio frame is specified by the
			/// <c>nBlockAlign</c> member of the WAVEFORMATEX (or WAVEFORMATEXTENSIBLE) structure that the client passed to the
			/// IAudioClient::Initialize method. The size in bytes of an audio frame equals the number of channels in the stream multiplied
			/// by the sample size per channel. For example, the frame size is four bytes for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// For a shared-mode rendering stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of audio
			/// frames that are queued up to play in the endpoint buffer. Before writing to the endpoint buffer, the client can calculate
			/// the amount of available space in the buffer by subtracting the padding value from the buffer length. To ensure that a
			/// subsequent call to the IAudioRenderClient::GetBuffer method succeeds, the client should request a packet length that does
			/// not exceed the available space in the buffer. To obtain the buffer length, call the IAudioClient::GetBufferSize method.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of frames of
			/// capture data that are available in the next packet in the endpoint buffer. At a particular moment, zero, one, or more
			/// packets of capture data might be ready for the client to read from the buffer. If no packets are currently available, the
			/// method reports a padding value of 0. Following the <c>GetCurrentPadding</c> call, an IAudioCaptureClient::GetBuffer method
			/// call will retrieve a packet whose length exactly equals the padding value reported by <c>GetCurrentPadding</c>. Each call to
			/// GetBuffer retrieves a whole packet. A packet always contains an integral number of audio frames.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, calling <c>GetCurrentPadding</c> is equivalent to calling the
			/// IAudioCaptureClient::GetNextPacketSize method. That is, the padding value reported by <c>GetCurrentPadding</c> is equal to
			/// the packet length reported by <c>GetNextPacketSize</c>.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag, the
			/// client typically has no use for the padding value reported by <c>GetCurrentPadding</c>. Instead, the client accesses an
			/// entire buffer during each processing pass. Each time a buffer becomes available for processing, the audio engine notifies
			/// the client by signaling the client's event handle. For more information about this flag, see IAudioClient::Initialize.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was not initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag,
			/// the client can use the padding value obtained from <c>GetCurrentPadding</c> in a way that is similar to that described
			/// previously for a shared-mode stream. The details are as follows.
			/// </para>
			/// <para>
			/// First, for an exclusive-mode rendering stream, the padding value specifies the number of audio frames that are queued up to
			/// play in the endpoint buffer. As before, the client can calculate the amount of available space in the buffer by subtracting
			/// the padding value from the buffer length.
			/// </para>
			/// <para>
			/// Second, for an exclusive-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the current
			/// length of the next packet. However, this padding value is a snapshot of the packet length, which might increase before the
			/// client calls the IAudioCaptureClient::GetBuffer method. Thus, the length of the packet retrieved by <c>GetBuffer</c> is at
			/// least as large as, but might be larger than, the padding value reported by the <c>GetCurrentPadding</c> call that preceded
			/// the <c>GetBuffer</c> call. In contrast, for a shared-mode capture stream, the length of the packet obtained from
			/// <c>GetBuffer</c> always equals the padding value reported by the preceding <c>GetCurrentPadding</c> call.
			/// </para>
			/// <para>For a code example that calls the <c>GetCurrentPadding</c> method, see Rendering a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getcurrentpadding HRESULT
			// GetCurrentPadding( UINT32 *pNumPaddingFrames );
			uint GetCurrentPadding();

			/// <summary>
			/// The <c>IsFormatSupported</c> method indicates whether the audio endpoint device supports a particular stream format.
			/// </summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the stream format. Through this parameter, the client indicates whether it wants to use the specified
			/// format in exclusive mode or shared mode. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="pFormat">
			/// Pointer to the specified stream format. This parameter points to a caller-allocated format descriptor of type
			/// <c>WAVEFORMATEX</c> or <c>WAVEFORMATEXTENSIBLE</c>. The client writes a format description to this structure before calling
			/// this method. For information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </param>
			/// <param name="ppClosestMatch">
			/// Pointer to a pointer variable into which the method writes the address of a <c>WAVEFORMATEX</c> or
			/// <c>WAVEFORMATEXTENSIBLE</c> structure. This structure specifies the supported format that is closest to the format that the
			/// client specified through the pFormat parameter. For shared mode (that is, if the ShareMode parameter is
			/// AUDCLNT_SHAREMODE_SHARED), set ppClosestMatch to point to a valid, non- <c>NULL</c> pointer variable. For exclusive mode,
			/// set ppClosestMatch to <c>NULL</c>. The method allocates the storage for the structure. The caller is responsible for freeing
			/// the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the <c>IsFormatSupported</c> call
			/// fails and ppClosestMatch is non- <c>NULL</c>, the method sets *ppClosestMatch to <c>NULL</c>. For information about
			/// <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>S_OK</term>
			/// <term>Succeeded and the audio endpoint device supports the specified stream format.</term>
			/// </item>
			/// <item>
			/// <term>S_FALSE</term>
			/// <term>Succeeded with a closest match to the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>Succeeded but the specified format is not supported in exclusive mode.</term>
			/// </item>
			/// </list>
			/// <para>If the operation fails, possible return codes include, but are not limited to, the values shown in the following table.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL, or ppClosestMatch is NULL and ShareMode is AUDCLNT_SHAREMODE_SHARED.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>Parameter ShareMode is a value other than AUDCLNT_SHAREMODE_SHARED or AUDCLNT_SHAREMODE_EXCLUSIVE.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method provides a way for a client to determine, before calling IAudioClient::Initialize, whether the audio engine
			/// supports a particular stream format.
			/// </para>
			/// <para>
			/// For exclusive mode, <c>IsFormatSupported</c> returns S_OK if the audio endpoint device supports the caller-specified format,
			/// or it returns AUDCLNT_E_UNSUPPORTED_FORMAT if the device does not support the format. The ppClosestMatch parameter can be
			/// <c>NULL</c>. If it is not <c>NULL</c>, the method writes <c>NULL</c> to *ppClosestMatch.
			/// </para>
			/// <para>
			/// For shared mode, if the audio engine supports the caller-specified format, <c>IsFormatSupported</c> sets
			/// <c>*ppClosestMatch</c> to <c>NULL</c> and returns S_OK. If the audio engine does not support the caller-specified format but
			/// does support a similar format, the method retrieves the similar format through the ppClosestMatch parameter and returns
			/// S_FALSE. If the audio engine does not support the caller-specified format or any similar format, the method sets
			/// *ppClosestMatch to <c>NULL</c> and returns AUDCLNT_E_UNSUPPORTED_FORMAT.
			/// </para>
			/// <para>
			/// In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the
			/// IAudioClient::GetMixFormat method. In addition, the audio engine might support similar formats that have the same sample
			/// rate and number of channels as the mix format but differ in the representation of audio sample values. The audio engine
			/// represents sample values internally as floating-point numbers, but if the caller-specified format represents sample values
			/// as integers, the audio engine typically can convert between the integer sample values and its internal floating-point representation.
			/// </para>
			/// <para>
			/// The audio engine might be able to support an even wider range of shared-mode formats if the installation package for the
			/// audio device includes a local effects (LFX) audio processing object (APO) that can handle format conversions. An LFX APO is
			/// a software module that performs device-specific processing of an audio stream. The audio graph builder in the Windows audio
			/// service inserts the LFX APO into the stream between each client and the audio engine. When a client calls the
			/// <c>IsFormatSupported</c> method and the method determines that an LFX APO is installed for use with the device, the method
			/// directs the query to the LFX APO, which indicates whether it supports the caller-specified format.
			/// </para>
			/// <para>
			/// For example, a particular LFX APO might accept a 6-channel surround sound stream from a client and convert the stream to a
			/// stereo format that can be played through headphones. Typically, an LFX APO supports only client formats with sample rates
			/// that match the sample rate of the mix format.
			/// </para>
			/// <para>
			/// For more information about APOs, see the white papers titled "Custom Audio Effects in Windows Vista" and "Reusing the
			/// Windows Vista Audio System Effects" at the Audio Device Technologies for Windows website. For more information about the
			/// <c>IsFormatSupported</c> method, see Device Formats.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-isformatsupported HRESULT
			// IsFormatSupported( AUDCLNT_SHAREMODE ShareMode, const WAVEFORMATEX *pFormat, WAVEFORMATEX **ppClosestMatch );
			[PreserveSig]
			HRESULT IsFormatSupported([In] AUDCLNT_SHAREMODE ShareMode, [In] IntPtr pFormat, out SafeCoTaskMemHandle ppClosestMatch);

			/// <summary>
			/// The <c>GetMixFormat</c> method retrieves the stream format that the audio engine uses for its internal processing of
			/// shared-mode streams.
			/// </summary>
			/// <param name="ppDeviceFormat">
			/// Pointer to a pointer variable into which the method writes the address of the mix format. This parameter must be a valid,
			/// non- <c>NULL</c> pointer to a pointer variable. The method writes the address of a <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>) structure to this variable. The method allocates the storage for the structure. The caller is
			/// responsible for freeing the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the
			/// <c>GetMixFormat</c> call fails, *ppDeviceFormat is <c>NULL</c>. For information about <c>WAVEFORMATEX</c>,
			/// <c>WAVEFORMATEXTENSIBLE</c>, and <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter ppDeviceFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The client can call this method before calling the IAudioClient::Initialize method. When creating a shared-mode stream for
			/// an audio endpoint device, the <c>Initialize</c> method always accepts the stream format obtained from a <c>GetMixFormat</c>
			/// call on the same device.
			/// </para>
			/// <para>
			/// The mix format is the format that the audio engine uses internally for digital processing of shared-mode streams. This
			/// format is not necessarily a format that the audio endpoint device supports. Thus, the caller might not succeed in creating
			/// an exclusive-mode stream with a format obtained by calling <c>GetMixFormat</c>.
			/// </para>
			/// <para>
			/// For example, to facilitate digital audio processing, the audio engine might use a mix format that represents samples as
			/// floating-point values. If the device supports only integer PCM samples, then the engine converts the samples to or from
			/// integer PCM values at the connection between the device and the engine. However, to avoid resampling, the engine might use a
			/// mix format with a sample rate that the device supports.
			/// </para>
			/// <para>
			/// To determine whether the <c>Initialize</c> method can create a shared-mode or exclusive-mode stream with a particular
			/// format, call the IAudioClient::IsFormatSupported method.
			/// </para>
			/// <para>
			/// By itself, a <c>WAVEFORMATEX</c> structure cannot specify the mapping of channels to speaker positions. In addition,
			/// although <c>WAVEFORMATEX</c> specifies the size of the container for each audio sample, it cannot specify the number of bits
			/// of precision in a sample (for example, 20 bits of precision in a 24-bit container). However, the <c>WAVEFORMATEXTENSIBLE</c>
			/// structure can specify both the mapping of channels to speakers and the number of bits of precision in each sample. For this
			/// reason, the <c>GetMixFormat</c> method retrieves a format descriptor that is in the form of a <c>WAVEFORMATEXTENSIBLE</c>
			/// structure instead of a standalone <c>WAVEFORMATEX</c> structure. Through the ppDeviceFormat parameter, the method outputs a
			/// pointer to the <c>WAVEFORMATEX</c> structure that is embedded at the start of this <c>WAVEFORMATEXTENSIBLE</c> structure.
			/// For more information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </para>
			/// <para>
			/// For more information about the <c>GetMixFormat</c> method, see Device Formats. For code examples that call
			/// <c>GetMixFormat</c>, see the following topics:
			/// </para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getmixformat HRESULT GetMixFormat(
			// WAVEFORMATEX **ppDeviceFormat );
			[PreserveSig]
			HRESULT GetMixFormat(out SafeCoTaskMemHandle ppDeviceFormat);

			/// <summary>
			/// The <c>GetDevicePeriod</c> method retrieves the length of the periodic interval separating successive processing passes by
			/// the audio engine on the data in the endpoint buffer.
			/// </summary>
			/// <param name="phnsDefaultDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the default interval between
			/// periodic processing passes by the audio engine. The time is expressed in 100-nanosecond units. For information about
			/// <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </param>
			/// <param name="phnsMinimumDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the minimum interval between
			/// periodic processing passes by the audio endpoint device. The time is expressed in 100-nanosecond units.
			/// </param>
			/// <remarks>
			/// <para>The client can call this method before calling the IAudioClient::Initialize method.</para>
			/// <para>
			/// The phnsDefaultDevicePeriod parameter specifies the default scheduling period for a shared-mode stream. The
			/// phnsMinimumDevicePeriod parameter specifies the minimum scheduling period for an exclusive-mode stream.
			/// </para>
			/// <para>
			/// At least one of the two parameters, phnsDefaultDevicePeriod and phnsMinimumDevicePeriod, must be non- <c>NULL</c> or the
			/// method returns immediately with error code E_POINTER. If both parameters are non- <c>NULL</c>, then the method outputs both
			/// the default and minimum periods.
			/// </para>
			/// <para>
			/// For a shared-mode stream, the audio engine periodically processes the data in the endpoint buffer, which the engine shares
			/// with the client application. The engine schedules itself to perform these processing passes at regular intervals.
			/// </para>
			/// <para>
			/// The period between processing passes by the audio engine is fixed for a particular audio endpoint device and represents the
			/// smallest processing quantum for the audio engine. This period plus the stream latency between the buffer and endpoint device
			/// represents the minimum possible latency that an audio application can achieve.
			/// </para>
			/// <para>
			/// The client has the option of scheduling its periodic processing thread to run at the same time interval as the audio engine.
			/// In this way, the client can achieve the smallest possible latency for a shared-mode stream. However, in an application for
			/// which latency is less important, the client can reduce the process-switching overhead on the CPU by scheduling its
			/// processing passes to occur less frequently. In this case, the endpoint buffer must be proportionally larger to compensate
			/// for the longer period between processing passes.
			/// </para>
			/// <para>
			/// The client determines the buffer size during its call to the IAudioClient::Initialize method. For a shared-mode stream, if
			/// the client passes this method an hnsBufferDuration parameter value of 0, the method assumes that the periods for the client
			/// and audio engine are guaranteed to be equal, and the method will allocate a buffer small enough to achieve the minimum
			/// possible latency. (In fact, any hnsBufferDuration value between 0 and the sum of the audio engine's period and device
			/// latency will have the same result.) Similarly, for an exclusive-mode stream, if the client sets hnsBufferDuration to 0, the
			/// method assumes that the period of the client is set to the minimum period of the audio endpoint device, and the method will
			/// allocate a buffer small enough to achieve the minimum possible latency.
			/// </para>
			/// <para>
			/// If the client chooses to run its periodic processing thread less often, at the cost of increased latency, it can do so as
			/// long as it creates an endpoint buffer during the IAudioClient::Initialize call that is sufficiently large.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getdeviceperiod HRESULT
			// GetDevicePeriod( REFERENCE_TIME *phnsDefaultDevicePeriod, REFERENCE_TIME *phnsMinimumDevicePeriod );
			void GetDevicePeriod([Out, Optional] out long phnsDefaultDevicePeriod, out long phnsMinimumDevicePeriod);

			/// <summary>The <c>Start</c> method starts the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Start</c> is a control method that the client calls to start the audio stream. Starting the stream causes the
			/// IAudioClient object to begin streaming data between the endpoint buffer and the audio engine. It also causes the stream's
			/// audio clock to resume counting from its current position.
			/// </para>
			/// <para>
			/// The first time this method is called following initialization of the stream, the IAudioClient object's stream position
			/// counter begins at 0. Otherwise, the clock resumes from its position at the time that the stream was last stopped. Resetting
			/// the stream forces the stream position back to 0.
			/// </para>
			/// <para>
			/// To avoid start-up glitches with rendering streams, clients should not call <c>Start</c> until the audio engine has been
			/// initially loaded with data by calling the IAudioRenderClient::GetBuffer and IAudioRenderClient::ReleaseBuffer methods on the
			/// rendering interface.
			/// </para>
			/// <para>For code examples that call the <c>Start</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-start HRESULT Start();
			void Start();

			/// <summary>The <c>Stop</c> method stops the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Stop</c> is a control method that stops a running audio stream. This method stops data from streaming through the
			/// client's connection with the audio engine. Stopping the stream freezes the stream's audio clock at its current stream
			/// position. A subsequent call to IAudioClient::Start causes the stream to resume running from that position. If necessary, the
			/// client can call the IAudioClient::Reset method to reset the position while the stream is stopped.
			/// </para>
			/// <para>For code examples that call the <c>Stop</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-stop HRESULT Stop();
			void Stop();

			/// <summary>The <c>Reset</c> method resets the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Reset</c> is a control method that the client calls to reset a stopped audio stream. Resetting the stream flushes all
			/// pending data and resets the audio clock stream position to 0. This method fails if it is called on a stream that is not stopped.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-reset HRESULT Reset();
			void Reset();

			/// <summary>
			/// The <c>SetEventHandle</c> method sets the event handle that the system signals when an audio buffer is ready to be processed
			/// by the client.
			/// </summary>
			/// <param name="eventHandle">The event handle.</param>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// During stream initialization, the client can, as an option, enable event-driven buffering. To do so, the client calls the
			/// IAudioClient::Initialize method with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag set. After enabling event-driven buffering,
			/// and before calling the IAudioClient::Start method to start the stream, the client must call <c>SetEventHandle</c> to
			/// register the event handle that the system will signal each time a buffer becomes ready to be processed by the client.
			/// </para>
			/// <para>The event handle should be in the nonsignaled state at the time that the client calls the Start method.</para>
			/// <para>
			/// If the client has enabled event-driven buffering of a stream, but the client calls the Start method for that stream without
			/// first calling <c>SetEventHandle</c>, the <c>Start</c> call will fail and return an error code.
			/// </para>
			/// <para>
			/// If the client does not enable event-driven buffering of a stream but attempts to set an event handle for the stream by
			/// calling <c>SetEventHandle</c>, the call will fail and return an error code.
			/// </para>
			/// <para>For a code example that calls the <c>SetEventHandle</c> method, see Exclusive-Mode Streams.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-seteventhandle HRESULT
			// SetEventHandle( HANDLE eventHandle );
			void SetEventHandle(IntPtr eventHandle);

			/// <summary>The <c>GetService</c> method accesses additional services from the audio client object.</summary>
			/// <param name="riid">
			/// <para>The interface ID for the requested service. The client should set this parameter to one of the following REFIID values:</para>
			/// <para>IID_IAudioCaptureClient</para>
			/// <para>IID_IAudioClock</para>
			/// <para>IID_IAudioRenderClient</para>
			/// <para>IID_IAudioSessionControl</para>
			/// <para>IID_IAudioStreamVolume</para>
			/// <para>IID_IChannelAudioVolume</para>
			/// <para>IID_IMFTrustedOutput</para>
			/// <para>IID_ISimpleAudioVolume</para>
			/// <para>For more information, see Remarks.</para>
			/// </param>
			/// <returns>
			/// Pointer to a pointer variable into which the method writes the address of an instance of the requested interface. Through
			/// this method, the caller obtains a counted reference to the interface. The caller is responsible for releasing the interface,
			/// when it is no longer needed, by calling the interface's <c>Release</c> method. If the <c>GetService</c> call fails, *ppv is <c>NULL</c>.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>The <c>GetService</c> method supports the following service interfaces:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioCaptureClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioClock</term>
			/// </item>
			/// <item>
			/// <term>IAudioRenderClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioSessionControl</term>
			/// </item>
			/// <item>
			/// <term>IAudioStreamVolume</term>
			/// </item>
			/// <item>
			/// <term>IChannelAudioVolume</term>
			/// </item>
			/// <item>
			/// <term>IMFTrustedOutput</term>
			/// </item>
			/// <item>
			/// <term>ISimpleAudioVolume</term>
			/// </item>
			/// </list>
			/// <para>
			/// In Windows 7, a new service identifier, <c>IID_IMFTrustedOutput</c>, has been added that facilitates the use of output trust
			/// authority (OTA) objects. These objects can operate inside or outside the Media Foundation's protected media path (PMP) and
			/// send content outside the Media Foundation pipeline. If the caller is outside PMP, then the OTA may not operate in the PMP,
			/// and the protection settings are less robust. OTAs must implement the IMFTrustedOutput interface. By passing
			/// <c>IID_IMFTrustedOutput</c> in <c>GetService</c>, an application can retrieve a pointer to the object's
			/// <c>IMFTrustedOutput</c> interface. For more information about protected objects and <c>IMFTrustedOutput</c>, see "Protected
			/// Media Path" in the Media Foundation SDK documentation.
			/// </para>
			/// <para>For information about using trusted audio drivers in OTAs, see Protected User Mode Audio (PUMA).</para>
			/// <para>
			/// Note that activating IMFTrustedOutput through this mechanism works regardless of whether the caller is running in PMP.
			/// However, if the caller is not running in a protected process (that is, the caller is not within Media Foundation's PMP) then
			/// the audio OTA might not operate in the PMP and the protection settings are less robust.
			/// </para>
			/// <para>
			/// To obtain the interface ID for a service interface, use the <c>__uuidof</c> operator. For example, the interface ID of
			/// <c>IAudioCaptureClient</c> is defined as follows:
			/// </para>
			/// <para>For information about the <c>__uuidof</c> operator, see the Windows SDK documentation.</para>
			/// <para>
			/// To release the <c>IAudioClient</c> object and free all its associated resources, the client must release all references to
			/// any service objects that were created by calling <c>GetService</c>, in addition to calling <c>Release</c> on the
			/// <c>IAudioClient</c> interface itself. The client must release a service from the same thread that releases the
			/// <c>IAudioClient</c> object.
			/// </para>
			/// <para>
			/// The <c>IAudioSessionControl</c>, <c>IAudioStreamVolume</c>, <c>IChannelAudioVolume</c>, and <c>ISimpleAudioVolume</c>
			/// interfaces control and monitor aspects of audio sessions and shared-mode streams. These interfaces do not work with
			/// exclusive-mode streams.
			/// </para>
			/// <para>For code examples that call the <c>GetService</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getservice HRESULT GetService(
			// REFIID riid, void **ppv );
			[return: MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 0)]
			object GetService(in Guid riid);
		}

		/// <summary>
		/// The <c>IAudioClient2</c> interface is derived from the IAudioClient interface, with a set of additional methods that enable a
		/// Windows Audio Session API (WASAPI) audio client to do the following: opt in for offloading, query stream properties, and get
		/// information from the hardware that handles offloading.The audio client can be successful in creating an offloaded stream if the
		/// underlying endpoint supports the hardware audio engine, the endpoint has been enumerated and discovered by the audio system, and
		/// there are still offload pin instances available on the endpoint.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclient2
		[PInvokeData("audioclient.h", MSDNShortId = "9CE79CEB-115E-4802-A687-B2CB23E6A0E0")]
		[ComImport, Guid("726778CD-F60A-4eda-82DE-E47610CD78AA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClient2 : IAudioClient
		{
			/// <summary>The <c>Initialize</c> method initializes the audio stream.</summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the connection. Through this parameter, the client tells the audio engine whether it wants to share the
			/// audio endpoint device with other clients. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="StreamFlags">
			/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of
			/// the AUDCLNT_STREAMFLAGS_XXX Constants or the AUDCLNT_SESSIONFLAGS_XXX Constants.
			/// </param>
			/// <param name="hnsBufferDuration">
			/// The buffer capacity as a time value. This parameter is of type <c>REFERENCE_TIME</c> and is expressed in 100-nanosecond
			/// units. This parameter contains the buffer size that the caller requests for the buffer that the audio application will share
			/// with the audio engine (in shared mode) or with the endpoint device (in exclusive mode). If the call succeeds, the method
			/// allocates a buffer that is a least this large. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK
			/// documentation. For more information about buffering requirements, see Remarks.
			/// </param>
			/// <param name="hnsPeriodicity">
			/// The device period. This parameter can be nonzero only in exclusive mode. In shared mode, always set this parameter to 0. In
			/// exclusive mode, this parameter specifies the requested scheduling period for successive buffer accesses by the audio
			/// endpoint device. If the requested device period lies outside the range that is set by the device's minimum period and the
			/// system's maximum period, then the method clamps the period to that range. If this parameter is 0, the method sets the device
			/// period to its default value. To obtain the default device period, call the IAudioClient::GetDevicePeriod method. If the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK stream flag is set and AUDCLNT_SHAREMODE_EXCLUSIVE is set as the ShareMode, then
			/// hnsPeriodicity must be nonzero and equal to hnsBufferDuration.
			/// </param>
			/// <param name="pFormat">
			/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>). For more information, see Remarks.
			/// </param>
			/// <param name="AudioSessionGuid">
			/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs
			/// to. If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the
			/// GUID does not identify an existing session, the method opens a new session and adds the stream to that session. The stream
			/// remains a member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a
			/// pointer to a GUID_NULL value.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_ALREADY_INITIALIZED</term>
			/// <term>The IAudioClient object is already initialized.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_WRONG_ENDPOINT_TYPE</term>
			/// <term>The AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but the endpoint device is a capture device, not a rendering device.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</term>
			/// <term>
			/// The requested buffer size is not aligned. This code can be returned for a render or a capture device if the caller specified
			/// AUDCLNT_SHAREMODE_EXCLUSIVE and the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flags. The caller must call Initialize again with the
			/// aligned buffer size. For more information, see Remarks.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
			/// <term>
			/// Indicates that the buffer duration value requested by an exclusive-mode client is out of range. The requested duration value
			/// for pull mode must not be greater than 500 milliseconds; for push mode the duration value must not be greater than 2 seconds.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_CPUUSAGE_EXCEEDED</term>
			/// <term>
			/// Indicates that the process-pass duration exceeded the maximum CPU usage. The audio engine keeps track of CPU usage by
			/// maintaining the number of times the process-pass duration exceeds the maximum CPU usage. The maximum CPU usage is calculated
			/// as a percent of the engine's periodicity. The percentage value is the system's CPU throttle value (within the range of 10%
			/// and 90%). If this value is not found, then the default value of 40% is used to calculate the maximum CPU usage.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_IN_USE</term>
			/// <term>
			/// The endpoint device is already in use. Either the device is being used in exclusive mode, or the device is being used in
			/// shared mode and the caller asked to use the device in exclusive mode.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_ENDPOINT_CREATE_FAILED</term>
			/// <term>
			/// The method failed to create the audio endpoint for the render or the capture device. This can occur if the audio endpoint
			/// device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured, disabled, removed,
			/// or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_INVALID_DEVICE_PERIOD</term>
			/// <term>Indicates that the device period requested by an exclusive-mode client is greater than 500 milliseconds.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>The audio engine (shared mode) or audio endpoint device (exclusive mode) does not support the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED</term>
			/// <term>
			/// The caller is requesting exclusive-mode use of the endpoint device, but the user has disabled exclusive-mode use of the device.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL</term>
			/// <term>The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is set but parameters hnsBufferDuration and hnsPeriodicity are not equal.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>
			/// Parameter pFormat points to an invalid format description; or the AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but ShareMode is
			/// not equal to AUDCLNT_SHAREMODE_SHARED; or the AUDCLNT_STREAMFLAGS_CROSSPROCESS flag is set but ShareMode is equal to
			/// AUDCLNT_SHAREMODE_EXCLUSIVE. A prior call to SetClientProperties was made with an invalid category for audio/render streams.
			/// </term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// After activating an IAudioClient interface on an audio endpoint device, the client must successfully call <c>Initialize</c>
			/// once and only once to initialize the audio stream between the client and the device. The client can either connect directly
			/// to the audio hardware (exclusive mode) or indirectly through the audio engine (shared mode). In the <c>Initialize</c> call,
			/// the client specifies the audio data format, the buffer size, and audio session for the stream.
			/// </para>
			/// <para>
			/// <c>Note</c> In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from
			/// an MTA thread may result in undefined behavior.
			/// </para>
			/// <para>
			/// An attempt to create a shared-mode stream can succeed only if the audio device is already operating in shared mode or the
			/// device is currently unused. An attempt to create a shared-mode stream fails if the device is already operating in exclusive mode.
			/// </para>
			/// <para>
			/// If a stream is initialized to be event driven and in shared mode, ShareMode is set to AUDCLNT_SHAREMODE_SHARED and one of
			/// the stream flags that are set includes AUDCLNT_STREAMFLAGS_EVENTCALLBACK. For such a stream, the associated application must
			/// also obtain a handle by making a call to IAudioClient::SetEventHandle. When it is time to retire the stream, the audio
			/// engine can then use the handle to release the stream objects. Failure to call <c>IAudioClient::SetEventHandle</c> before
			/// releasing the stream objects can cause a delay of several seconds (a time-out period) while the audio engine waits for an
			/// available handle. After the time-out period expires, the audio engine then releases the stream objects.
			/// </para>
			/// <para>
			/// Whether an attempt to create an exclusive-mode stream succeeds depends on several factors, including the availability of the
			/// device and the user-controlled settings that govern exclusive-mode operation of the device. For more information, see
			/// Exclusive-Mode Streams.
			/// </para>
			/// <para>
			/// An <c>IAudioClient</c> object supports exactly one connection to the audio engine or audio hardware. This connection lasts
			/// for the lifetime of the <c>IAudioClient</c> object.
			/// </para>
			/// <para>The client should call the following methods only after calling <c>Initialize</c>:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetBufferSize</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetCurrentPadding</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetService</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetStreamLatency</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Reset</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::SetEventHandle</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Start</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Stop</term>
			/// </item>
			/// </list>
			/// <para>The following methods do not require that <c>Initialize</c> be called first:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetDevicePeriod</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetMixFormat</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::IsFormatSupported</term>
			/// </item>
			/// </list>
			/// <para>These methods can be called any time after activating the <c>IAudioClient</c> interface.</para>
			/// <para>
			/// Before calling <c>Initialize</c> to set up a shared-mode or exclusive-mode connection, the client can call the
			/// IAudioClient::IsFormatSupported method to discover whether the audio engine or audio endpoint device supports a particular
			/// format in that mode. Before opening a shared-mode connection, the client can obtain the audio engine's mix format by calling
			/// the IAudioClient::GetMixFormat method.
			/// </para>
			/// <para>
			/// The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from
			/// occurring in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client
			/// thread periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a
			/// capture endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the
			/// buffer. In either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough
			/// to accommodate the longer of the two periods without allowing glitches to occur.
			/// </para>
			/// <para>
			/// The client specifies a buffer size through the hnsBufferDuration parameter. The client is responsible for requesting a
			/// buffer that is large enough to ensure that glitches cannot occur between the periodic processing passes that it performs on
			/// the buffer. Similarly, the <c>Initialize</c> method ensures that the buffer is never smaller than the minimum buffer size
			/// needed to ensure that glitches do not occur between the periodic processing passes that the engine thread performs on the
			/// buffer. If the client requests a buffer size that is smaller than the audio engine's minimum required buffer size, the
			/// method sets the buffer size to this minimum buffer size rather than to the buffer size requested by the client.
			/// </para>
			/// <para>
			/// If the client requests a buffer size (through the hnsBufferDuration parameter) that is not an integral number of audio
			/// frames, the method rounds up the requested buffer size to the next integral number of frames.
			/// </para>
			/// <para>
			/// Following the <c>Initialize</c> call, the client should call the IAudioClient::GetBufferSize method to get the precise size
			/// of the endpoint buffer. During each processing pass, the client will need the actual buffer size to calculate how much data
			/// to transfer to or from the buffer. The client calls the IAudioClient::GetCurrentPadding method to determine how much of the
			/// data in the buffer is currently available for processing.
			/// </para>
			/// <para>
			/// To achieve the minimum stream latency between the client application and audio endpoint device, the client thread should run
			/// at the same period as the audio engine thread. The period of the engine thread is fixed and cannot be controlled by the
			/// client. Making the client's period smaller than the engine's period unnecessarily increases the client thread's load on the
			/// processor without improving latency or decreasing the buffer size. To determine the period of the engine thread, the client
			/// can call the IAudioClient::GetDevicePeriod method. To set the buffer to the minimum size required by the engine thread, the
			/// client should call <c>Initialize</c> with the hnsBufferDuration parameter set to 0. Following the <c>Initialize</c> call,
			/// the client can get the size of the resulting buffer by calling <c>IAudioClient::GetBufferSize</c>.
			/// </para>
			/// <para>
			/// A client has the option of requesting a buffer size that is larger than what is strictly necessary to make timing glitches
			/// rare or nonexistent. Increasing the buffer size does not necessarily increase the stream latency. For a rendering stream,
			/// the latency through the buffer is determined solely by the separation between the client's write pointer and the engine's
			/// read pointer. For a capture stream, the latency through the buffer is determined solely by the separation between the
			/// engine's write pointer and the client's read pointer.
			/// </para>
			/// <para>
			/// The loopback flag (AUDCLNT_STREAMFLAGS_LOOPBACK) enables audio loopback. A client can enable audio loopback only on a
			/// rendering endpoint with a shared-mode stream. Audio loopback is provided primarily to support acoustic echo cancellation (AEC).
			/// </para>
			/// <para>
			/// An AEC client requires both a rendering endpoint and the ability to capture the output stream from the audio engine. The
			/// engine's output stream is the global mix that the audio device plays through the speakers. If audio loopback is enabled, a
			/// client can open a capture buffer for the global audio mix by calling the IAudioClient::GetService method to obtain an
			/// IAudioCaptureClient interface on the rendering stream object. If audio loopback is not enabled, then an attempt to open a
			/// capture buffer on a rendering stream will fail. The loopback data in the capture buffer is in the device format, which the
			/// client can obtain by querying the device's PKEY_AudioEngine_DeviceFormat property.
			/// </para>
			/// <para>
			/// On Windows versions prior to Windows 10, a pull-mode capture client will not receive any events when a stream is initialized
			/// with event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) and is loopback-enabled (AUDCLNT_STREAMFLAGS_LOOPBACK). If
			/// the stream is opened with this configuration, the <c>Initialize</c> call succeeds, but relevant events are not raised to
			/// notify the capture client each time a buffer becomes ready for processing. To work around this, initialize a render stream
			/// in event-driven mode. Each time the client receives an event for the render stream, it must signal the capture client to run
			/// the capture thread that reads the next set of samples from the capture endpoint buffer. As of Windows 10 the relevant event
			/// handles are now set for loopback-enabled streams that are active.
			/// </para>
			/// <para>
			/// Note that all streams must be opened in share mode because exclusive-mode streams cannot operate in loopback mode. For more
			/// information about audio loopback, see Loopback Recording.
			/// </para>
			/// <para>
			/// The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag indicates that processing of the audio buffer by the client will be event driven.
			/// WASAPI supports event-driven buffering to enable low-latency processing of both shared-mode and exclusive-mode streams.
			/// </para>
			/// <para>
			/// The initial release of Windows Vista supports event-driven buffering (that is, the use of the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag) for rendering streams only.
			/// </para>
			/// <para>
			/// In the initial release of Windows Vista, for capture streams, the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is supported only
			/// in shared mode. Setting this flag has no effect for exclusive-mode capture streams. That is, although the application
			/// specifies this flag in exclusive mode through the <c>Initialize</c> call, the application will not receive any events that
			/// are usually required to capture the audio stream. In the Windows Vista Service Pack 1 release, this flag is functional in
			/// shared-mode and exclusive mode; an application can set this flag to enable event-buffering for capture streams. For more
			/// information about capturing an audio stream, see Capturing a Stream.
			/// </para>
			/// <para>
			/// To enable event-driven buffering, the client must provide an event handle to the system. Following the <c>Initialize</c>
			/// call and before calling the IAudioClient::Start method to start the stream, the client must call the
			/// IAudioClient::SetEventHandle method to set the event handle. While the stream is running, the system periodically signals
			/// the event to indicate to the client that audio data is available for processing. Between processing passes, the client
			/// thread waits on the event handle by calling a synchronization function such as <c>WaitForSingleObject</c>. For more
			/// information about synchronization functions, see the Windows SDK documentation.
			/// </para>
			/// <para>
			/// For a shared-mode stream that uses event-driven buffering, the caller must set both hnsPeriodicity and hnsBufferDuration to
			/// 0. The <c>Initialize</c> method determines how large a buffer to allocate based on the scheduling period of the audio
			/// engine. Although the client's buffer processing thread is event driven, the basic buffer management process, as described
			/// previously, is unaltered. Each time the thread awakens, it should call IAudioClient::GetCurrentPadding to determine how much
			/// data to write to a rendering buffer or read from a capture buffer. In contrast to the two buffers that the <c>Initialize</c>
			/// method allocates for an exclusive-mode stream that uses event-driven buffering, a shared-mode stream requires a single buffer.
			/// </para>
			/// <para>
			/// For an exclusive-mode stream that uses event-driven buffering, the caller must specify nonzero values for hnsPeriodicity and
			/// hnsBufferDuration, and the values of these two parameters must be equal. The <c>Initialize</c> method allocates two buffers
			/// for the stream. Each buffer is equal in duration to the value of the hnsBufferDuration parameter. Following the
			/// <c>Initialize</c> call for a rendering stream, the caller should fill the first of the two buffers before starting the
			/// stream. For a capture stream, the buffers are initially empty, and the caller should assume that each buffer remains empty
			/// until the event for that buffer is signaled. While the stream is running, the system alternately sends one buffer or the
			/// other to the client—this form of double buffering is referred to as "ping-ponging". Each time the client receives a buffer
			/// from the system (which the system indicates by signaling the event), the client must process the entire buffer. For example,
			/// if the client requests a packet size from the IAudioRenderClient::GetBuffer method that does not match the buffer size, the
			/// method fails. Calls to the <c>IAudioClient::GetCurrentPadding</c> method are unnecessary because the packet size must always
			/// equal the buffer size. In contrast to the buffering modes discussed previously, the latency for an event-driven,
			/// exclusive-mode stream depends directly on the buffer size.
			/// </para>
			/// <para>
			/// As explained in Audio Sessions, the default behavior for a session that contains rendering streams is that its volume and
			/// mute settings persist across system restarts. The AUDCLNT_STREAMFLAGS_NOPERSIST flag overrides the default behavior and
			/// makes the settings nonpersistent. This flag has no effect on sessions that contain capture streams—the settings for those
			/// sessions are never persistent. In addition, the settings for a session that contains a loopback stream (a stream that is
			/// initialized with the AUDCLNT_STREAMFLAGS_LOOPBACK flag) are not persistent.
			/// </para>
			/// <para>
			/// Only a session that connects to a rendering endpoint device can have persistent volume and mute settings. The first stream
			/// to be added to the session determines whether the session's settings are persistent. Thus, if the
			/// AUDCLNT_STREAMFLAGS_NOPERSIST or AUDCLNT_STREAMFLAGS_LOOPBACK flag is set during initialization of the first stream, the
			/// session's settings are not persistent. Otherwise, they are persistent. Their persistence is unaffected by additional streams
			/// that might be subsequently added or removed during the lifetime of the session object.
			/// </para>
			/// <para>
			/// After a call to <c>Initialize</c> has successfully initialized an <c>IAudioClient</c> interface instance, a subsequent
			/// <c>Initialize</c> call to initialize the same interface instance will fail and return error code E_ALREADY_INITIALIZED.
			/// </para>
			/// <para>
			/// If the initial call to <c>Initialize</c> fails, subsequent <c>Initialize</c> calls might fail and return error code
			/// E_ALREADY_INITIALIZED, even though the interface has not been initialized. If this occurs, release the <c>IAudioClient</c>
			/// interface and obtain a new <c>IAudioClient</c> interface from the MMDevice API before calling <c>Initialize</c> again.
			/// </para>
			/// <para>For code examples that call the <c>Initialize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// <item>
			/// <term>Exclusive-Mode Streams</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 7, <c>Initialize</c> can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render or a capture device.
			/// This indicates that the buffer size, specified by the caller in the hnsBufferDuration parameter, is not aligned. This error
			/// code is returned only if the caller requested an exclusive-mode stream (AUDCLNT_SHAREMODE_EXCLUSIVE) and event-driven
			/// buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).
			/// </para>
			/// <para>
			/// If <c>Initialize</c> returns AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, the caller must call <c>Initialize</c> again and specify the
			/// aligned buffer size. Use the following steps:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Call IAudioClient::GetBufferSize and receive the next-highest-aligned buffer size (in frames).</term>
			/// </item>
			/// <item>
			/// <term>Call <c>IAudioClient::Release</c> to release the audio client used in the previous call that returned AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.</term>
			/// </item>
			/// <item>
			/// <term>
			/// Calculate the aligned buffer size in 100-nansecond units (hns). The buffer size is . In this formula, is the buffer size
			/// retrieved by GetBufferSize.
			/// </term>
			/// </item>
			/// <item>
			/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient to create a new audio client.</term>
			/// </item>
			/// <item>
			/// <term>Call <c>Initialize</c> again on the created audio client and specify the new buffer size and periodicity.</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
			/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must specify
			/// the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to <c>IAudioClient::Initialize</c>.
			/// </para>
			/// <para>Examples</para>
			/// <para>The following example code shows how to respond to the <c>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</c> return code.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize HRESULT Initialize(
			// AUDCLNT_SHAREMODE ShareMode, DWORD StreamFlags, REFERENCE_TIME hnsBufferDuration, REFERENCE_TIME hnsPeriodicity, const
			// WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid );
			[PreserveSig]
			new HRESULT Initialize([In] AUDCLNT_SHAREMODE ShareMode, AUDCLNT_STREAMFLAGS StreamFlags, long hnsBufferDuration, long hnsPeriodicity, [In] IntPtr pFormat, [In, Optional] in Guid AudioSessionGuid);

			/// <summary>The <c>GetBufferSize</c> method retrieves the size (maximum capacity) of the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the number of audio frames that the buffer can hold.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the length of the endpoint buffer shared between the client application and the audio engine. The
			/// length is expressed as the number of audio frames the buffer can hold. The size in bytes of an audio frame is calculated as
			/// the number of channels in the stream multiplied by the sample size per channel. For example, the frame size is four bytes
			/// for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// The IAudioClient::Initialize method allocates the buffer. The client specifies the buffer length in the hnsBufferDuration
			/// parameter value that it passes to the <c>Initialize</c> method. For rendering clients, the buffer length determines the
			/// maximum amount of rendering data that the application can write to the endpoint buffer during a single processing pass. For
			/// capture clients, the buffer length determines the maximum amount of capture data that the audio engine can read from the
			/// endpoint buffer during a single processing pass. The client should always call <c>GetBufferSize</c> after calling
			/// <c>Initialize</c> to determine the actual size of the allocated buffer, which might differ from the requested size.
			/// </para>
			/// <para>
			/// Rendering clients can use this value to calculate the largest rendering buffer size that can be requested from
			/// IAudioRenderClient::GetBuffer during each processing pass.
			/// </para>
			/// <para>For code examples that call the <c>GetBufferSize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getbuffersize HRESULT
			// GetBufferSize( UINT32 *pNumBufferFrames );
			new uint GetBufferSize();

			/// <summary>
			/// The <c>GetStreamLatency</c> method retrieves the maximum latency for the current stream and can be called any time after the
			/// stream has been initialized.
			/// </summary>
			/// <returns>
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value representing the latency. The time is
			/// expressed in 100-nanosecond units. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the maximum latency for the current stream. The value will not change for the lifetime of the
			/// IAudioClient object.
			/// </para>
			/// <para>
			/// Rendering clients can use this latency value to compute the minimum amount of data that they can write during any single
			/// processing pass. To write less than this minimum is to risk introducing glitches into the audio stream. For more
			/// information, see IAudioRenderClient::GetBuffer.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getstreamlatency HRESULT
			// GetStreamLatency( REFERENCE_TIME *phnsLatency );
			new long GetStreamLatency();

			/// <summary>The <c>GetCurrentPadding</c> method retrieves the number of frames of padding in the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the frame count (the number of audio frames of padding in
			/// the buffer).
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves a padding value that indicates the amount of valid, unread data that the endpoint buffer currently
			/// contains. A rendering application can use the padding value to determine how much new data it can safely write to the
			/// endpoint buffer without overwriting previously written data that the audio engine has not yet read from the buffer. A
			/// capture application can use the padding value to determine how much new data it can safely read from the endpoint buffer
			/// without reading invalid data from a region of the buffer to which the audio engine has not yet written valid data.
			/// </para>
			/// <para>
			/// The padding value is expressed as a number of audio frames. The size of an audio frame is specified by the
			/// <c>nBlockAlign</c> member of the WAVEFORMATEX (or WAVEFORMATEXTENSIBLE) structure that the client passed to the
			/// IAudioClient::Initialize method. The size in bytes of an audio frame equals the number of channels in the stream multiplied
			/// by the sample size per channel. For example, the frame size is four bytes for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// For a shared-mode rendering stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of audio
			/// frames that are queued up to play in the endpoint buffer. Before writing to the endpoint buffer, the client can calculate
			/// the amount of available space in the buffer by subtracting the padding value from the buffer length. To ensure that a
			/// subsequent call to the IAudioRenderClient::GetBuffer method succeeds, the client should request a packet length that does
			/// not exceed the available space in the buffer. To obtain the buffer length, call the IAudioClient::GetBufferSize method.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of frames of
			/// capture data that are available in the next packet in the endpoint buffer. At a particular moment, zero, one, or more
			/// packets of capture data might be ready for the client to read from the buffer. If no packets are currently available, the
			/// method reports a padding value of 0. Following the <c>GetCurrentPadding</c> call, an IAudioCaptureClient::GetBuffer method
			/// call will retrieve a packet whose length exactly equals the padding value reported by <c>GetCurrentPadding</c>. Each call to
			/// GetBuffer retrieves a whole packet. A packet always contains an integral number of audio frames.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, calling <c>GetCurrentPadding</c> is equivalent to calling the
			/// IAudioCaptureClient::GetNextPacketSize method. That is, the padding value reported by <c>GetCurrentPadding</c> is equal to
			/// the packet length reported by <c>GetNextPacketSize</c>.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag, the
			/// client typically has no use for the padding value reported by <c>GetCurrentPadding</c>. Instead, the client accesses an
			/// entire buffer during each processing pass. Each time a buffer becomes available for processing, the audio engine notifies
			/// the client by signaling the client's event handle. For more information about this flag, see IAudioClient::Initialize.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was not initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag,
			/// the client can use the padding value obtained from <c>GetCurrentPadding</c> in a way that is similar to that described
			/// previously for a shared-mode stream. The details are as follows.
			/// </para>
			/// <para>
			/// First, for an exclusive-mode rendering stream, the padding value specifies the number of audio frames that are queued up to
			/// play in the endpoint buffer. As before, the client can calculate the amount of available space in the buffer by subtracting
			/// the padding value from the buffer length.
			/// </para>
			/// <para>
			/// Second, for an exclusive-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the current
			/// length of the next packet. However, this padding value is a snapshot of the packet length, which might increase before the
			/// client calls the IAudioCaptureClient::GetBuffer method. Thus, the length of the packet retrieved by <c>GetBuffer</c> is at
			/// least as large as, but might be larger than, the padding value reported by the <c>GetCurrentPadding</c> call that preceded
			/// the <c>GetBuffer</c> call. In contrast, for a shared-mode capture stream, the length of the packet obtained from
			/// <c>GetBuffer</c> always equals the padding value reported by the preceding <c>GetCurrentPadding</c> call.
			/// </para>
			/// <para>For a code example that calls the <c>GetCurrentPadding</c> method, see Rendering a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getcurrentpadding HRESULT
			// GetCurrentPadding( UINT32 *pNumPaddingFrames );
			new uint GetCurrentPadding();

			/// <summary>
			/// The <c>IsFormatSupported</c> method indicates whether the audio endpoint device supports a particular stream format.
			/// </summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the stream format. Through this parameter, the client indicates whether it wants to use the specified
			/// format in exclusive mode or shared mode. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="pFormat">
			/// Pointer to the specified stream format. This parameter points to a caller-allocated format descriptor of type
			/// <c>WAVEFORMATEX</c> or <c>WAVEFORMATEXTENSIBLE</c>. The client writes a format description to this structure before calling
			/// this method. For information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </param>
			/// <param name="ppClosestMatch">
			/// Pointer to a pointer variable into which the method writes the address of a <c>WAVEFORMATEX</c> or
			/// <c>WAVEFORMATEXTENSIBLE</c> structure. This structure specifies the supported format that is closest to the format that the
			/// client specified through the pFormat parameter. For shared mode (that is, if the ShareMode parameter is
			/// AUDCLNT_SHAREMODE_SHARED), set ppClosestMatch to point to a valid, non- <c>NULL</c> pointer variable. For exclusive mode,
			/// set ppClosestMatch to <c>NULL</c>. The method allocates the storage for the structure. The caller is responsible for freeing
			/// the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the <c>IsFormatSupported</c> call
			/// fails and ppClosestMatch is non- <c>NULL</c>, the method sets *ppClosestMatch to <c>NULL</c>. For information about
			/// <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>S_OK</term>
			/// <term>Succeeded and the audio endpoint device supports the specified stream format.</term>
			/// </item>
			/// <item>
			/// <term>S_FALSE</term>
			/// <term>Succeeded with a closest match to the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>Succeeded but the specified format is not supported in exclusive mode.</term>
			/// </item>
			/// </list>
			/// <para>If the operation fails, possible return codes include, but are not limited to, the values shown in the following table.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL, or ppClosestMatch is NULL and ShareMode is AUDCLNT_SHAREMODE_SHARED.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>Parameter ShareMode is a value other than AUDCLNT_SHAREMODE_SHARED or AUDCLNT_SHAREMODE_EXCLUSIVE.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method provides a way for a client to determine, before calling IAudioClient::Initialize, whether the audio engine
			/// supports a particular stream format.
			/// </para>
			/// <para>
			/// For exclusive mode, <c>IsFormatSupported</c> returns S_OK if the audio endpoint device supports the caller-specified format,
			/// or it returns AUDCLNT_E_UNSUPPORTED_FORMAT if the device does not support the format. The ppClosestMatch parameter can be
			/// <c>NULL</c>. If it is not <c>NULL</c>, the method writes <c>NULL</c> to *ppClosestMatch.
			/// </para>
			/// <para>
			/// For shared mode, if the audio engine supports the caller-specified format, <c>IsFormatSupported</c> sets
			/// <c>*ppClosestMatch</c> to <c>NULL</c> and returns S_OK. If the audio engine does not support the caller-specified format but
			/// does support a similar format, the method retrieves the similar format through the ppClosestMatch parameter and returns
			/// S_FALSE. If the audio engine does not support the caller-specified format or any similar format, the method sets
			/// *ppClosestMatch to <c>NULL</c> and returns AUDCLNT_E_UNSUPPORTED_FORMAT.
			/// </para>
			/// <para>
			/// In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the
			/// IAudioClient::GetMixFormat method. In addition, the audio engine might support similar formats that have the same sample
			/// rate and number of channels as the mix format but differ in the representation of audio sample values. The audio engine
			/// represents sample values internally as floating-point numbers, but if the caller-specified format represents sample values
			/// as integers, the audio engine typically can convert between the integer sample values and its internal floating-point representation.
			/// </para>
			/// <para>
			/// The audio engine might be able to support an even wider range of shared-mode formats if the installation package for the
			/// audio device includes a local effects (LFX) audio processing object (APO) that can handle format conversions. An LFX APO is
			/// a software module that performs device-specific processing of an audio stream. The audio graph builder in the Windows audio
			/// service inserts the LFX APO into the stream between each client and the audio engine. When a client calls the
			/// <c>IsFormatSupported</c> method and the method determines that an LFX APO is installed for use with the device, the method
			/// directs the query to the LFX APO, which indicates whether it supports the caller-specified format.
			/// </para>
			/// <para>
			/// For example, a particular LFX APO might accept a 6-channel surround sound stream from a client and convert the stream to a
			/// stereo format that can be played through headphones. Typically, an LFX APO supports only client formats with sample rates
			/// that match the sample rate of the mix format.
			/// </para>
			/// <para>
			/// For more information about APOs, see the white papers titled "Custom Audio Effects in Windows Vista" and "Reusing the
			/// Windows Vista Audio System Effects" at the Audio Device Technologies for Windows website. For more information about the
			/// <c>IsFormatSupported</c> method, see Device Formats.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-isformatsupported HRESULT
			// IsFormatSupported( AUDCLNT_SHAREMODE ShareMode, const WAVEFORMATEX *pFormat, WAVEFORMATEX **ppClosestMatch );
			[PreserveSig]
			new HRESULT IsFormatSupported([In] AUDCLNT_SHAREMODE ShareMode, [In] IntPtr pFormat, out SafeCoTaskMemHandle ppClosestMatch);

			/// <summary>
			/// The <c>GetMixFormat</c> method retrieves the stream format that the audio engine uses for its internal processing of
			/// shared-mode streams.
			/// </summary>
			/// <param name="ppDeviceFormat">
			/// Pointer to a pointer variable into which the method writes the address of the mix format. This parameter must be a valid,
			/// non- <c>NULL</c> pointer to a pointer variable. The method writes the address of a <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>) structure to this variable. The method allocates the storage for the structure. The caller is
			/// responsible for freeing the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the
			/// <c>GetMixFormat</c> call fails, *ppDeviceFormat is <c>NULL</c>. For information about <c>WAVEFORMATEX</c>,
			/// <c>WAVEFORMATEXTENSIBLE</c>, and <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter ppDeviceFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The client can call this method before calling the IAudioClient::Initialize method. When creating a shared-mode stream for
			/// an audio endpoint device, the <c>Initialize</c> method always accepts the stream format obtained from a <c>GetMixFormat</c>
			/// call on the same device.
			/// </para>
			/// <para>
			/// The mix format is the format that the audio engine uses internally for digital processing of shared-mode streams. This
			/// format is not necessarily a format that the audio endpoint device supports. Thus, the caller might not succeed in creating
			/// an exclusive-mode stream with a format obtained by calling <c>GetMixFormat</c>.
			/// </para>
			/// <para>
			/// For example, to facilitate digital audio processing, the audio engine might use a mix format that represents samples as
			/// floating-point values. If the device supports only integer PCM samples, then the engine converts the samples to or from
			/// integer PCM values at the connection between the device and the engine. However, to avoid resampling, the engine might use a
			/// mix format with a sample rate that the device supports.
			/// </para>
			/// <para>
			/// To determine whether the <c>Initialize</c> method can create a shared-mode or exclusive-mode stream with a particular
			/// format, call the IAudioClient::IsFormatSupported method.
			/// </para>
			/// <para>
			/// By itself, a <c>WAVEFORMATEX</c> structure cannot specify the mapping of channels to speaker positions. In addition,
			/// although <c>WAVEFORMATEX</c> specifies the size of the container for each audio sample, it cannot specify the number of bits
			/// of precision in a sample (for example, 20 bits of precision in a 24-bit container). However, the <c>WAVEFORMATEXTENSIBLE</c>
			/// structure can specify both the mapping of channels to speakers and the number of bits of precision in each sample. For this
			/// reason, the <c>GetMixFormat</c> method retrieves a format descriptor that is in the form of a <c>WAVEFORMATEXTENSIBLE</c>
			/// structure instead of a standalone <c>WAVEFORMATEX</c> structure. Through the ppDeviceFormat parameter, the method outputs a
			/// pointer to the <c>WAVEFORMATEX</c> structure that is embedded at the start of this <c>WAVEFORMATEXTENSIBLE</c> structure.
			/// For more information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </para>
			/// <para>
			/// For more information about the <c>GetMixFormat</c> method, see Device Formats. For code examples that call
			/// <c>GetMixFormat</c>, see the following topics:
			/// </para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getmixformat HRESULT GetMixFormat(
			// WAVEFORMATEX **ppDeviceFormat );
			[PreserveSig]
			new HRESULT GetMixFormat(out SafeCoTaskMemHandle ppDeviceFormat);

			/// <summary>
			/// The <c>GetDevicePeriod</c> method retrieves the length of the periodic interval separating successive processing passes by
			/// the audio engine on the data in the endpoint buffer.
			/// </summary>
			/// <param name="phnsDefaultDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the default interval between
			/// periodic processing passes by the audio engine. The time is expressed in 100-nanosecond units. For information about
			/// <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </param>
			/// <param name="phnsMinimumDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the minimum interval between
			/// periodic processing passes by the audio endpoint device. The time is expressed in 100-nanosecond units.
			/// </param>
			/// <remarks>
			/// <para>The client can call this method before calling the IAudioClient::Initialize method.</para>
			/// <para>
			/// The phnsDefaultDevicePeriod parameter specifies the default scheduling period for a shared-mode stream. The
			/// phnsMinimumDevicePeriod parameter specifies the minimum scheduling period for an exclusive-mode stream.
			/// </para>
			/// <para>
			/// At least one of the two parameters, phnsDefaultDevicePeriod and phnsMinimumDevicePeriod, must be non- <c>NULL</c> or the
			/// method returns immediately with error code E_POINTER. If both parameters are non- <c>NULL</c>, then the method outputs both
			/// the default and minimum periods.
			/// </para>
			/// <para>
			/// For a shared-mode stream, the audio engine periodically processes the data in the endpoint buffer, which the engine shares
			/// with the client application. The engine schedules itself to perform these processing passes at regular intervals.
			/// </para>
			/// <para>
			/// The period between processing passes by the audio engine is fixed for a particular audio endpoint device and represents the
			/// smallest processing quantum for the audio engine. This period plus the stream latency between the buffer and endpoint device
			/// represents the minimum possible latency that an audio application can achieve.
			/// </para>
			/// <para>
			/// The client has the option of scheduling its periodic processing thread to run at the same time interval as the audio engine.
			/// In this way, the client can achieve the smallest possible latency for a shared-mode stream. However, in an application for
			/// which latency is less important, the client can reduce the process-switching overhead on the CPU by scheduling its
			/// processing passes to occur less frequently. In this case, the endpoint buffer must be proportionally larger to compensate
			/// for the longer period between processing passes.
			/// </para>
			/// <para>
			/// The client determines the buffer size during its call to the IAudioClient::Initialize method. For a shared-mode stream, if
			/// the client passes this method an hnsBufferDuration parameter value of 0, the method assumes that the periods for the client
			/// and audio engine are guaranteed to be equal, and the method will allocate a buffer small enough to achieve the minimum
			/// possible latency. (In fact, any hnsBufferDuration value between 0 and the sum of the audio engine's period and device
			/// latency will have the same result.) Similarly, for an exclusive-mode stream, if the client sets hnsBufferDuration to 0, the
			/// method assumes that the period of the client is set to the minimum period of the audio endpoint device, and the method will
			/// allocate a buffer small enough to achieve the minimum possible latency.
			/// </para>
			/// <para>
			/// If the client chooses to run its periodic processing thread less often, at the cost of increased latency, it can do so as
			/// long as it creates an endpoint buffer during the IAudioClient::Initialize call that is sufficiently large.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getdeviceperiod HRESULT
			// GetDevicePeriod( REFERENCE_TIME *phnsDefaultDevicePeriod, REFERENCE_TIME *phnsMinimumDevicePeriod );
			new void GetDevicePeriod([Out, Optional] out long phnsDefaultDevicePeriod, out long phnsMinimumDevicePeriod);

			/// <summary>The <c>Start</c> method starts the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Start</c> is a control method that the client calls to start the audio stream. Starting the stream causes the
			/// IAudioClient object to begin streaming data between the endpoint buffer and the audio engine. It also causes the stream's
			/// audio clock to resume counting from its current position.
			/// </para>
			/// <para>
			/// The first time this method is called following initialization of the stream, the IAudioClient object's stream position
			/// counter begins at 0. Otherwise, the clock resumes from its position at the time that the stream was last stopped. Resetting
			/// the stream forces the stream position back to 0.
			/// </para>
			/// <para>
			/// To avoid start-up glitches with rendering streams, clients should not call <c>Start</c> until the audio engine has been
			/// initially loaded with data by calling the IAudioRenderClient::GetBuffer and IAudioRenderClient::ReleaseBuffer methods on the
			/// rendering interface.
			/// </para>
			/// <para>For code examples that call the <c>Start</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-start HRESULT Start();
			new void Start();

			/// <summary>The <c>Stop</c> method stops the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Stop</c> is a control method that stops a running audio stream. This method stops data from streaming through the
			/// client's connection with the audio engine. Stopping the stream freezes the stream's audio clock at its current stream
			/// position. A subsequent call to IAudioClient::Start causes the stream to resume running from that position. If necessary, the
			/// client can call the IAudioClient::Reset method to reset the position while the stream is stopped.
			/// </para>
			/// <para>For code examples that call the <c>Stop</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-stop HRESULT Stop();
			new void Stop();

			/// <summary>The <c>Reset</c> method resets the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Reset</c> is a control method that the client calls to reset a stopped audio stream. Resetting the stream flushes all
			/// pending data and resets the audio clock stream position to 0. This method fails if it is called on a stream that is not stopped.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-reset HRESULT Reset();
			new void Reset();

			/// <summary>
			/// The <c>SetEventHandle</c> method sets the event handle that the system signals when an audio buffer is ready to be processed
			/// by the client.
			/// </summary>
			/// <param name="eventHandle">The event handle.</param>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// During stream initialization, the client can, as an option, enable event-driven buffering. To do so, the client calls the
			/// IAudioClient::Initialize method with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag set. After enabling event-driven buffering,
			/// and before calling the IAudioClient::Start method to start the stream, the client must call <c>SetEventHandle</c> to
			/// register the event handle that the system will signal each time a buffer becomes ready to be processed by the client.
			/// </para>
			/// <para>The event handle should be in the nonsignaled state at the time that the client calls the Start method.</para>
			/// <para>
			/// If the client has enabled event-driven buffering of a stream, but the client calls the Start method for that stream without
			/// first calling <c>SetEventHandle</c>, the <c>Start</c> call will fail and return an error code.
			/// </para>
			/// <para>
			/// If the client does not enable event-driven buffering of a stream but attempts to set an event handle for the stream by
			/// calling <c>SetEventHandle</c>, the call will fail and return an error code.
			/// </para>
			/// <para>For a code example that calls the <c>SetEventHandle</c> method, see Exclusive-Mode Streams.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-seteventhandle HRESULT
			// SetEventHandle( HANDLE eventHandle );
			new void SetEventHandle(IntPtr eventHandle);

			/// <summary>The <c>GetService</c> method accesses additional services from the audio client object.</summary>
			/// <param name="riid">
			/// <para>The interface ID for the requested service. The client should set this parameter to one of the following REFIID values:</para>
			/// <para>IID_IAudioCaptureClient</para>
			/// <para>IID_IAudioClock</para>
			/// <para>IID_IAudioRenderClient</para>
			/// <para>IID_IAudioSessionControl</para>
			/// <para>IID_IAudioStreamVolume</para>
			/// <para>IID_IChannelAudioVolume</para>
			/// <para>IID_IMFTrustedOutput</para>
			/// <para>IID_ISimpleAudioVolume</para>
			/// <para>For more information, see Remarks.</para>
			/// </param>
			/// <returns>
			/// Pointer to a pointer variable into which the method writes the address of an instance of the requested interface. Through
			/// this method, the caller obtains a counted reference to the interface. The caller is responsible for releasing the interface,
			/// when it is no longer needed, by calling the interface's <c>Release</c> method. If the <c>GetService</c> call fails, *ppv is <c>NULL</c>.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>The <c>GetService</c> method supports the following service interfaces:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioCaptureClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioClock</term>
			/// </item>
			/// <item>
			/// <term>IAudioRenderClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioSessionControl</term>
			/// </item>
			/// <item>
			/// <term>IAudioStreamVolume</term>
			/// </item>
			/// <item>
			/// <term>IChannelAudioVolume</term>
			/// </item>
			/// <item>
			/// <term>IMFTrustedOutput</term>
			/// </item>
			/// <item>
			/// <term>ISimpleAudioVolume</term>
			/// </item>
			/// </list>
			/// <para>
			/// In Windows 7, a new service identifier, <c>IID_IMFTrustedOutput</c>, has been added that facilitates the use of output trust
			/// authority (OTA) objects. These objects can operate inside or outside the Media Foundation's protected media path (PMP) and
			/// send content outside the Media Foundation pipeline. If the caller is outside PMP, then the OTA may not operate in the PMP,
			/// and the protection settings are less robust. OTAs must implement the IMFTrustedOutput interface. By passing
			/// <c>IID_IMFTrustedOutput</c> in <c>GetService</c>, an application can retrieve a pointer to the object's
			/// <c>IMFTrustedOutput</c> interface. For more information about protected objects and <c>IMFTrustedOutput</c>, see "Protected
			/// Media Path" in the Media Foundation SDK documentation.
			/// </para>
			/// <para>For information about using trusted audio drivers in OTAs, see Protected User Mode Audio (PUMA).</para>
			/// <para>
			/// Note that activating IMFTrustedOutput through this mechanism works regardless of whether the caller is running in PMP.
			/// However, if the caller is not running in a protected process (that is, the caller is not within Media Foundation's PMP) then
			/// the audio OTA might not operate in the PMP and the protection settings are less robust.
			/// </para>
			/// <para>
			/// To obtain the interface ID for a service interface, use the <c>__uuidof</c> operator. For example, the interface ID of
			/// <c>IAudioCaptureClient</c> is defined as follows:
			/// </para>
			/// <para>For information about the <c>__uuidof</c> operator, see the Windows SDK documentation.</para>
			/// <para>
			/// To release the <c>IAudioClient</c> object and free all its associated resources, the client must release all references to
			/// any service objects that were created by calling <c>GetService</c>, in addition to calling <c>Release</c> on the
			/// <c>IAudioClient</c> interface itself. The client must release a service from the same thread that releases the
			/// <c>IAudioClient</c> object.
			/// </para>
			/// <para>
			/// The <c>IAudioSessionControl</c>, <c>IAudioStreamVolume</c>, <c>IChannelAudioVolume</c>, and <c>ISimpleAudioVolume</c>
			/// interfaces control and monitor aspects of audio sessions and shared-mode streams. These interfaces do not work with
			/// exclusive-mode streams.
			/// </para>
			/// <para>For code examples that call the <c>GetService</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getservice HRESULT GetService(
			// REFIID riid, void **ppv );
			[return: MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 0)]
			new object GetService(in Guid riid);

			/// <summary>
			/// The <c>IsOffloadCapable</c> method retrieves information about whether or not the endpoint on which a stream is created is
			/// capable of supporting an offloaded audio stream.
			/// </summary>
			/// <param name="Category">An enumeration that specifies the category of an audio stream.</param>
			/// <returns>
			/// A pointer to a Boolean value. <c>TRUE</c> indicates that the endpoint is offload-capable. <c>FALSE</c> indicates that the
			/// endpoint is not offload-capable.
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-isoffloadcapable HRESULT
			// IsOffloadCapable( AUDIO_STREAM_CATEGORY Category, BOOL *pbOffloadCapable );
			[return: MarshalAs(UnmanagedType.Bool)]
			bool IsOffloadCapable(AUDIO_STREAM_CATEGORY Category);

			/// <summary>Sets the properties of the audio stream by populating an AudioClientProperties structure.</summary>
			/// <param name="pProperties">Pointer to an AudioClientProperties structure.</param>
			/// <remarks>
			/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
			/// <c>IAudioClient2::SetClientProperties</c> and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must
			/// specify the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to IAudioClient::Initialize.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-setclientproperties HRESULT
			// SetClientProperties( const AudioClientProperties *pProperties );
			void SetClientProperties(in AudioClientProperties pProperties);

			/// <summary>
			/// The <c>GetBufferSizeLimits</c> method returns the buffer size limits of the hardware audio engine in 100-nanosecond units.
			/// </summary>
			/// <param name="pFormat">A pointer to the target format that is being queried for the buffer size limit.</param>
			/// <param name="bEventDriven">Boolean value to indicate whether or not the stream can be event-driven.</param>
			/// <param name="phnsMinBufferDuration">
			/// Returns a pointer to the minimum buffer size (in 100-nanosecond units) that is required for the underlying hardware audio
			/// engine to operate at the format specified in the pFormat parameter, without frequent audio glitching.
			/// </param>
			/// <param name="phnsMaxBufferDuration">
			/// Returns a pointer to the maximum buffer size (in 100-nanosecond units) that the underlying hardware audio engine can support
			/// for the format specified in the pFormat parameter.
			/// </param>
			/// <remarks>The <c>GetBufferSizeLimits</c> method is a device-facing method and does not require prior audio stream initialization.</remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-getbuffersizelimits HRESULT
			// GetBufferSizeLimits( const WAVEFORMATEX *pFormat, BOOL bEventDriven, REFERENCE_TIME *phnsMinBufferDuration, REFERENCE_TIME
			// *phnsMaxBufferDuration );
			void GetBufferSizeLimits(in WAVEFORMATEX pFormat, [MarshalAs(UnmanagedType.Bool)] bool bEventDriven, out long phnsMinBufferDuration, out long phnsMaxBufferDuration);
		}

		/// <summary>
		/// The <c>IAudioClient3</c> interface is derived from the IAudioClient2 interface, with a set of additional methods that enable a
		/// Windows Audio Session API (WASAPI) audio client to query for the audio engine's supported periodicities and current periodicity
		/// as well as request initialization a shared audio stream with a specified periodicity.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclient3
		[PInvokeData("audioclient.h", MSDNShortId = "E8EFE682-E1BC-4D0D-A60E-DD257D6E5894")]
		[ComImport, Guid("7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClient3 : IAudioClient2
		{
			/// <summary>The <c>Initialize</c> method initializes the audio stream.</summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the connection. Through this parameter, the client tells the audio engine whether it wants to share the
			/// audio endpoint device with other clients. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="StreamFlags">
			/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of
			/// the AUDCLNT_STREAMFLAGS_XXX Constants or the AUDCLNT_SESSIONFLAGS_XXX Constants.
			/// </param>
			/// <param name="hnsBufferDuration">
			/// The buffer capacity as a time value. This parameter is of type <c>REFERENCE_TIME</c> and is expressed in 100-nanosecond
			/// units. This parameter contains the buffer size that the caller requests for the buffer that the audio application will share
			/// with the audio engine (in shared mode) or with the endpoint device (in exclusive mode). If the call succeeds, the method
			/// allocates a buffer that is a least this large. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK
			/// documentation. For more information about buffering requirements, see Remarks.
			/// </param>
			/// <param name="hnsPeriodicity">
			/// The device period. This parameter can be nonzero only in exclusive mode. In shared mode, always set this parameter to 0. In
			/// exclusive mode, this parameter specifies the requested scheduling period for successive buffer accesses by the audio
			/// endpoint device. If the requested device period lies outside the range that is set by the device's minimum period and the
			/// system's maximum period, then the method clamps the period to that range. If this parameter is 0, the method sets the device
			/// period to its default value. To obtain the default device period, call the IAudioClient::GetDevicePeriod method. If the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK stream flag is set and AUDCLNT_SHAREMODE_EXCLUSIVE is set as the ShareMode, then
			/// hnsPeriodicity must be nonzero and equal to hnsBufferDuration.
			/// </param>
			/// <param name="pFormat">
			/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>). For more information, see Remarks.
			/// </param>
			/// <param name="AudioSessionGuid">
			/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs
			/// to. If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the
			/// GUID does not identify an existing session, the method opens a new session and adds the stream to that session. The stream
			/// remains a member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a
			/// pointer to a GUID_NULL value.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_ALREADY_INITIALIZED</term>
			/// <term>The IAudioClient object is already initialized.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_WRONG_ENDPOINT_TYPE</term>
			/// <term>The AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but the endpoint device is a capture device, not a rendering device.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</term>
			/// <term>
			/// The requested buffer size is not aligned. This code can be returned for a render or a capture device if the caller specified
			/// AUDCLNT_SHAREMODE_EXCLUSIVE and the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flags. The caller must call Initialize again with the
			/// aligned buffer size. For more information, see Remarks.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
			/// <term>
			/// Indicates that the buffer duration value requested by an exclusive-mode client is out of range. The requested duration value
			/// for pull mode must not be greater than 500 milliseconds; for push mode the duration value must not be greater than 2 seconds.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_CPUUSAGE_EXCEEDED</term>
			/// <term>
			/// Indicates that the process-pass duration exceeded the maximum CPU usage. The audio engine keeps track of CPU usage by
			/// maintaining the number of times the process-pass duration exceeds the maximum CPU usage. The maximum CPU usage is calculated
			/// as a percent of the engine's periodicity. The percentage value is the system's CPU throttle value (within the range of 10%
			/// and 90%). If this value is not found, then the default value of 40% is used to calculate the maximum CPU usage.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_IN_USE</term>
			/// <term>
			/// The endpoint device is already in use. Either the device is being used in exclusive mode, or the device is being used in
			/// shared mode and the caller asked to use the device in exclusive mode.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_ENDPOINT_CREATE_FAILED</term>
			/// <term>
			/// The method failed to create the audio endpoint for the render or the capture device. This can occur if the audio endpoint
			/// device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured, disabled, removed,
			/// or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_INVALID_DEVICE_PERIOD</term>
			/// <term>Indicates that the device period requested by an exclusive-mode client is greater than 500 milliseconds.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>The audio engine (shared mode) or audio endpoint device (exclusive mode) does not support the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED</term>
			/// <term>
			/// The caller is requesting exclusive-mode use of the endpoint device, but the user has disabled exclusive-mode use of the device.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL</term>
			/// <term>The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is set but parameters hnsBufferDuration and hnsPeriodicity are not equal.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>
			/// Parameter pFormat points to an invalid format description; or the AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but ShareMode is
			/// not equal to AUDCLNT_SHAREMODE_SHARED; or the AUDCLNT_STREAMFLAGS_CROSSPROCESS flag is set but ShareMode is equal to
			/// AUDCLNT_SHAREMODE_EXCLUSIVE. A prior call to SetClientProperties was made with an invalid category for audio/render streams.
			/// </term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// After activating an IAudioClient interface on an audio endpoint device, the client must successfully call <c>Initialize</c>
			/// once and only once to initialize the audio stream between the client and the device. The client can either connect directly
			/// to the audio hardware (exclusive mode) or indirectly through the audio engine (shared mode). In the <c>Initialize</c> call,
			/// the client specifies the audio data format, the buffer size, and audio session for the stream.
			/// </para>
			/// <para>
			/// <c>Note</c> In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from
			/// an MTA thread may result in undefined behavior.
			/// </para>
			/// <para>
			/// An attempt to create a shared-mode stream can succeed only if the audio device is already operating in shared mode or the
			/// device is currently unused. An attempt to create a shared-mode stream fails if the device is already operating in exclusive mode.
			/// </para>
			/// <para>
			/// If a stream is initialized to be event driven and in shared mode, ShareMode is set to AUDCLNT_SHAREMODE_SHARED and one of
			/// the stream flags that are set includes AUDCLNT_STREAMFLAGS_EVENTCALLBACK. For such a stream, the associated application must
			/// also obtain a handle by making a call to IAudioClient::SetEventHandle. When it is time to retire the stream, the audio
			/// engine can then use the handle to release the stream objects. Failure to call <c>IAudioClient::SetEventHandle</c> before
			/// releasing the stream objects can cause a delay of several seconds (a time-out period) while the audio engine waits for an
			/// available handle. After the time-out period expires, the audio engine then releases the stream objects.
			/// </para>
			/// <para>
			/// Whether an attempt to create an exclusive-mode stream succeeds depends on several factors, including the availability of the
			/// device and the user-controlled settings that govern exclusive-mode operation of the device. For more information, see
			/// Exclusive-Mode Streams.
			/// </para>
			/// <para>
			/// An <c>IAudioClient</c> object supports exactly one connection to the audio engine or audio hardware. This connection lasts
			/// for the lifetime of the <c>IAudioClient</c> object.
			/// </para>
			/// <para>The client should call the following methods only after calling <c>Initialize</c>:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetBufferSize</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetCurrentPadding</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetService</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetStreamLatency</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Reset</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::SetEventHandle</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Start</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::Stop</term>
			/// </item>
			/// </list>
			/// <para>The following methods do not require that <c>Initialize</c> be called first:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioClient::GetDevicePeriod</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::GetMixFormat</term>
			/// </item>
			/// <item>
			/// <term>IAudioClient::IsFormatSupported</term>
			/// </item>
			/// </list>
			/// <para>These methods can be called any time after activating the <c>IAudioClient</c> interface.</para>
			/// <para>
			/// Before calling <c>Initialize</c> to set up a shared-mode or exclusive-mode connection, the client can call the
			/// IAudioClient::IsFormatSupported method to discover whether the audio engine or audio endpoint device supports a particular
			/// format in that mode. Before opening a shared-mode connection, the client can obtain the audio engine's mix format by calling
			/// the IAudioClient::GetMixFormat method.
			/// </para>
			/// <para>
			/// The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from
			/// occurring in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client
			/// thread periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a
			/// capture endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the
			/// buffer. In either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough
			/// to accommodate the longer of the two periods without allowing glitches to occur.
			/// </para>
			/// <para>
			/// The client specifies a buffer size through the hnsBufferDuration parameter. The client is responsible for requesting a
			/// buffer that is large enough to ensure that glitches cannot occur between the periodic processing passes that it performs on
			/// the buffer. Similarly, the <c>Initialize</c> method ensures that the buffer is never smaller than the minimum buffer size
			/// needed to ensure that glitches do not occur between the periodic processing passes that the engine thread performs on the
			/// buffer. If the client requests a buffer size that is smaller than the audio engine's minimum required buffer size, the
			/// method sets the buffer size to this minimum buffer size rather than to the buffer size requested by the client.
			/// </para>
			/// <para>
			/// If the client requests a buffer size (through the hnsBufferDuration parameter) that is not an integral number of audio
			/// frames, the method rounds up the requested buffer size to the next integral number of frames.
			/// </para>
			/// <para>
			/// Following the <c>Initialize</c> call, the client should call the IAudioClient::GetBufferSize method to get the precise size
			/// of the endpoint buffer. During each processing pass, the client will need the actual buffer size to calculate how much data
			/// to transfer to or from the buffer. The client calls the IAudioClient::GetCurrentPadding method to determine how much of the
			/// data in the buffer is currently available for processing.
			/// </para>
			/// <para>
			/// To achieve the minimum stream latency between the client application and audio endpoint device, the client thread should run
			/// at the same period as the audio engine thread. The period of the engine thread is fixed and cannot be controlled by the
			/// client. Making the client's period smaller than the engine's period unnecessarily increases the client thread's load on the
			/// processor without improving latency or decreasing the buffer size. To determine the period of the engine thread, the client
			/// can call the IAudioClient::GetDevicePeriod method. To set the buffer to the minimum size required by the engine thread, the
			/// client should call <c>Initialize</c> with the hnsBufferDuration parameter set to 0. Following the <c>Initialize</c> call,
			/// the client can get the size of the resulting buffer by calling <c>IAudioClient::GetBufferSize</c>.
			/// </para>
			/// <para>
			/// A client has the option of requesting a buffer size that is larger than what is strictly necessary to make timing glitches
			/// rare or nonexistent. Increasing the buffer size does not necessarily increase the stream latency. For a rendering stream,
			/// the latency through the buffer is determined solely by the separation between the client's write pointer and the engine's
			/// read pointer. For a capture stream, the latency through the buffer is determined solely by the separation between the
			/// engine's write pointer and the client's read pointer.
			/// </para>
			/// <para>
			/// The loopback flag (AUDCLNT_STREAMFLAGS_LOOPBACK) enables audio loopback. A client can enable audio loopback only on a
			/// rendering endpoint with a shared-mode stream. Audio loopback is provided primarily to support acoustic echo cancellation (AEC).
			/// </para>
			/// <para>
			/// An AEC client requires both a rendering endpoint and the ability to capture the output stream from the audio engine. The
			/// engine's output stream is the global mix that the audio device plays through the speakers. If audio loopback is enabled, a
			/// client can open a capture buffer for the global audio mix by calling the IAudioClient::GetService method to obtain an
			/// IAudioCaptureClient interface on the rendering stream object. If audio loopback is not enabled, then an attempt to open a
			/// capture buffer on a rendering stream will fail. The loopback data in the capture buffer is in the device format, which the
			/// client can obtain by querying the device's PKEY_AudioEngine_DeviceFormat property.
			/// </para>
			/// <para>
			/// On Windows versions prior to Windows 10, a pull-mode capture client will not receive any events when a stream is initialized
			/// with event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) and is loopback-enabled (AUDCLNT_STREAMFLAGS_LOOPBACK). If
			/// the stream is opened with this configuration, the <c>Initialize</c> call succeeds, but relevant events are not raised to
			/// notify the capture client each time a buffer becomes ready for processing. To work around this, initialize a render stream
			/// in event-driven mode. Each time the client receives an event for the render stream, it must signal the capture client to run
			/// the capture thread that reads the next set of samples from the capture endpoint buffer. As of Windows 10 the relevant event
			/// handles are now set for loopback-enabled streams that are active.
			/// </para>
			/// <para>
			/// Note that all streams must be opened in share mode because exclusive-mode streams cannot operate in loopback mode. For more
			/// information about audio loopback, see Loopback Recording.
			/// </para>
			/// <para>
			/// The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag indicates that processing of the audio buffer by the client will be event driven.
			/// WASAPI supports event-driven buffering to enable low-latency processing of both shared-mode and exclusive-mode streams.
			/// </para>
			/// <para>
			/// The initial release of Windows Vista supports event-driven buffering (that is, the use of the
			/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag) for rendering streams only.
			/// </para>
			/// <para>
			/// In the initial release of Windows Vista, for capture streams, the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is supported only
			/// in shared mode. Setting this flag has no effect for exclusive-mode capture streams. That is, although the application
			/// specifies this flag in exclusive mode through the <c>Initialize</c> call, the application will not receive any events that
			/// are usually required to capture the audio stream. In the Windows Vista Service Pack 1 release, this flag is functional in
			/// shared-mode and exclusive mode; an application can set this flag to enable event-buffering for capture streams. For more
			/// information about capturing an audio stream, see Capturing a Stream.
			/// </para>
			/// <para>
			/// To enable event-driven buffering, the client must provide an event handle to the system. Following the <c>Initialize</c>
			/// call and before calling the IAudioClient::Start method to start the stream, the client must call the
			/// IAudioClient::SetEventHandle method to set the event handle. While the stream is running, the system periodically signals
			/// the event to indicate to the client that audio data is available for processing. Between processing passes, the client
			/// thread waits on the event handle by calling a synchronization function such as <c>WaitForSingleObject</c>. For more
			/// information about synchronization functions, see the Windows SDK documentation.
			/// </para>
			/// <para>
			/// For a shared-mode stream that uses event-driven buffering, the caller must set both hnsPeriodicity and hnsBufferDuration to
			/// 0. The <c>Initialize</c> method determines how large a buffer to allocate based on the scheduling period of the audio
			/// engine. Although the client's buffer processing thread is event driven, the basic buffer management process, as described
			/// previously, is unaltered. Each time the thread awakens, it should call IAudioClient::GetCurrentPadding to determine how much
			/// data to write to a rendering buffer or read from a capture buffer. In contrast to the two buffers that the <c>Initialize</c>
			/// method allocates for an exclusive-mode stream that uses event-driven buffering, a shared-mode stream requires a single buffer.
			/// </para>
			/// <para>
			/// For an exclusive-mode stream that uses event-driven buffering, the caller must specify nonzero values for hnsPeriodicity and
			/// hnsBufferDuration, and the values of these two parameters must be equal. The <c>Initialize</c> method allocates two buffers
			/// for the stream. Each buffer is equal in duration to the value of the hnsBufferDuration parameter. Following the
			/// <c>Initialize</c> call for a rendering stream, the caller should fill the first of the two buffers before starting the
			/// stream. For a capture stream, the buffers are initially empty, and the caller should assume that each buffer remains empty
			/// until the event for that buffer is signaled. While the stream is running, the system alternately sends one buffer or the
			/// other to the client—this form of double buffering is referred to as "ping-ponging". Each time the client receives a buffer
			/// from the system (which the system indicates by signaling the event), the client must process the entire buffer. For example,
			/// if the client requests a packet size from the IAudioRenderClient::GetBuffer method that does not match the buffer size, the
			/// method fails. Calls to the <c>IAudioClient::GetCurrentPadding</c> method are unnecessary because the packet size must always
			/// equal the buffer size. In contrast to the buffering modes discussed previously, the latency for an event-driven,
			/// exclusive-mode stream depends directly on the buffer size.
			/// </para>
			/// <para>
			/// As explained in Audio Sessions, the default behavior for a session that contains rendering streams is that its volume and
			/// mute settings persist across system restarts. The AUDCLNT_STREAMFLAGS_NOPERSIST flag overrides the default behavior and
			/// makes the settings nonpersistent. This flag has no effect on sessions that contain capture streams—the settings for those
			/// sessions are never persistent. In addition, the settings for a session that contains a loopback stream (a stream that is
			/// initialized with the AUDCLNT_STREAMFLAGS_LOOPBACK flag) are not persistent.
			/// </para>
			/// <para>
			/// Only a session that connects to a rendering endpoint device can have persistent volume and mute settings. The first stream
			/// to be added to the session determines whether the session's settings are persistent. Thus, if the
			/// AUDCLNT_STREAMFLAGS_NOPERSIST or AUDCLNT_STREAMFLAGS_LOOPBACK flag is set during initialization of the first stream, the
			/// session's settings are not persistent. Otherwise, they are persistent. Their persistence is unaffected by additional streams
			/// that might be subsequently added or removed during the lifetime of the session object.
			/// </para>
			/// <para>
			/// After a call to <c>Initialize</c> has successfully initialized an <c>IAudioClient</c> interface instance, a subsequent
			/// <c>Initialize</c> call to initialize the same interface instance will fail and return error code E_ALREADY_INITIALIZED.
			/// </para>
			/// <para>
			/// If the initial call to <c>Initialize</c> fails, subsequent <c>Initialize</c> calls might fail and return error code
			/// E_ALREADY_INITIALIZED, even though the interface has not been initialized. If this occurs, release the <c>IAudioClient</c>
			/// interface and obtain a new <c>IAudioClient</c> interface from the MMDevice API before calling <c>Initialize</c> again.
			/// </para>
			/// <para>For code examples that call the <c>Initialize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// <item>
			/// <term>Exclusive-Mode Streams</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 7, <c>Initialize</c> can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render or a capture device.
			/// This indicates that the buffer size, specified by the caller in the hnsBufferDuration parameter, is not aligned. This error
			/// code is returned only if the caller requested an exclusive-mode stream (AUDCLNT_SHAREMODE_EXCLUSIVE) and event-driven
			/// buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).
			/// </para>
			/// <para>
			/// If <c>Initialize</c> returns AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, the caller must call <c>Initialize</c> again and specify the
			/// aligned buffer size. Use the following steps:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Call IAudioClient::GetBufferSize and receive the next-highest-aligned buffer size (in frames).</term>
			/// </item>
			/// <item>
			/// <term>Call <c>IAudioClient::Release</c> to release the audio client used in the previous call that returned AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.</term>
			/// </item>
			/// <item>
			/// <term>
			/// Calculate the aligned buffer size in 100-nansecond units (hns). The buffer size is . In this formula, is the buffer size
			/// retrieved by GetBufferSize.
			/// </term>
			/// </item>
			/// <item>
			/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient to create a new audio client.</term>
			/// </item>
			/// <item>
			/// <term>Call <c>Initialize</c> again on the created audio client and specify the new buffer size and periodicity.</term>
			/// </item>
			/// </list>
			/// <para>
			/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
			/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must specify
			/// the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to <c>IAudioClient::Initialize</c>.
			/// </para>
			/// <para>Examples</para>
			/// <para>The following example code shows how to respond to the <c>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</c> return code.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize HRESULT Initialize(
			// AUDCLNT_SHAREMODE ShareMode, DWORD StreamFlags, REFERENCE_TIME hnsBufferDuration, REFERENCE_TIME hnsPeriodicity, const
			// WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid );
			[PreserveSig]
			new HRESULT Initialize([In] AUDCLNT_SHAREMODE ShareMode, AUDCLNT_STREAMFLAGS StreamFlags, long hnsBufferDuration, long hnsPeriodicity, [In] IntPtr pFormat, [In, Optional] in Guid AudioSessionGuid);

			/// <summary>The <c>GetBufferSize</c> method retrieves the size (maximum capacity) of the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the number of audio frames that the buffer can hold.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the length of the endpoint buffer shared between the client application and the audio engine. The
			/// length is expressed as the number of audio frames the buffer can hold. The size in bytes of an audio frame is calculated as
			/// the number of channels in the stream multiplied by the sample size per channel. For example, the frame size is four bytes
			/// for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// The IAudioClient::Initialize method allocates the buffer. The client specifies the buffer length in the hnsBufferDuration
			/// parameter value that it passes to the <c>Initialize</c> method. For rendering clients, the buffer length determines the
			/// maximum amount of rendering data that the application can write to the endpoint buffer during a single processing pass. For
			/// capture clients, the buffer length determines the maximum amount of capture data that the audio engine can read from the
			/// endpoint buffer during a single processing pass. The client should always call <c>GetBufferSize</c> after calling
			/// <c>Initialize</c> to determine the actual size of the allocated buffer, which might differ from the requested size.
			/// </para>
			/// <para>
			/// Rendering clients can use this value to calculate the largest rendering buffer size that can be requested from
			/// IAudioRenderClient::GetBuffer during each processing pass.
			/// </para>
			/// <para>For code examples that call the <c>GetBufferSize</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getbuffersize HRESULT
			// GetBufferSize( UINT32 *pNumBufferFrames );
			new uint GetBufferSize();

			/// <summary>
			/// The <c>GetStreamLatency</c> method retrieves the maximum latency for the current stream and can be called any time after the
			/// stream has been initialized.
			/// </summary>
			/// <returns>
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value representing the latency. The time is
			/// expressed in 100-nanosecond units. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves the maximum latency for the current stream. The value will not change for the lifetime of the
			/// IAudioClient object.
			/// </para>
			/// <para>
			/// Rendering clients can use this latency value to compute the minimum amount of data that they can write during any single
			/// processing pass. To write less than this minimum is to risk introducing glitches into the audio stream. For more
			/// information, see IAudioRenderClient::GetBuffer.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getstreamlatency HRESULT
			// GetStreamLatency( REFERENCE_TIME *phnsLatency );
			new long GetStreamLatency();

			/// <summary>The <c>GetCurrentPadding</c> method retrieves the number of frames of padding in the endpoint buffer.</summary>
			/// <returns>
			/// Pointer to a <c>UINT32</c> variable into which the method writes the frame count (the number of audio frames of padding in
			/// the buffer).
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// This method retrieves a padding value that indicates the amount of valid, unread data that the endpoint buffer currently
			/// contains. A rendering application can use the padding value to determine how much new data it can safely write to the
			/// endpoint buffer without overwriting previously written data that the audio engine has not yet read from the buffer. A
			/// capture application can use the padding value to determine how much new data it can safely read from the endpoint buffer
			/// without reading invalid data from a region of the buffer to which the audio engine has not yet written valid data.
			/// </para>
			/// <para>
			/// The padding value is expressed as a number of audio frames. The size of an audio frame is specified by the
			/// <c>nBlockAlign</c> member of the WAVEFORMATEX (or WAVEFORMATEXTENSIBLE) structure that the client passed to the
			/// IAudioClient::Initialize method. The size in bytes of an audio frame equals the number of channels in the stream multiplied
			/// by the sample size per channel. For example, the frame size is four bytes for a stereo (2-channel) stream with 16-bit samples.
			/// </para>
			/// <para>
			/// For a shared-mode rendering stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of audio
			/// frames that are queued up to play in the endpoint buffer. Before writing to the endpoint buffer, the client can calculate
			/// the amount of available space in the buffer by subtracting the padding value from the buffer length. To ensure that a
			/// subsequent call to the IAudioRenderClient::GetBuffer method succeeds, the client should request a packet length that does
			/// not exceed the available space in the buffer. To obtain the buffer length, call the IAudioClient::GetBufferSize method.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the number of frames of
			/// capture data that are available in the next packet in the endpoint buffer. At a particular moment, zero, one, or more
			/// packets of capture data might be ready for the client to read from the buffer. If no packets are currently available, the
			/// method reports a padding value of 0. Following the <c>GetCurrentPadding</c> call, an IAudioCaptureClient::GetBuffer method
			/// call will retrieve a packet whose length exactly equals the padding value reported by <c>GetCurrentPadding</c>. Each call to
			/// GetBuffer retrieves a whole packet. A packet always contains an integral number of audio frames.
			/// </para>
			/// <para>
			/// For a shared-mode capture stream, calling <c>GetCurrentPadding</c> is equivalent to calling the
			/// IAudioCaptureClient::GetNextPacketSize method. That is, the padding value reported by <c>GetCurrentPadding</c> is equal to
			/// the packet length reported by <c>GetNextPacketSize</c>.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag, the
			/// client typically has no use for the padding value reported by <c>GetCurrentPadding</c>. Instead, the client accesses an
			/// entire buffer during each processing pass. Each time a buffer becomes available for processing, the audio engine notifies
			/// the client by signaling the client's event handle. For more information about this flag, see IAudioClient::Initialize.
			/// </para>
			/// <para>
			/// For an exclusive-mode rendering or capture stream that was not initialized with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag,
			/// the client can use the padding value obtained from <c>GetCurrentPadding</c> in a way that is similar to that described
			/// previously for a shared-mode stream. The details are as follows.
			/// </para>
			/// <para>
			/// First, for an exclusive-mode rendering stream, the padding value specifies the number of audio frames that are queued up to
			/// play in the endpoint buffer. As before, the client can calculate the amount of available space in the buffer by subtracting
			/// the padding value from the buffer length.
			/// </para>
			/// <para>
			/// Second, for an exclusive-mode capture stream, the padding value reported by <c>GetCurrentPadding</c> specifies the current
			/// length of the next packet. However, this padding value is a snapshot of the packet length, which might increase before the
			/// client calls the IAudioCaptureClient::GetBuffer method. Thus, the length of the packet retrieved by <c>GetBuffer</c> is at
			/// least as large as, but might be larger than, the padding value reported by the <c>GetCurrentPadding</c> call that preceded
			/// the <c>GetBuffer</c> call. In contrast, for a shared-mode capture stream, the length of the packet obtained from
			/// <c>GetBuffer</c> always equals the padding value reported by the preceding <c>GetCurrentPadding</c> call.
			/// </para>
			/// <para>For a code example that calls the <c>GetCurrentPadding</c> method, see Rendering a Stream.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getcurrentpadding HRESULT
			// GetCurrentPadding( UINT32 *pNumPaddingFrames );
			new uint GetCurrentPadding();

			/// <summary>
			/// The <c>IsFormatSupported</c> method indicates whether the audio endpoint device supports a particular stream format.
			/// </summary>
			/// <param name="ShareMode">
			/// <para>
			/// The sharing mode for the stream format. Through this parameter, the client indicates whether it wants to use the specified
			/// format in exclusive mode or shared mode. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
			/// enumeration values:
			/// </para>
			/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
			/// <para>AUDCLNT_SHAREMODE_SHARED</para>
			/// </param>
			/// <param name="pFormat">
			/// Pointer to the specified stream format. This parameter points to a caller-allocated format descriptor of type
			/// <c>WAVEFORMATEX</c> or <c>WAVEFORMATEXTENSIBLE</c>. The client writes a format description to this structure before calling
			/// this method. For information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </param>
			/// <param name="ppClosestMatch">
			/// Pointer to a pointer variable into which the method writes the address of a <c>WAVEFORMATEX</c> or
			/// <c>WAVEFORMATEXTENSIBLE</c> structure. This structure specifies the supported format that is closest to the format that the
			/// client specified through the pFormat parameter. For shared mode (that is, if the ShareMode parameter is
			/// AUDCLNT_SHAREMODE_SHARED), set ppClosestMatch to point to a valid, non- <c>NULL</c> pointer variable. For exclusive mode,
			/// set ppClosestMatch to <c>NULL</c>. The method allocates the storage for the structure. The caller is responsible for freeing
			/// the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the <c>IsFormatSupported</c> call
			/// fails and ppClosestMatch is non- <c>NULL</c>, the method sets *ppClosestMatch to <c>NULL</c>. For information about
			/// <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>S_OK</term>
			/// <term>Succeeded and the audio endpoint device supports the specified stream format.</term>
			/// </item>
			/// <item>
			/// <term>S_FALSE</term>
			/// <term>Succeeded with a closest match to the specified format.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
			/// <term>Succeeded but the specified format is not supported in exclusive mode.</term>
			/// </item>
			/// </list>
			/// <para>If the operation fails, possible return codes include, but are not limited to, the values shown in the following table.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter pFormat is NULL, or ppClosestMatch is NULL and ShareMode is AUDCLNT_SHAREMODE_SHARED.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>Parameter ShareMode is a value other than AUDCLNT_SHAREMODE_SHARED or AUDCLNT_SHAREMODE_EXCLUSIVE.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method provides a way for a client to determine, before calling IAudioClient::Initialize, whether the audio engine
			/// supports a particular stream format.
			/// </para>
			/// <para>
			/// For exclusive mode, <c>IsFormatSupported</c> returns S_OK if the audio endpoint device supports the caller-specified format,
			/// or it returns AUDCLNT_E_UNSUPPORTED_FORMAT if the device does not support the format. The ppClosestMatch parameter can be
			/// <c>NULL</c>. If it is not <c>NULL</c>, the method writes <c>NULL</c> to *ppClosestMatch.
			/// </para>
			/// <para>
			/// For shared mode, if the audio engine supports the caller-specified format, <c>IsFormatSupported</c> sets
			/// <c>*ppClosestMatch</c> to <c>NULL</c> and returns S_OK. If the audio engine does not support the caller-specified format but
			/// does support a similar format, the method retrieves the similar format through the ppClosestMatch parameter and returns
			/// S_FALSE. If the audio engine does not support the caller-specified format or any similar format, the method sets
			/// *ppClosestMatch to <c>NULL</c> and returns AUDCLNT_E_UNSUPPORTED_FORMAT.
			/// </para>
			/// <para>
			/// In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the
			/// IAudioClient::GetMixFormat method. In addition, the audio engine might support similar formats that have the same sample
			/// rate and number of channels as the mix format but differ in the representation of audio sample values. The audio engine
			/// represents sample values internally as floating-point numbers, but if the caller-specified format represents sample values
			/// as integers, the audio engine typically can convert between the integer sample values and its internal floating-point representation.
			/// </para>
			/// <para>
			/// The audio engine might be able to support an even wider range of shared-mode formats if the installation package for the
			/// audio device includes a local effects (LFX) audio processing object (APO) that can handle format conversions. An LFX APO is
			/// a software module that performs device-specific processing of an audio stream. The audio graph builder in the Windows audio
			/// service inserts the LFX APO into the stream between each client and the audio engine. When a client calls the
			/// <c>IsFormatSupported</c> method and the method determines that an LFX APO is installed for use with the device, the method
			/// directs the query to the LFX APO, which indicates whether it supports the caller-specified format.
			/// </para>
			/// <para>
			/// For example, a particular LFX APO might accept a 6-channel surround sound stream from a client and convert the stream to a
			/// stereo format that can be played through headphones. Typically, an LFX APO supports only client formats with sample rates
			/// that match the sample rate of the mix format.
			/// </para>
			/// <para>
			/// For more information about APOs, see the white papers titled "Custom Audio Effects in Windows Vista" and "Reusing the
			/// Windows Vista Audio System Effects" at the Audio Device Technologies for Windows website. For more information about the
			/// <c>IsFormatSupported</c> method, see Device Formats.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-isformatsupported HRESULT
			// IsFormatSupported( AUDCLNT_SHAREMODE ShareMode, const WAVEFORMATEX *pFormat, WAVEFORMATEX **ppClosestMatch );
			[PreserveSig]
			new HRESULT IsFormatSupported([In] AUDCLNT_SHAREMODE ShareMode, [In] IntPtr pFormat, out SafeCoTaskMemHandle ppClosestMatch);

			/// <summary>
			/// The <c>GetMixFormat</c> method retrieves the stream format that the audio engine uses for its internal processing of
			/// shared-mode streams.
			/// </summary>
			/// <param name="ppDeviceFormat">
			/// Pointer to a pointer variable into which the method writes the address of the mix format. This parameter must be a valid,
			/// non- <c>NULL</c> pointer to a pointer variable. The method writes the address of a <c>WAVEFORMATEX</c> (or
			/// <c>WAVEFORMATEXTENSIBLE</c>) structure to this variable. The method allocates the storage for the structure. The caller is
			/// responsible for freeing the storage, when it is no longer needed, by calling the <c>CoTaskMemFree</c> function. If the
			/// <c>GetMixFormat</c> call fails, *ppDeviceFormat is <c>NULL</c>. For information about <c>WAVEFORMATEX</c>,
			/// <c>WAVEFORMATEXTENSIBLE</c>, and <c>CoTaskMemFree</c>, see the Windows SDK documentation.
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_POINTER</term>
			/// <term>Parameter ppDeviceFormat is NULL.</term>
			/// </item>
			/// <item>
			/// <term>E_OUTOFMEMORY</term>
			/// <term>Out of memory.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The client can call this method before calling the IAudioClient::Initialize method. When creating a shared-mode stream for
			/// an audio endpoint device, the <c>Initialize</c> method always accepts the stream format obtained from a <c>GetMixFormat</c>
			/// call on the same device.
			/// </para>
			/// <para>
			/// The mix format is the format that the audio engine uses internally for digital processing of shared-mode streams. This
			/// format is not necessarily a format that the audio endpoint device supports. Thus, the caller might not succeed in creating
			/// an exclusive-mode stream with a format obtained by calling <c>GetMixFormat</c>.
			/// </para>
			/// <para>
			/// For example, to facilitate digital audio processing, the audio engine might use a mix format that represents samples as
			/// floating-point values. If the device supports only integer PCM samples, then the engine converts the samples to or from
			/// integer PCM values at the connection between the device and the engine. However, to avoid resampling, the engine might use a
			/// mix format with a sample rate that the device supports.
			/// </para>
			/// <para>
			/// To determine whether the <c>Initialize</c> method can create a shared-mode or exclusive-mode stream with a particular
			/// format, call the IAudioClient::IsFormatSupported method.
			/// </para>
			/// <para>
			/// By itself, a <c>WAVEFORMATEX</c> structure cannot specify the mapping of channels to speaker positions. In addition,
			/// although <c>WAVEFORMATEX</c> specifies the size of the container for each audio sample, it cannot specify the number of bits
			/// of precision in a sample (for example, 20 bits of precision in a 24-bit container). However, the <c>WAVEFORMATEXTENSIBLE</c>
			/// structure can specify both the mapping of channels to speakers and the number of bits of precision in each sample. For this
			/// reason, the <c>GetMixFormat</c> method retrieves a format descriptor that is in the form of a <c>WAVEFORMATEXTENSIBLE</c>
			/// structure instead of a standalone <c>WAVEFORMATEX</c> structure. Through the ppDeviceFormat parameter, the method outputs a
			/// pointer to the <c>WAVEFORMATEX</c> structure that is embedded at the start of this <c>WAVEFORMATEXTENSIBLE</c> structure.
			/// For more information about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
			/// </para>
			/// <para>
			/// For more information about the <c>GetMixFormat</c> method, see Device Formats. For code examples that call
			/// <c>GetMixFormat</c>, see the following topics:
			/// </para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getmixformat HRESULT GetMixFormat(
			// WAVEFORMATEX **ppDeviceFormat );
			[PreserveSig]
			new HRESULT GetMixFormat(out SafeCoTaskMemHandle ppDeviceFormat);

			/// <summary>
			/// The <c>GetDevicePeriod</c> method retrieves the length of the periodic interval separating successive processing passes by
			/// the audio engine on the data in the endpoint buffer.
			/// </summary>
			/// <param name="phnsDefaultDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the default interval between
			/// periodic processing passes by the audio engine. The time is expressed in 100-nanosecond units. For information about
			/// <c>REFERENCE_TIME</c>, see the Windows SDK documentation.
			/// </param>
			/// <param name="phnsMinimumDevicePeriod">
			/// Pointer to a REFERENCE_TIME variable into which the method writes a time value specifying the minimum interval between
			/// periodic processing passes by the audio endpoint device. The time is expressed in 100-nanosecond units.
			/// </param>
			/// <remarks>
			/// <para>The client can call this method before calling the IAudioClient::Initialize method.</para>
			/// <para>
			/// The phnsDefaultDevicePeriod parameter specifies the default scheduling period for a shared-mode stream. The
			/// phnsMinimumDevicePeriod parameter specifies the minimum scheduling period for an exclusive-mode stream.
			/// </para>
			/// <para>
			/// At least one of the two parameters, phnsDefaultDevicePeriod and phnsMinimumDevicePeriod, must be non- <c>NULL</c> or the
			/// method returns immediately with error code E_POINTER. If both parameters are non- <c>NULL</c>, then the method outputs both
			/// the default and minimum periods.
			/// </para>
			/// <para>
			/// For a shared-mode stream, the audio engine periodically processes the data in the endpoint buffer, which the engine shares
			/// with the client application. The engine schedules itself to perform these processing passes at regular intervals.
			/// </para>
			/// <para>
			/// The period between processing passes by the audio engine is fixed for a particular audio endpoint device and represents the
			/// smallest processing quantum for the audio engine. This period plus the stream latency between the buffer and endpoint device
			/// represents the minimum possible latency that an audio application can achieve.
			/// </para>
			/// <para>
			/// The client has the option of scheduling its periodic processing thread to run at the same time interval as the audio engine.
			/// In this way, the client can achieve the smallest possible latency for a shared-mode stream. However, in an application for
			/// which latency is less important, the client can reduce the process-switching overhead on the CPU by scheduling its
			/// processing passes to occur less frequently. In this case, the endpoint buffer must be proportionally larger to compensate
			/// for the longer period between processing passes.
			/// </para>
			/// <para>
			/// The client determines the buffer size during its call to the IAudioClient::Initialize method. For a shared-mode stream, if
			/// the client passes this method an hnsBufferDuration parameter value of 0, the method assumes that the periods for the client
			/// and audio engine are guaranteed to be equal, and the method will allocate a buffer small enough to achieve the minimum
			/// possible latency. (In fact, any hnsBufferDuration value between 0 and the sum of the audio engine's period and device
			/// latency will have the same result.) Similarly, for an exclusive-mode stream, if the client sets hnsBufferDuration to 0, the
			/// method assumes that the period of the client is set to the minimum period of the audio endpoint device, and the method will
			/// allocate a buffer small enough to achieve the minimum possible latency.
			/// </para>
			/// <para>
			/// If the client chooses to run its periodic processing thread less often, at the cost of increased latency, it can do so as
			/// long as it creates an endpoint buffer during the IAudioClient::Initialize call that is sufficiently large.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getdeviceperiod HRESULT
			// GetDevicePeriod( REFERENCE_TIME *phnsDefaultDevicePeriod, REFERENCE_TIME *phnsMinimumDevicePeriod );
			new void GetDevicePeriod([Out, Optional] out long phnsDefaultDevicePeriod, out long phnsMinimumDevicePeriod);

			/// <summary>The <c>Start</c> method starts the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Start</c> is a control method that the client calls to start the audio stream. Starting the stream causes the
			/// IAudioClient object to begin streaming data between the endpoint buffer and the audio engine. It also causes the stream's
			/// audio clock to resume counting from its current position.
			/// </para>
			/// <para>
			/// The first time this method is called following initialization of the stream, the IAudioClient object's stream position
			/// counter begins at 0. Otherwise, the clock resumes from its position at the time that the stream was last stopped. Resetting
			/// the stream forces the stream position back to 0.
			/// </para>
			/// <para>
			/// To avoid start-up glitches with rendering streams, clients should not call <c>Start</c> until the audio engine has been
			/// initially loaded with data by calling the IAudioRenderClient::GetBuffer and IAudioRenderClient::ReleaseBuffer methods on the
			/// rendering interface.
			/// </para>
			/// <para>For code examples that call the <c>Start</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-start HRESULT Start();
			new void Start();

			/// <summary>The <c>Stop</c> method stops the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Stop</c> is a control method that stops a running audio stream. This method stops data from streaming through the
			/// client's connection with the audio engine. Stopping the stream freezes the stream's audio clock at its current stream
			/// position. A subsequent call to IAudioClient::Start causes the stream to resume running from that position. If necessary, the
			/// client can call the IAudioClient::Reset method to reset the position while the stream is stopped.
			/// </para>
			/// <para>For code examples that call the <c>Stop</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-stop HRESULT Stop();
			new void Stop();

			/// <summary>The <c>Reset</c> method resets the audio stream.</summary>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// <c>Reset</c> is a control method that the client calls to reset a stopped audio stream. Resetting the stream flushes all
			/// pending data and resets the audio clock stream position to 0. This method fails if it is called on a stream that is not stopped.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-reset HRESULT Reset();
			new void Reset();

			/// <summary>
			/// The <c>SetEventHandle</c> method sets the event handle that the system signals when an audio buffer is ready to be processed
			/// by the client.
			/// </summary>
			/// <param name="eventHandle">The event handle.</param>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>
			/// During stream initialization, the client can, as an option, enable event-driven buffering. To do so, the client calls the
			/// IAudioClient::Initialize method with the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag set. After enabling event-driven buffering,
			/// and before calling the IAudioClient::Start method to start the stream, the client must call <c>SetEventHandle</c> to
			/// register the event handle that the system will signal each time a buffer becomes ready to be processed by the client.
			/// </para>
			/// <para>The event handle should be in the nonsignaled state at the time that the client calls the Start method.</para>
			/// <para>
			/// If the client has enabled event-driven buffering of a stream, but the client calls the Start method for that stream without
			/// first calling <c>SetEventHandle</c>, the <c>Start</c> call will fail and return an error code.
			/// </para>
			/// <para>
			/// If the client does not enable event-driven buffering of a stream but attempts to set an event handle for the stream by
			/// calling <c>SetEventHandle</c>, the call will fail and return an error code.
			/// </para>
			/// <para>For a code example that calls the <c>SetEventHandle</c> method, see Exclusive-Mode Streams.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-seteventhandle HRESULT
			// SetEventHandle( HANDLE eventHandle );
			new void SetEventHandle(IntPtr eventHandle);

			/// <summary>The <c>GetService</c> method accesses additional services from the audio client object.</summary>
			/// <param name="riid">
			/// <para>The interface ID for the requested service. The client should set this parameter to one of the following REFIID values:</para>
			/// <para>IID_IAudioCaptureClient</para>
			/// <para>IID_IAudioClock</para>
			/// <para>IID_IAudioRenderClient</para>
			/// <para>IID_IAudioSessionControl</para>
			/// <para>IID_IAudioStreamVolume</para>
			/// <para>IID_IChannelAudioVolume</para>
			/// <para>IID_IMFTrustedOutput</para>
			/// <para>IID_ISimpleAudioVolume</para>
			/// <para>For more information, see Remarks.</para>
			/// </param>
			/// <returns>
			/// Pointer to a pointer variable into which the method writes the address of an instance of the requested interface. Through
			/// this method, the caller obtains a counted reference to the interface. The caller is responsible for releasing the interface,
			/// when it is no longer needed, by calling the interface's <c>Release</c> method. If the <c>GetService</c> call fails, *ppv is <c>NULL</c>.
			/// </returns>
			/// <remarks>
			/// <para>
			/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
			/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
			/// </para>
			/// <para>The <c>GetService</c> method supports the following service interfaces:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>IAudioCaptureClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioClock</term>
			/// </item>
			/// <item>
			/// <term>IAudioRenderClient</term>
			/// </item>
			/// <item>
			/// <term>IAudioSessionControl</term>
			/// </item>
			/// <item>
			/// <term>IAudioStreamVolume</term>
			/// </item>
			/// <item>
			/// <term>IChannelAudioVolume</term>
			/// </item>
			/// <item>
			/// <term>IMFTrustedOutput</term>
			/// </item>
			/// <item>
			/// <term>ISimpleAudioVolume</term>
			/// </item>
			/// </list>
			/// <para>
			/// In Windows 7, a new service identifier, <c>IID_IMFTrustedOutput</c>, has been added that facilitates the use of output trust
			/// authority (OTA) objects. These objects can operate inside or outside the Media Foundation's protected media path (PMP) and
			/// send content outside the Media Foundation pipeline. If the caller is outside PMP, then the OTA may not operate in the PMP,
			/// and the protection settings are less robust. OTAs must implement the IMFTrustedOutput interface. By passing
			/// <c>IID_IMFTrustedOutput</c> in <c>GetService</c>, an application can retrieve a pointer to the object's
			/// <c>IMFTrustedOutput</c> interface. For more information about protected objects and <c>IMFTrustedOutput</c>, see "Protected
			/// Media Path" in the Media Foundation SDK documentation.
			/// </para>
			/// <para>For information about using trusted audio drivers in OTAs, see Protected User Mode Audio (PUMA).</para>
			/// <para>
			/// Note that activating IMFTrustedOutput through this mechanism works regardless of whether the caller is running in PMP.
			/// However, if the caller is not running in a protected process (that is, the caller is not within Media Foundation's PMP) then
			/// the audio OTA might not operate in the PMP and the protection settings are less robust.
			/// </para>
			/// <para>
			/// To obtain the interface ID for a service interface, use the <c>__uuidof</c> operator. For example, the interface ID of
			/// <c>IAudioCaptureClient</c> is defined as follows:
			/// </para>
			/// <para>For information about the <c>__uuidof</c> operator, see the Windows SDK documentation.</para>
			/// <para>
			/// To release the <c>IAudioClient</c> object and free all its associated resources, the client must release all references to
			/// any service objects that were created by calling <c>GetService</c>, in addition to calling <c>Release</c> on the
			/// <c>IAudioClient</c> interface itself. The client must release a service from the same thread that releases the
			/// <c>IAudioClient</c> object.
			/// </para>
			/// <para>
			/// The <c>IAudioSessionControl</c>, <c>IAudioStreamVolume</c>, <c>IChannelAudioVolume</c>, and <c>ISimpleAudioVolume</c>
			/// interfaces control and monitor aspects of audio sessions and shared-mode streams. These interfaces do not work with
			/// exclusive-mode streams.
			/// </para>
			/// <para>For code examples that call the <c>GetService</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Capturing a Stream</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getservice HRESULT GetService(
			// REFIID riid, void **ppv );
			[return: MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 0)]
			new object GetService(in Guid riid);

			/// <summary>
			/// The <c>IsOffloadCapable</c> method retrieves information about whether or not the endpoint on which a stream is created is
			/// capable of supporting an offloaded audio stream.
			/// </summary>
			/// <param name="Category">An enumeration that specifies the category of an audio stream.</param>
			/// <returns>
			/// A pointer to a Boolean value. <c>TRUE</c> indicates that the endpoint is offload-capable. <c>FALSE</c> indicates that the
			/// endpoint is not offload-capable.
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-isoffloadcapable HRESULT
			// IsOffloadCapable( AUDIO_STREAM_CATEGORY Category, BOOL *pbOffloadCapable );
			[return: MarshalAs(UnmanagedType.Bool)]
			new bool IsOffloadCapable(AUDIO_STREAM_CATEGORY Category);

			/// <summary>Sets the properties of the audio stream by populating an AudioClientProperties structure.</summary>
			/// <param name="pProperties">Pointer to an AudioClientProperties structure.</param>
			/// <remarks>
			/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
			/// <c>IAudioClient2::SetClientProperties</c> and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must
			/// specify the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to IAudioClient::Initialize.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-setclientproperties HRESULT
			// SetClientProperties( const AudioClientProperties *pProperties );
			new void SetClientProperties(in AudioClientProperties pProperties);

			/// <summary>
			/// The <c>GetBufferSizeLimits</c> method returns the buffer size limits of the hardware audio engine in 100-nanosecond units.
			/// </summary>
			/// <param name="pFormat">A pointer to the target format that is being queried for the buffer size limit.</param>
			/// <param name="bEventDriven">Boolean value to indicate whether or not the stream can be event-driven.</param>
			/// <param name="phnsMinBufferDuration">
			/// Returns a pointer to the minimum buffer size (in 100-nanosecond units) that is required for the underlying hardware audio
			/// engine to operate at the format specified in the pFormat parameter, without frequent audio glitching.
			/// </param>
			/// <param name="phnsMaxBufferDuration">
			/// Returns a pointer to the maximum buffer size (in 100-nanosecond units) that the underlying hardware audio engine can support
			/// for the format specified in the pFormat parameter.
			/// </param>
			/// <remarks>The <c>GetBufferSizeLimits</c> method is a device-facing method and does not require prior audio stream initialization.</remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient2-getbuffersizelimits HRESULT
			// GetBufferSizeLimits( const WAVEFORMATEX *pFormat, BOOL bEventDriven, REFERENCE_TIME *phnsMinBufferDuration, REFERENCE_TIME
			// *phnsMaxBufferDuration );
			new void GetBufferSizeLimits(in WAVEFORMATEX pFormat, [MarshalAs(UnmanagedType.Bool)] bool bEventDriven, out long phnsMinBufferDuration, out long phnsMaxBufferDuration);

			/// <summary>
			/// Returns the range of periodicities supported by the engine for the specified stream format. The periodicity of the engine is
			/// the rate at which the engine wakes an event-driven audio client to transfer audio data to or from the engine. The values
			/// returned depend on the characteristics of the audio client as specified through a previous call to IAudioClient2::SetClientProperties.
			/// </summary>
			/// <param name="pFormat">
			/// <para>Type: <c>const WAVEFORMATEX*</c></para>
			/// <para>The stream format for which the supported periodicities are queried.</para>
			/// </param>
			/// <param name="pDefaultPeriodInFrames">
			/// <para>Type: <c>UINT32*</c></para>
			/// <para>The default period with which the engine will wake the client for transferring audio samples</para>
			/// </param>
			/// <param name="pFundamentalPeriodInFrames">
			/// <para>Type: <c>UINT32*</c></para>
			/// <para>
			/// The fundamental period with which the engine will wake the client for transferring audio samples. When setting the audio
			/// engine periodicity, you must use an integral multiple of this value.
			/// </para>
			/// </param>
			/// <param name="pMinPeriodInFrames">
			/// <para>Type: <c>UINT32*</c></para>
			/// <para>The shortest period, in audio frames, with which the audio engine will wake the client for transferring audio samples.</para>
			/// </param>
			/// <param name="pMaxPeriodInFrames">
			/// <para>Type: <c>UINT32*</c></para>
			/// <para>The longest period, in audio frames, with which the audio engine will wake the client for transferring audio samples.</para>
			/// </param>
			/// <remarks>
			/// <para>
			/// Audio clients request a specific periodicity from the audio engine with the PeriodInFrames parameter to
			/// IAudioClient3::InitializeSharedAudioStream. The value of PeriodInFrames must be an integral multiple of the value returned
			/// in the pFundamentalPeriodInFrames parameter. PeriodInFrames must also be greater than or equal to the value returned in
			/// pMinPeriodInFrames and less than or equal to the value of pMaxPeriodInFrames.
			/// </para>
			/// <para>For example, for a 44100 kHz format, <c>GetSharedModeEnginePeriod</c> might return:</para>
			/// <list type="bullet">
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// </list>
			/// <para>
			/// Allowed values for the PeriodInFrames parameter to <c>InitializeSharedAudioStream</c> would include 48 and 448. They would
			/// also include things like 96 and 128.
			/// </para>
			/// <para>
			/// They would NOT include 4 (which is smaller than the minimum allowed value) or 98 (which is not a multiple of the
			/// fundamental) or 1000 (which is larger than the maximum allowed value).
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-getsharedmodeengineperiod HRESULT
			// GetSharedModeEnginePeriod( const WAVEFORMATEX *pFormat, UINT32 *pDefaultPeriodInFrames, UINT32 *pFundamentalPeriodInFrames,
			// UINT32 *pMinPeriodInFrames, UINT32 *pMaxPeriodInFrames );
			void GetSharedModeEnginePeriod(in WAVEFORMATEX pFormat, out uint pDefaultPeriodInFrames, out uint pFundamentalPeriodInFrames, out uint pMinPeriodInFrames, out uint pMaxPeriodInFrames);

			/// <summary>
			/// Returns the current format and periodicity of the audio engine. This method enables audio clients to match the current
			/// period of the audio engine.
			/// </summary>
			/// <param name="ppFormat">
			/// <para>Type: <c>WAVEFORMATEX**</c></para>
			/// <para>The current device format that is being used by the audio engine.</para>
			/// </param>
			/// <param name="pCurrentPeriodInFrames">
			/// <para>Type: <c>UINT32*</c></para>
			/// <para>The current period of the audio engine, in audio frames.</para>
			/// </param>
			/// <remarks>
			/// <para>
			/// <c>Note</c> The values returned by this method are instantaneous values and may be invalid immediately after the call
			/// returns if, for example, another audio client sets the periodicity or format to a different value.
			/// </para>
			/// <para>
			/// <c>Note</c> The caller is responsible for calling CoTaskMemFree to deallocate the memory of the <c>WAVEFORMATEX</c>
			/// structure populated by this method.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-getcurrentsharedmodeengineperiod
			// HRESULT GetCurrentSharedModeEnginePeriod( WAVEFORMATEX **ppFormat, UINT32 *pCurrentPeriodInFrames );
			void GetCurrentSharedModeEnginePeriod(out SafeCoTaskMemHandle ppFormat, out uint pCurrentPeriodInFrames);

			/// <summary>Initializes a shared stream with the specified periodicity.</summary>
			/// <param name="StreamFlags">
			/// <para>Type: <c>DWORD</c></para>
			/// <para>
			/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of
			/// the supported AUDCLNT_STREAMFLAGS_XXX Constants or AUDCLNT_SESSIONFLAGS_XXX Constants. The supported AUDCLNT_STREAMFLAGS_XXX
			/// Constants for this parameter when using this method are:
			/// </para>
			/// <list type="bullet">
			/// <item>
			/// <term>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY</term>
			/// </item>
			/// </list>
			/// </param>
			/// <param name="PeriodInFrames">
			/// <para>Type: <c>UINT32</c></para>
			/// <para>
			/// Periodicity requested by the client. This value must be an integral multiple of the value returned in the
			/// pFundamentalPeriodInFrames parameter to IAudioClient3::GetSharedModeEnginePeriod. PeriodInFrames must also be greater than
			/// or equal to the value returned in pMinPeriodInFrames and less than or equal to the value returned in pMaxPeriodInFrames.
			/// </para>
			/// </param>
			/// <param name="pFormat">
			/// <para>Type: <c>const WAVEFORMATEX*</c></para>
			/// <para>
			/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type WAVEFORMATEX or <c></c>
			/// WAVEFORMATEXTENSIBLE. For more information, see the Remarks section for IAudioClient::Initialize.
			/// </para>
			/// </param>
			/// <param name="AudioSessionGuid">
			/// <para>Type: <c>LPCGUID</c></para>
			/// <para>
			/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs
			/// to. If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the
			/// GUID does not identify an existing session, the method opens a new session and adds the stream to that session. The stream
			/// remains a member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a
			/// pointer to a GUID_NULL value.
			/// </para>
			/// </param>
			/// <remarks>
			/// <para>
			/// Unlike IAudioClient::Initialize, this method does not allow you to specify a buffer size. The buffer size is computed based
			/// on the periodicity requested with the PeriodInFrames parameter. It is the client app's responsibility to ensure that audio
			/// samples are transferred in and out of the buffer in a timely manner.
			/// </para>
			/// <para>
			/// Audio clients should check for allowed values for the PeriodInFrames parameter by calling
			/// IAudioClient3::GetSharedModeEnginePeriod. The value of PeriodInFrames must be an integral multiple of the value returned in
			/// the pFundamentalPeriodInFrames parameter. PeriodInFrames must also be greater than or equal to the value returned in
			/// pMinPeriodInFrames and less than or equal to the value of pMaxPeriodInFrames.
			/// </para>
			/// <para>For example, for a 44100 kHz format, <c>GetSharedModeEnginePeriod</c> might return:</para>
			/// <list type="bullet">
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// <item>
			/// <term/>
			/// </item>
			/// </list>
			/// <para>
			/// Allowed values for the PeriodInFrames parameter to <c>InitializeSharedAudioStream</c> would include 48 and 448. They would
			/// also include things like 96 and 128.
			/// </para>
			/// <para>
			/// They would NOT include 4 (which is smaller than the minimum allowed value) or 98 (which is not a multiple of the
			/// fundamental) or 1000 (which is larger than the maximum allowed value).
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-initializesharedaudiostream
			// HRESULT InitializeSharedAudioStream( DWORD StreamFlags, UINT32 PeriodInFrames, const WAVEFORMATEX *pFormat, LPCGUID
			// AudioSessionGuid );
			void InitializeSharedAudioStream(AUDCLNT_STREAMFLAGS StreamFlags, [In] uint PeriodInFrames, [In] IntPtr pFormat, [In, Optional] in Guid AudioSessionGuid);
		}

		/// <summary>
		/// <para>
		/// The <c>IAudioClock</c> interface enables a client to monitor a stream's data rate and the current position in the stream. The
		/// client obtains a reference to the <c>IAudioClock</c> interface of a stream object by calling the IAudioClient::GetService method
		/// with parameter riid set to REFIID IID_IAudioClock.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioClock</c> interface instance, the client must call the interface's Release method from the same
		/// thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclock
		[PInvokeData("audioclient.h", MSDNShortId = "dbec9468-b555-42a0-a988-dec3a66c9f96")]
		[ComImport, Guid("CD63314F-3FBA-4a1b-812C-EF96358728E7"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClock
		{
			/// <summary>The <c>GetFrequency</c> method gets the device frequency.</summary>
			/// <returns>A <c>UINT64</c> variable into which the method writes the device frequency. For more information, see Remarks.</returns>
			/// <remarks>
			/// <para>
			/// The device frequency is the frequency generated by the hardware clock in the audio device. This method reports the device
			/// frequency in units that are compatible with those of the device position that the IAudioClock::GetPosition method reports.
			/// For example, if, for a particular stream, the <c>GetPosition</c> method expresses the position p as a byte offset, the
			/// <c>GetFrequency</c> method expresses the frequency f in bytes per second. For any stream, the offset in seconds from the
			/// start of the stream can always be reliably calculated as p/f regardless of the units in which p and f are expressed.
			/// </para>
			/// <para>
			/// In Windows Vista, the device frequency reported by successive calls to <c>GetFrequency</c> never changes during the lifetime
			/// of a stream.
			/// </para>
			/// <para>
			/// If the clock generated by an audio device runs at a nominally constant frequency, the frequency might still vary slightly
			/// over time due to drift or jitter with respect to a reference clock. The reference clock might be a wall clock or the system
			/// clock used by the <c>QueryPerformanceCounter</c> function. The <c>GetFrequency</c> method ignores such variations and simply
			/// reports a constant frequency. However, the position reported by the <c>IAudioClient::GetPosition</c> method takes all such
			/// variations into account to report an accurate position value each time it is called. For more information about
			/// <c>QueryPerformanceCounter</c>, see the Windows SDK documentation.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclock-getfrequency HRESULT GetFrequency(
			// UINT64 *pu64Frequency );
			ulong GetFrequency();

			/// <summary>The <c>GetPosition</c> method gets the current device position.</summary>
			/// <param name="pu64Position">
			/// Pointer to a <c>UINT64</c> variable into which the method writes the device position. The device position is the offset from
			/// the start of the stream to the current position in the stream. However, the units in which this offset is expressed are
			/// undefined—the device position value has meaning only in relation to the frequency reported by the IAudioClock::GetFrequency
			/// method. For more information, see Remarks.
			/// </param>
			/// <param name="pu64QPCPosition">
			/// Pointer to a <c>UINT64</c> variable into which the method writes the value of the performance counter at the time that the
			/// audio endpoint device read the device position (*pu64Position) in response to the <c>GetPosition</c> call. The method
			/// converts the counter value to 100-nanosecond time units before writing it to *pu64QPCPosition. This parameter can be
			/// <c>NULL</c> if the client does not require the performance counter value.
			/// </param>
			/// <remarks>
			/// <para>
			/// Rendering or capture clients that need to expose a clock based on the stream's current playback or record position can use
			/// this method to derive that clock.
			/// </para>
			/// <para>This method retrieves two correlated stream-position values:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>
			/// Device position. The client obtains the device position through output parameter pu64Position. This is the stream position
			/// of the sample that is currently playing through the speakers (for a rendering stream) or being recorded through the
			/// microphone (for a capture stream).
			/// </term>
			/// </item>
			/// <item>
			/// <term>
			/// Performance counter. The client obtains the performance counter through output parameter pu64QPCPosition. This is the
			/// counter value that the method obtained by calling the <c>QueryPerformanceCounter</c> function at the time that the audio
			/// endpoint device recorded the stream position (*pu64Position). Note that <c>GetPosition</c> converts the counter value to
			/// 100-nanosecond time units.
			/// </term>
			/// </item>
			/// </list>
			/// <para>
			/// The device position is meaningless unless it is combined with the device frequency reported by the
			/// <c>IAudioClock::GetFrequency</c> method. The reason is that the units in which the device positions for different streams
			/// are expressed might vary according to factors such as whether the stream was opened in shared mode or exclusive mode.
			/// However, the frequency f obtained from <c>GetFrequency</c> is always expressed in units that are compatible with those of
			/// the device position p. Thus, the stream-relative offset in seconds can always be calculated as p/f.
			/// </para>
			/// <para>
			/// The device position is a stream-relative offset. That is, it is specified as an offset from the start of the stream. The
			/// device position can be thought of as an offset into an idealized buffer that contains the entire stream and is contiguous
			/// from beginning to end.
			/// </para>
			/// <para>
			/// Given the device position and the performance counter at the time of the <c>GetPosition</c> call, the client can provide a
			/// more timely estimate of the device position at a slightly later time by calling <c>QueryPerformanceCounter</c> to obtain the
			/// current performance counter, and extrapolating the device position based on how far the counter has advanced since the
			/// original device position was recorded. The client can call the <c>QueryPerformanceFrequency</c> function to determine the
			/// frequency of the clock that increments the counter. Before comparing the raw counter value obtained from
			/// <c>QueryPerformanceCounter</c> to the value written to *pu64QPCPosition by <c>GetPosition</c>, convert the raw counter value
			/// to 100-nanosecond time units as follows:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Multiply the raw counter value by 10,000,000.</term>
			/// </item>
			/// <item>
			/// <term>Divide the result by the counter frequency obtained from <c>QueryPerformanceFrequency</c>.</term>
			/// </item>
			/// </list>
			/// <para>
			/// For more information about <c>QueryPerformanceCounter</c> and <c>QueryPerformanceFrequency</c>, see the Windows SDK documentation.
			/// </para>
			/// <para>
			/// Immediately following creation of a new stream, the device position is 0. Following a call to the IAudioClient::Start
			/// method, the device position increments at a uniform rate. The IAudioClient::Stop method freezes the device position, and a
			/// subsequent <c>Start</c> call causes the device position to resume incrementing from its value at the time of the <c>Stop</c>
			/// call. A call to IAudioClient::Reset, which should only occur while the stream is stopped, resets the device position to 0.
			/// </para>
			/// <para>
			/// When a new or reset rendering stream initially begins running, its device position might remain 0 for a few milliseconds
			/// until the audio data has had time to propagate from the endpoint buffer to the rendering endpoint device. The device
			/// position changes from 0 to a nonzero value when the data begins playing through the device.
			/// </para>
			/// <para>
			/// Successive device readings are monotonically increasing. Although the device position might not change between two
			/// successive readings, the device position never decreases from one reading to the next.
			/// </para>
			/// <para>
			/// The pu64Position parameter must be a valid, non- <c>NULL</c> pointer or the method will fail and return error code E_POINTER.
			/// </para>
			/// <para>
			/// Position measurements might occasionally be delayed by intermittent, high-priority events. These events might be unrelated
			/// to audio. In the case of an exclusive-mode stream, the method can return S_FALSE instead of S_OK if the method succeeds but
			/// the duration of the call is long enough to detract from the accuracy of the reported position. When this occurs, the caller
			/// has the option of calling the method again to attempt to retrieve a more accurate position (as indicated by return value
			/// S_OK). However, the caller should avoid performing this test in an infinite loop in the event that the method consistently
			/// returns S_FALSE.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclock-getposition HRESULT GetPosition(
			// UINT64 *pu64Position, UINT64 *pu64QPCPosition );
			void GetPosition(out ulong pu64Position, out ulong pu64QPCPosition);

			/// <summary>The <c>GetCharacteristics</c> method is reserved for future use.</summary>
			/// <returns>
			/// Pointer to a <c>DWORD</c> variable into which the method writes a value that indicates the characteristics of the audio clock.
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclock-getcharacteristics HRESULT
			// GetCharacteristics( DWORD *pdwCharacteristics );
			uint GetCharacteristics();
		}

		/// <summary>
		/// <para>The <c>IAudioClock2</c> interface is used to get the current device position.</para>
		/// <para>
		/// To get a reference to the <c>IAudioClock2</c> interface, the application must call <c>IAudioClock::QueryInterface</c> to request
		/// the interface pointer from the stream object's IAudioClock interface.
		/// </para>
		/// <para>
		/// The client obtains a reference to the <c>IAudioClock</c> interface of a stream object by calling the IAudioClient::GetService
		/// method with parameter riid set to REFIID IID_IAudioClock.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioClock2</c> interface instance, the client must call the interface's <c>Release</c> method from the
		/// same thread as the call to IAudioClient::GetService that created the object.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclock2
		[PInvokeData("audioclient.h", MSDNShortId = "4820c93a-a5d8-4ab9-aefc-9377fc76e745")]
		[ComImport, Guid("6f49ff73-6727-49ac-a008-d98cf5e70048"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClock2
		{
			/// <summary>The <c>GetDevicePosition</c> method gets the current device position, in frames, directly from the hardware.</summary>
			/// <param name="DevicePosition">
			/// Receives the device position, in frames. The received position is an unprocessed value that the method obtains directly from
			/// the hardware. For more information, see Remarks.
			/// </param>
			/// <param name="QPCPosition">
			/// Receives the value of the performance counter at the time that the audio endpoint device read the device position retrieved
			/// in the DevicePosition parameter in response to the <c>GetDevicePosition</c> call. <c>GetDevicePosition</c> converts the
			/// counter value to 100-nanosecond time units before writing it to QPCPosition. QPCPosition can be <c>NULL</c> if the client
			/// does not require the performance counter value. For more information, see Remarks.
			/// </param>
			/// <remarks>
			/// <para>This method only applies to shared-mode streams.</para>
			/// <para>This method retrieves two correlated stream-position values:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>
			/// Device position. The client retrieves the unprocessed device position in DevicePosition. This is the stream position of the
			/// sample that is currently playing through the speakers (for a rendering stream) or being recorded through the microphone (for
			/// a capture stream). The sampling rate of the device endpoint may be different from the sampling rate of the mix format used
			/// by the client. To retrieve the device position from the client, call IAudioClock::GetPosition.
			/// </term>
			/// </item>
			/// <item>
			/// <term>
			/// Performance counter. The client retrieves the performance counter in QPCPosition. <c>GetDevicePosition</c> obtains the
			/// counter value by calling the <c>QueryPerformanceCounter</c> function at the time that the audio endpoint device stores the
			/// stream position in the DevicePosition parameter of the <c>GetDevicePosition</c> method. <c>GetDevicePosition</c> converts
			/// the counter value to 100-nanosecond time units. For more information about <c>QueryPerformanceCounter</c> and
			/// <c>QueryPerformanceFrequency</c>, see the Windows SDK documentation.
			/// </term>
			/// </item>
			/// </list>
			/// <para>
			/// Given the device position and the performance counter at the time of the <c>GetDevicePosition</c> call, the client can get a
			/// more timely estimate of the device position at a later time by calling <c>QueryPerformanceCounter</c> to obtain the current
			/// performance counter, and extrapolating the device position based on how far the counter has advanced since the original
			/// device position was recorded. The client can call the <c>QueryPerformanceCounter</c> function to get the frequency of the
			/// clock that increments the counter. Before comparing the raw counter value obtained from <c>QueryPerformanceCounter</c> to
			/// the value retrieved by <c>GetDevicePosition</c>, convert the raw counter value to 100-nanosecond time units as follows:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Multiply the raw counter value by 10,000,000.</term>
			/// </item>
			/// <item>
			/// <term>Divide the result by the counter frequency obtained from <c>QueryPerformanceCounter</c>.</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclock2-getdeviceposition HRESULT
			// GetDevicePosition( UINT64 *DevicePosition, UINT64 *QPCPosition );
			void GetDevicePosition(out ulong DevicePosition, out ulong QPCPosition);
		}

		/// <summary>
		/// <para>The <c>IAudioClockAdjustment</c> interface is used to adjust the sample rate of a stream.</para>
		/// <para>
		/// The client obtains a reference to the <c>IAudioClockAdjustment</c> interface of a stream object by calling the
		/// IAudioClient::GetService method with parameter riid set to REFIID IID_IAudioClockAdjustment. Adjusting the sample rate is not
		/// supported for exclusive mode streams.
		/// </para>
		/// <para>
		/// The <c>IAudioClockAdjustment</c> interface must be obtained from an audio client that is initialized with both the
		/// AUDCLNT_STREAMFLAGS_RATEADJUST flag and the share mode set to AUDCLNT_SHAREMODE_SHARED. If Initialize is called in an exclusive
		/// mode with the AUDCLNT_STREAMFLAGS_RATEADJUST flag, <c>Initialize</c> fails with the AUDCLNT_E_UNSUPPORTED_FORMAT error code.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioClockAdjustment</c> interface instance, the client must call the interface's <c>Release</c> method
		/// from the same thread as the call to IAudioClient::GetService that created the object.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclockadjustment
		[PInvokeData("audioclient.h", MSDNShortId = "61d90fd9-6c73-4987-b424-1523f15ab023")]
		[ComImport, Guid("f6e4c0a0-46d9-4fb8-be21-57a3ef2b626c"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioClockAdjustment
		{
			/// <summary>The <c>SetSampleRate</c> method sets the sample rate of a stream.</summary>
			/// <param name="flSampleRate">The new sample rate in frames per second.</param>
			/// <remarks>
			/// <para>This method must not be called from a real-time processing thread.</para>
			/// <para>
			/// The new sample rate will take effect after the current frame is done processing and will remain in effect until
			/// <c>SetSampleRate</c> is called again. The audio client must be initialized in shared-mode (AUDCLNT_SHAREMODE_SHARED),
			/// otherwise <c>SetSampleRate</c> fails.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclockadjustment-setsamplerate HRESULT
			// SetSampleRate( float flSampleRate );
			void SetSampleRate([In] float flSampleRate);
		}

		/// <summary>
		/// <para>
		/// The <c>IAudioRenderClient</c> interface enables a client to write output data to a rendering endpoint buffer. The client obtains
		/// a reference to the <c>IAudioRenderClient</c> interface of a stream object by calling the IAudioClient::GetService method with
		/// parameter riid set to <c>REFIID</c> IID_IAudioRenderClient.
		/// </para>
		/// <para>
		/// The methods in this interface manage the movement of data packets that contain audio-rendering data. The length of a data packet
		/// is expressed as the number of audio frames in the packet. The size of an audio frame is specified by the <c>nBlockAlign</c>
		/// member of the <c>WAVEFORMATEX</c> structure that the client obtains by calling the IAudioClient::GetMixFormat method. The size
		/// in bytes of an audio frame equals the number of channels in the stream multiplied by the sample size per channel. For example,
		/// the frame size is four bytes for a stereo (2-channel) stream with 16-bit samples. A packet always contains an integral number of
		/// audio frames.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioRenderClient</c> interface instance, the client must call the interface's <c>Release</c> method from
		/// the same thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// <para>For code examples that use the <c>IAudioRenderClient</c> interface, see the following topics:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Exclusive-Mode Streams</term>
		/// </item>
		/// </list>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiorenderclient
		[PInvokeData("audioclient.h", MSDNShortId = "e3e18e1e-1a09-4072-add6-36d2a6428a74")]
		[ComImport, Guid("F294ACFC-3146-4483-A7BF-ADDCA7C260E2"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioRenderClient
		{
			/// <summary>
			/// Retrieves a pointer to the next available space in the rendering endpoint buffer into which the caller can write a data packet.
			/// </summary>
			/// <param name="NumFramesRequested">
			/// The number of audio frames in the data packet that the caller plans to write to the requested space in the buffer. If the
			/// call succeeds, the size of the buffer area pointed to by *ppData matches the size specified in NumFramesRequested.
			/// </param>
			/// <returns>
			/// Pointer to a variable into which the method writes the starting address of the buffer area into which the caller will write
			/// the data packet.
			/// </returns>
			/// <remarks>
			/// <para>
			/// The caller can request a packet size that is less than or equal to the amount of available space in the buffer (except in
			/// the case of an exclusive-mode stream that uses event-driven buffering; for more information, see IAudioClient::Initialize).
			/// The available space is simply the buffer size minus the amount of data in the buffer that is already queued up to be played.
			/// If the caller specifies a NumFramesRequested value that exceeds the available space in the buffer, the call fails and
			/// returns error code AUDCLNT_E_BUFFER_TOO_LARGE.
			/// </para>
			/// <para>
			/// The client is responsible for writing a sufficient amount of data to the buffer to prevent glitches from occurring in the
			/// audio stream. For more information about buffering requirements, see IAudioClient::Initialize.
			/// </para>
			/// <para>
			/// After obtaining a data packet by calling <c>GetBuffer</c>, the client fills the packet with rendering data and issues the
			/// packet to the audio engine by calling the IAudioRenderClient::ReleaseBuffer method.
			/// </para>
			/// <para>
			/// The client must call <c>ReleaseBuffer</c> after a <c>GetBuffer</c> call that successfully obtains a packet of any size other
			/// than 0. The client has the option of calling or not calling <c>ReleaseBuffer</c> to release a packet of size 0.
			/// </para>
			/// <para>
			/// For nonzero packet sizes, the client must alternate calls to <c>GetBuffer</c> and <c>ReleaseBuffer</c>. Each
			/// <c>GetBuffer</c> call must be followed by a corresponding <c>ReleaseBuffer</c> call. After the client has called
			/// <c>GetBuffer</c> to acquire a data packet, the client cannot acquire the next data packet until it has called
			/// <c>ReleaseBuffer</c> to release the previous packet. Two or more consecutive calls either to <c>GetBuffer</c> or to
			/// <c>ReleaseBuffer</c> are not permitted and will fail with error code AUDCLNT_E_OUT_OF_ORDER.
			/// </para>
			/// <para>
			/// To ensure the correct ordering of calls, a <c>GetBuffer</c> call and its corresponding <c>ReleaseBuffer</c> call must occur
			/// in the same thread.
			/// </para>
			/// <para>
			/// The size of an audio frame is specified by the <c>nBlockAlign</c> member of the <c>WAVEFORMATEX</c> structure that the
			/// client obtains by calling the IAudioClient::GetMixFormat method.
			/// </para>
			/// <para>
			/// If the caller sets NumFramesRequested = 0, the method returns status code S_OK but does not write to the variable that the
			/// ppData parameter points to.
			/// </para>
			/// <para>
			/// Clients should avoid excessive delays between the <c>GetBuffer</c> call that acquires a buffer and the <c>ReleaseBuffer</c>
			/// call that releases the buffer. The implementation of the audio engine assumes that the <c>GetBuffer</c> call and the
			/// corresponding <c>ReleaseBuffer</c> call occur within the same buffer-processing period. Clients that delay releasing a
			/// buffer for more than one period risk losing sample data.
			/// </para>
			/// <para>
			/// In Windows 7, <c>GetBuffer</c> can return the <c>AUDCLNT_E_BUFFER_ERROR</c> error code for an audio client that uses the
			/// endpoint buffer in the exclusive mode. This error indicates that the data buffer was not retrieved because a data packet was
			/// not available (*ppData received <c>NULL</c>).
			/// </para>
			/// <para>
			/// If <c>GetBuffer</c> returns <c>AUDCLNT_E_BUFFER_ERROR</c>, the thread consuming the audio samples must wait for the next
			/// processing pass. The client might benefit from keeping a count of the failed <c>GetBuffer</c> calls. If <c>GetBuffer</c>
			/// returns this error repeatedly, the client can start a new processing loop after shutting down the current client by calling
			/// IAudioClient::Stop, IAudioClient::Reset, and releasing the audio client.
			/// </para>
			/// <para>Examples</para>
			/// <para>For code examples that call the <c>GetBuffer</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Exclusive-Mode Streams</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiorenderclient-getbuffer HRESULT GetBuffer(
			// UINT32 NumFramesRequested, BYTE **ppData );
			IntPtr GetBuffer([In] uint NumFramesRequested);

			/// <summary>
			/// The <c>ReleaseBuffer</c> method releases the buffer space acquired in the previous call to the IAudioRenderClient::GetBuffer method.
			/// </summary>
			/// <param name="NumFramesWritten">
			/// The number of audio frames written by the client to the data packet. The value of this parameter must be less than or equal
			/// to the size of the data packet, as specified in the NumFramesRequested parameter passed to the IAudioRenderClient::GetBuffer method.
			/// </param>
			/// <param name="dwFlags">
			/// <para>
			/// The buffer-configuration flags. The caller can set this parameter either to 0 or to the following _AUDCLNT_BUFFERFLAGS
			/// enumeration value (a flag bit):
			/// </para>
			/// <para>AUDCLNT_BUFFERFLAGS_SILENT</para>
			/// <para>
			/// If this flag bit is set, the audio engine treats the data packet as though it contains silence regardless of the data values
			/// contained in the packet. This flag eliminates the need for the client to explicitly write silence data to the rendering buffer.
			/// </para>
			/// </param>
			/// <returns>
			/// <para>
			/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values
			/// shown in the following table.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>AUDCLNT_E_INVALID_SIZE</term>
			/// <term>
			/// The NumFramesWritten value exceeds the NumFramesRequested value specified in the previous IAudioRenderClient::GetBuffer call.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
			/// <term>
			/// The stream is exclusive mode and uses event-driven buffering, but the client attempted to release a packet that was not the
			/// size of the buffer.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_OUT_OF_ORDER</term>
			/// <term>This call was not preceded by a corresponding call to IAudioRenderClient::GetBuffer.</term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
			/// <term>
			/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
			/// disabled, removed, or otherwise made unavailable for use.
			/// </term>
			/// </item>
			/// <item>
			/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
			/// <term>The Windows audio service is not running.</term>
			/// </item>
			/// <item>
			/// <term>E_INVALIDARG</term>
			/// <term>Parameter dwFlags is not a valid value.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The client must release the same number of frames that it requested in the preceding call to the
			/// IAudioRenderClient::GetBuffer method. The single exception to this rule is that the client can always call
			/// <c>ReleaseBuffer</c> to release 0 frames (unless the stream is exclusive mode and uses event-driven buffering).
			/// </para>
			/// <para>
			/// This behavior provides a convenient means for the client to "release" a previously requested packet of length 0. In this
			/// case, the call to <c>ReleaseBuffer</c> is optional. After calling GetBuffer to obtain a packet of length 0, the client has
			/// the option of not calling <c>ReleaseBuffer</c> before calling <c>GetBuffer</c> again.
			/// </para>
			/// <para>
			/// In addition, if the preceding GetBuffer call obtained a packet of nonzero size, calling <c>ReleaseBuffer</c> with
			/// NumFramesRequested set to 0 will succeed (unless the stream is exclusive mode and uses event-driven buffering). The meaning
			/// of the call is that the client wrote no data to the packet before releasing it. Thus, the method treats the portion of the
			/// buffer represented by the packet as unused and will make this portion of the buffer available again to the client in the
			/// next <c>GetBuffer</c> call.
			/// </para>
			/// <para>
			/// Clients should avoid excessive delays between the GetBuffer call that acquires a buffer and the <c>ReleaseBuffer</c> call
			/// that releases the buffer. The implementation of the audio engine assumes that the <c>GetBuffer</c> call and the
			/// corresponding <c>ReleaseBuffer</c> call occur within the same buffer-processing period. Clients that delay releasing a
			/// buffer for more than one period risk losing sample data.
			/// </para>
			/// <para>For code examples that call the <c>ReleaseBuffer</c> method, see the following topics:</para>
			/// <list type="bullet">
			/// <item>
			/// <term>Rendering a Stream</term>
			/// </item>
			/// <item>
			/// <term>Exclusive-Mode Streams</term>
			/// </item>
			/// </list>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiorenderclient-releasebuffer HRESULT
			// ReleaseBuffer( UINT32 NumFramesWritten, DWORD dwFlags );
			void ReleaseBuffer([In] uint NumFramesWritten, [In] AUDCLNT_BUFFERFLAGS dwFlags);
		}

		/// <summary>
		/// <para>
		/// The <c>IAudioStreamVolume</c> interface enables a client to control and monitor the volume levels for all of the channels in an
		/// audio stream. The client obtains a reference to the <c>IAudioStreamVolume</c> interface on a stream object by calling the
		/// IAudioClient::GetService method with parameter riid set to REFIID IID_IAudioStreamVolume.
		/// </para>
		/// <para>
		/// The effective volume level of any channel in the session submix, as heard at the speakers, is the product of the following four
		/// volume-level factors:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>
		/// The per-channel volume levels of the streams in the session, which clients can control through the methods in the
		/// <c>IAudioStreamVolume</c> interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>
		/// The per-channel volume level of the session, which clients can control through the methods in the IChannelAudioVolume interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>The master volume level of the session, which clients can control through the methods in the ISimpleAudioVolume interface.</term>
		/// </item>
		/// <item>
		/// <term>The policy-based volume level of the session, which the system dynamically assigns to the session as the global mix changes.</term>
		/// </item>
		/// </list>
		/// <para>
		/// Each of the four volume-level factors in the preceding list is a value in the range 0.0 to 1.0, where 0.0 indicates silence and
		/// 1.0 indicates full volume (no attenuation). The effective volume level is also a value in the range 0.0 to 1.0.
		/// </para>
		/// <para>
		/// When releasing an <c>IAudioStreamVolume</c> interface instance, the client must call the interface's <c>Release</c> method from
		/// the same thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// <para>
		/// The <c>IAudioStreamVolume</c> interface controls the channel volumes in a shared-mode audio stream. This interface does not work
		/// with exclusive-mode streams. For information about volume controls for exclusive-mode streams, see EndpointVolume API.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiostreamvolume
		[PInvokeData("audioclient.h", MSDNShortId = "92cc127b-77ac-4fc7-ac3c-319e5d6368d3")]
		[ComImport, Guid("93014887-242D-4068-8A15-CF5E93B90FE3"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IAudioStreamVolume
		{
			/// <summary>The <c>GetChannelCount</c> method retrieves the number of channels in the audio stream.</summary>
			/// <returns>A <c>UINT32</c> variable into which the method writes the channel count.</returns>
			/// <remarks>
			/// Call this method to get the number of channels in the audio stream before calling any of the other methods in the
			/// IAudioStreamVolume interface.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiostreamvolume-getchannelcount HRESULT
			// GetChannelCount( UINT32 *pdwCount );
			uint GetChannelCount();

			/// <summary>The <c>SetChannelVolume</c> method sets the volume level for the specified channel in the audio stream.</summary>
			/// <param name="dwIndex">
			/// The channel number. If the stream format has N channels, the channels are numbered from 0 to N– 1. To get the number of
			/// channels, call the IAudioStreamVolume::GetChannelCount method.
			/// </param>
			/// <param name="fLevel">The volume level for the channel. Valid volume levels are in the range 0.0 to 1.0.</param>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiostreamvolume-setchannelvolume HRESULT
			// SetChannelVolume( UINT32 dwIndex, const float fLevel );
			void SetChannelVolume([In] uint dwIndex, [In] float fLevel);

			/// <summary>The <c>GetChannelVolume</c> method retrieves the volume level for the specified channel in the audio stream.</summary>
			/// <param name="dwIndex">
			/// The channel number. If the stream format has N channels, then the channels are numbered from 0 to N– 1. To get the number of
			/// channels, call the IAudioStreamVolume::GetChannelCount method.
			/// </param>
			/// <returns>
			/// A <c>float</c> variable into which the method writes the volume level of the specified channel. The volume level is in the
			/// range 0.0 to 1.0.
			/// </returns>
			/// <remarks>
			/// Clients can call the IAudioStreamVolume::SetAllVolumes or IAudioStreamVolume::SetChannelVolume method to set the per-channel
			/// volume levels in an audio stream.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiostreamvolume-getchannelvolume HRESULT
			// GetChannelVolume( UINT32 dwIndex, float *pfLevel );
			float GetChannelVolume([In] uint dwIndex);

			/// <summary>The <c>SetAllVolumes</c> method sets the individual volume levels for all the channels in the audio stream.</summary>
			/// <param name="dwCount">
			/// The number of elements in the pfVolumes array. This parameter must equal the number of channels in the stream format. To get
			/// the number of channels, call the IAudioStreamVolume::GetChannelCount method.
			/// </param>
			/// <param name="pfVolumes">
			/// Pointer to an array of volume levels for the channels in the audio stream. The number of elements in the pfVolumes array is
			/// specified by the dwCount parameter. The caller writes the volume level for each channel to the array element whose index
			/// matches the channel number. If the stream format has N channels, the channels are numbered from 0 to N– 1. Valid volume
			/// levels are in the range 0.0 to 1.0.
			/// </param>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiostreamvolume-setallvolumes HRESULT
			// SetAllVolumes( UINT32 dwCount, const float *pfVolumes );
			void SetAllVolumes([In] uint dwCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] pfVolumes);

			/// <summary>The <c>GetAllVolumes</c> method retrieves the volume levels for all the channels in the audio stream.</summary>
			/// <param name="dwCount">
			/// The number of elements in the pfVolumes array. The dwCount parameter must equal the number of channels in the stream format.
			/// To get the number of channels, call the IAudioStreamVolume::GetChannelCount method.
			/// </param>
			/// <param name="pfVolumes">
			/// Pointer to an array of volume levels for the channels in the audio stream. This parameter points to a caller-allocated
			/// <c>float</c> array into which the method writes the volume levels for the individual channels. Volume levels are in the
			/// range 0.0 to 1.0.
			/// </param>
			/// <remarks>
			/// Clients can call the IAudioStreamVolume::SetAllVolumes or IAudioStreamVolume::SetChannelVolume method to set the per-channel
			/// volume levels in an audio stream.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudiostreamvolume-getallvolumes HRESULT
			// GetAllVolumes( UINT32 dwCount, float *pfVolumes );
			void GetAllVolumes([In] uint dwCount, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] pfVolumes);
		}

		/// <summary>
		/// <para>
		/// The <c>IChannelAudioVolume</c> interface enables a client to control and monitor the volume levels for all of the channels in
		/// the audio session that the stream belongs to. This is the session that the client assigned the stream to during the call to the
		/// IAudioClient::Initialize method. The client obtains a reference to the <c>IChannelAudioVolume</c> interface on a stream object
		/// by calling the IAudioClient::GetService method with parameter riid set to REFIID IID_IChannelAudioVolume.
		/// </para>
		/// <para>
		/// The effective volume level of any channel in the session submix, as heard at the speakers, is the product of the following four
		/// volume-level factors:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>
		/// The per-channel volume levels of the streams in the session, which clients can control through the methods in the
		/// IAudioStreamVolume interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>
		/// The per-channel volume level of the session, which clients can control through the methods in the <c>IChannelAudioVolume</c> interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>The master volume level of the session, which clients can control through the methods in the ISimpleAudioVolume interface.</term>
		/// </item>
		/// <item>
		/// <term>The policy-based volume level of the session, which the system dynamically assigns to the session as the global mix changes.</term>
		/// </item>
		/// </list>
		/// <para>
		/// Each of the four volume-level factors in the preceding list is a value in the range 0.0 to 1.0, where 0.0 indicates silence and
		/// 1.0 indicates full volume (no attenuation). The effective volume level is also a value in the range 0.0 to 1.0.
		/// </para>
		/// <para>
		/// Typical audio applications do not modify the volume levels of sessions. Instead, they rely on users to set these volume levels
		/// through the Sndvol program. Sndvol modifies only the master volume levels of sessions. By default, the session manager sets the
		/// per-channel volume levels to 1.0 at the initial activation of a session. Subsequent per-channel volume changes by clients are
		/// persistent across computer restarts.
		/// </para>
		/// <para>
		/// When releasing an <c>IChannelAudioVolume</c> interface instance, the client must call the interface's <c>Release</c> method from
		/// the same thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// <para>
		/// The <c>IChannelAudioVolume</c> interface controls the channel volumes in an audio session. An audio session is a collection of
		/// shared-mode streams. This interface does not work with exclusive-mode streams. For information about volume controls for
		/// exclusive-mode streams, see EndpointVolume API.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-ichannelaudiovolume
		[PInvokeData("audioclient.h", MSDNShortId = "0d0a20dc-5e5a-49a7-adc9-20aacb88368a")]
		[ComImport, Guid("1C158861-B533-4B30-B1CF-E853E51C59B8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IChannelAudioVolume
		{
			/// <summary>The <c>GetChannelCount</c> method retrieves the number of channels in the stream format for the audio session.</summary>
			/// <returns>A <c>UINT32</c> variable into which the method writes the channel count.</returns>
			/// <remarks>
			/// Call this method to get the number of channels in the audio session before calling any of the other methods in the
			/// IChannelAudioVolume interface.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-ichannelaudiovolume-getchannelcount HRESULT
			// GetChannelCount( UINT32 *pdwCount );
			uint GetChannelCount();

			/// <summary>The <c>SetChannelVolume</c> method sets the volume level for the specified channel in the audio session.</summary>
			/// <param name="dwIndex">
			/// The channel number. If the stream format for the audio session has N channels, the channels are numbered from 0 to N– 1. To
			/// get the number of channels, call the IChannelAudioVolume::GetChannelCount method.
			/// </param>
			/// <param name="fLevel">The volume level for the channel. Valid volume levels are in the range 0.0 to 1.0.</param>
			/// <param name="EventContext">
			/// Pointer to the event-context GUID. If a call to this method generates a channel-volume-change event, the session manager
			/// sends notifications to all clients that have registered IAudioSessionEvents interfaces with the session manager. The session
			/// manager includes the EventContext pointer value with each notification. Upon receiving a notification, a client can
			/// determine whether it or another client is the source of the event by inspecting the EventContext value. This scheme depends
			/// on the client selecting a value for this parameter that is unique among all clients in the session. If the caller supplies a
			/// <c>NULL</c> pointer for this parameter, the client's notification method receives a <c>NULL</c> context pointer.
			/// </param>
			/// <remarks>
			/// This method, if it succeeds, generates a channel-volume-change event regardless of whether the new channel volume level
			/// differs in value from the previous channel volume level.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-ichannelaudiovolume-setchannelvolume HRESULT
			// SetChannelVolume( UINT32 dwIndex, const float fLevel, LPCGUID EventContext );
			void SetChannelVolume([In] uint dwIndex, [In] float fLevel, in Guid EventContext);

			/// <summary>The <c>GetChannelVolume</c> method retrieves the volume level for the specified channel in the audio session.</summary>
			/// <param name="dwIndex">
			/// The channel number. If the stream format for the audio session has N channels, then the channels are numbered from 0 to N–
			/// 1. To get the number of channels, call the IChannelAudioVolume::GetChannelCount method.
			/// </param>
			/// <returns>
			/// A <c>float</c> variable into which the method writes the volume level of the specified channel. The volume level is in the
			/// range 0.0 to 1.0.
			/// </returns>
			/// <remarks>
			/// Clients can call the IChannelAudioVolume::SetAllVolumes or IChannelAudioVolume::SetChannelVolume method to set the
			/// per-channel volume levels in an audio session.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-ichannelaudiovolume-getchannelvolume HRESULT
			// GetChannelVolume( UINT32 dwIndex, float *pfLevel );
			float GetChannelVolume([In] uint dwIndex);

			/// <summary>The <c>SetAllVolumes</c> method sets the individual volume levels for all the channels in the audio session.</summary>
			/// <param name="dwCount">
			/// The number of elements in the pfVolumes array. This parameter must equal the number of channels in the stream format for the
			/// audio session. To get the number of channels, call the IChannelAudioVolume::GetChannelCount method.
			/// </param>
			/// <param name="pfVolumes">
			/// Pointer to an array of volume levels for the channels in the audio session. The number of elements in the pfVolumes array is
			/// specified by the dwCount parameter. The caller writes the volume level for each channel to the array element whose index
			/// matches the channel number. If the stream format for the audio session has N channels, the channels are numbered from 0 to
			/// N– 1. Valid volume levels are in the range 0.0 to 1.0.
			/// </param>
			/// <param name="EventContext">
			/// Pointer to the event-context GUID. If a call to this method generates a channel-volume-change event, the session manager
			/// sends notifications to all clients that have registered IAudioSessionEvents interfaces with the session manager. The session
			/// manager includes the EventContext pointer value with each notification. Upon receiving a notification, a client can
			/// determine whether it or another client is the source of the event by inspecting the EventContext value. This scheme depends
			/// on the client selecting a value for this parameter that is unique among all clients in the session. If the caller supplies a
			/// <c>NULL</c> pointer for this parameter, the client's notification method receives a <c>NULL</c> context pointer.
			/// </param>
			/// <remarks>
			/// This method, if it succeeds, generates a channel-volume-change event regardless of whether any of the new channel volume
			/// levels differ in value from the previous channel volume levels.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-ichannelaudiovolume-setallvolumes HRESULT
			// SetAllVolumes( UINT32 dwCount, const float *pfVolumes, LPCGUID EventContext );
			void SetAllVolumes([In] uint dwCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] pfVolumes, in Guid EventContext);

			/// <summary>The <c>GetAllVolumes</c> method retrieves the volume levels for all the channels in the audio session.</summary>
			/// <param name="dwCount">
			/// The number of elements in the pfVolumes array. The dwCount parameter must equal the number of channels in the stream format
			/// for the audio session. To get the number of channels, call the IChannelAudioVolume::GetChannelCount method.
			/// </param>
			/// <param name="pfVolumes">
			/// Pointer to an array of volume levels for the channels in the audio session. This parameter points to a caller-allocated
			/// <c>float</c> array into which the method writes the volume levels for the individual channels. Volume levels are in the
			/// range 0.0 to 1.0.
			/// </param>
			/// <remarks>
			/// Clients can call the IChannelAudioVolume::SetAllVolumes or IChannelAudioVolume::SetChannelVolume method to set the
			/// per-channel volume levels in an audio session.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-ichannelaudiovolume-getallvolumes HRESULT
			// GetAllVolumes( UINT32 dwCount, float *pfVolumes );
			void GetAllVolumes([In] uint dwCount, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] pfVolumes);
		}

		/// <summary>
		/// <para>
		/// The <c>ISimpleAudioVolume</c> interface enables a client to control the master volume level of an audio session. The
		/// IAudioClient::Initialize method initializes a stream object and assigns the stream to an audio session. The client obtains a
		/// reference to the <c>ISimpleAudioVolume</c> interface on a stream object by calling the IAudioClient::GetService method with
		/// parameter riid set to <c>REFIID</c> IID_ISimpleAudioVolume.
		/// </para>
		/// <para>
		/// Alternatively, a client can obtain the <c>ISimpleAudioVolume</c> interface of an existing session without having to first create
		/// a stream object and add the stream to the session. Instead, the client calls the IAudioSessionManager::GetSimpleAudioVolume
		/// method with the session GUID.
		/// </para>
		/// <para>
		/// The effective volume level of any channel in the session submix, as heard at the speakers, is the product of the following four
		/// volume-level factors:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>
		/// The per-channel volume levels of the streams in the session, which clients can control through the methods in the
		/// IAudioStreamVolume interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>
		/// The master volume level of the session, which clients can control through the methods in the <c>ISimpleAudioVolume</c> interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>
		/// The per-channel volume level of the session, which clients can control through the methods in the IChannelAudioVolume interface.
		/// </term>
		/// </item>
		/// <item>
		/// <term>The policy-based volume level of the session, which the system dynamically assigns to the session as the global mix changes.</term>
		/// </item>
		/// </list>
		/// <para>
		/// Each of the four volume-level factors in the preceding list is a value in the range 0.0 to 1.0, where 0.0 indicates silence and
		/// 1.0 indicates full volume (no attenuation). The effective volume level is also a value in the range 0.0 to 1.0.
		/// </para>
		/// <para>
		/// Typical audio applications do not modify the volume levels of sessions. Instead, they rely on users to set these volume levels
		/// through the Sndvol program. Sndvol modifies only the master volume levels of sessions. By default, the session manager sets the
		/// master volume level to 1.0 at the initial activation of a session. Subsequent volume changes by Sndvol or other clients are
		/// persistent across computer restarts.
		/// </para>
		/// <para>
		/// When releasing an <c>ISimpleAudioVolume</c> interface instance, the client must call the interface's <c>Release</c> method from
		/// the same thread as the call to <c>IAudioClient::GetService</c> that created the object.
		/// </para>
		/// <para>
		/// The <c>ISimpleAudioVolume</c> interface controls the volume of an audio session. An audio session is a collection of shared-mode
		/// streams. This interface does not work with exclusive-mode streams. For information about volume controls for exclusive-mode
		/// streams, see EndpointVolume API.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-isimpleaudiovolume
		[PInvokeData("audioclient.h", MSDNShortId = "360211f2-de82-4ff5-896c-dee1d60cb7b7")]
		[ComImport, Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface ISimpleAudioVolume
		{
			/// <summary>The <c>SetMasterVolume</c> method sets the master volume level for the audio session.</summary>
			/// <param name="fLevel">The new master volume level. Valid volume levels are in the range 0.0 to 1.0.</param>
			/// <param name="EventContext">
			/// Pointer to the event-context GUID. If a call to this method generates a volume-change event, the session manager sends
			/// notifications to all clients that have registered IAudioSessionEvents interfaces with the session manager. The session
			/// manager includes the EventContext pointer value with each notification. Upon receiving a notification, a client can
			/// determine whether it or another client is the source of the event by inspecting the EventContext value. This scheme depends
			/// on the client selecting a value for this parameter that is unique among all clients in the session. If the caller supplies a
			/// <c>NULL</c> pointer for this parameter, the client's notification method receives a <c>NULL</c> context pointer.
			/// </param>
			/// <remarks>
			/// This method generates a volume-change event only if the method call changes the volume level of the session. For example, if
			/// the volume level is 0.4 when the call occurs, and the call sets the volume level to 0.4, no event is generated.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-setmastervolume HRESULT
			// SetMasterVolume( float fLevel, LPCGUID EventContext );
			void SetMasterVolume([In] float fLevel, in Guid EventContext);

			/// <summary>The <c>GetMasterVolume</c> method retrieves the client volume level for the audio session.</summary>
			/// <returns>
			/// A <c>float</c> variable into which the method writes the client volume level. The volume level is a value in the range 0.0
			/// to 1.0.
			/// </returns>
			/// <remarks>
			/// This method retrieves the client volume level for the session. This is the volume level that the client set in a previous
			/// call to the ISimpleAudioVolume::SetMasterVolume method.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-getmastervolume HRESULT
			// GetMasterVolume( float *pfLevel );
			float GetMasterVolume();

			/// <summary>The <c>SetMute</c> method sets the muting state for the audio session.</summary>
			/// <param name="bMute">The new muting state. <c>TRUE</c> enables muting. <c>FALSE</c> disables muting.</param>
			/// <param name="EventContext">
			/// Pointer to the event-context GUID. If a call to this method generates a volume-change event, the session manager sends
			/// notifications to all clients that have registered IAudioSessionEvents interfaces with the session manager. The session
			/// manager includes the EventContext pointer value with each notification. Upon receiving a notification, a client can
			/// determine whether it or another client is the source of the event by inspecting the EventContext value. This scheme depends
			/// on the client selecting a value for this parameter that is unique among all clients in the session. If the caller supplies a
			/// <c>NULL</c> pointer for this parameter, the client's notification method receives a <c>NULL</c> context pointer.
			/// </param>
			/// <remarks>
			/// <para>
			/// This method generates a volume-change event only if the method call changes the muting state of the session from disabled to
			/// enabled, or from enabled to disabled. For example, if muting is enabled when the call occurs, and the call enables muting,
			/// no event is generated.
			/// </para>
			/// <para>
			/// This method applies the same muting state to all channels in the audio session. The endpoint device always applies muting
			/// uniformly across all the channels in the session. There are no IChannelAudioVolume methods for setting the muting states of
			/// individual channels.
			/// </para>
			/// <para>The client can get the muting state of the audio session by calling the SimpleAudioVolume::GetMute method.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-setmute HRESULT SetMute(
			// const BOOL bMute, LPCGUID EventContext );
			void SetMute([In] [MarshalAs(UnmanagedType.Bool)] bool bMute, in Guid EventContext);

			/// <summary>The <c>GetMute</c> method retrieves the current muting state for the audio session.</summary>
			/// <returns>
			/// A <c>BOOL</c> variable into which the method writes the muting state. <c>TRUE</c> indicates that muting is enabled.
			/// <c>FALSE</c> indicates that it is disabled.
			/// </returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-getmute HRESULT GetMute(
			// BOOL *pbMute );
			[return: MarshalAs(UnmanagedType.Bool)]
			bool GetMute();
		}

		/// <summary>
		/// Returns the current format and periodicity of the audio engine. This method enables audio clients to match the current period of
		/// the audio engine.
		/// </summary>
		/// <param name="client">The client.</param>
		/// <returns>
		/// <para>A tuple:</para>
		/// <para><c>ppFormat</c> - Type: <c>WAVEFORMATEX</c></para>
		/// <para>The current device format that is being used by the audio engine.</para>
		/// <para><c>pCurrentPeriodInFrames</c> - Type: <c>UINT32</c></para>
		/// <para>The current period of the audio engine, in audio frames.</para>
		/// </returns>
		/// <remarks>
		/// <c>Note</c> The values returned by this method are instantaneous values and may be invalid immediately after the call returns
		/// if, for example, another audio client sets the periodicity or format to a different value.
		/// </remarks>
		public static (WAVEFORMATEX ppFormat, uint pCurrentPeriodInFrames) GetCurrentSharedModeEnginePeriod(this IAudioClient3 client)
		{
			client.GetCurrentSharedModeEnginePeriod(out var fmt, out var fr);
			using (fmt)
				return (fmt.ToStructure<WAVEFORMATEX>(), fr);
		}

		/// <summary>
		/// The <c>GetMixFormat</c> method retrieves the stream format that the audio engine uses for its internal processing of shared-mode streams.
		/// </summary>
		/// <param name="client">The client.</param>
		/// <returns>A variable into which the method writes the address of the mix format.</returns>
		/// <remarks>
		/// <para>
		/// The client can call this method before calling the IAudioClient::Initialize method. When creating a shared-mode stream for an
		/// audio endpoint device, the <c>Initialize</c> method always accepts the stream format obtained from a <c>GetMixFormat</c> call on
		/// the same device.
		/// </para>
		/// <para>
		/// The mix format is the format that the audio engine uses internally for digital processing of shared-mode streams. This format is
		/// not necessarily a format that the audio endpoint device supports. Thus, the caller might not succeed in creating an
		/// exclusive-mode stream with a format obtained by calling <c>GetMixFormat</c>.
		/// </para>
		/// <para>
		/// For example, to facilitate digital audio processing, the audio engine might use a mix format that represents samples as
		/// floating-point values. If the device supports only integer PCM samples, then the engine converts the samples to or from integer
		/// PCM values at the connection between the device and the engine. However, to avoid resampling, the engine might use a mix format
		/// with a sample rate that the device supports.
		/// </para>
		/// <para>
		/// To determine whether the <c>Initialize</c> method can create a shared-mode or exclusive-mode stream with a particular format,
		/// call the IAudioClient::IsFormatSupported method.
		/// </para>
		/// <para>
		/// By itself, a <c>WAVEFORMATEX</c> structure cannot specify the mapping of channels to speaker positions. In addition, although
		/// <c>WAVEFORMATEX</c> specifies the size of the container for each audio sample, it cannot specify the number of bits of precision
		/// in a sample (for example, 20 bits of precision in a 24-bit container). However, the <c>WAVEFORMATEXTENSIBLE</c> structure can
		/// specify both the mapping of channels to speakers and the number of bits of precision in each sample. For this reason, the
		/// <c>GetMixFormat</c> method retrieves a format descriptor that is in the form of a <c>WAVEFORMATEXTENSIBLE</c> structure instead
		/// of a standalone <c>WAVEFORMATEX</c> structure. Through the ppDeviceFormat parameter, the method outputs a pointer to the
		/// <c>WAVEFORMATEX</c> structure that is embedded at the start of this <c>WAVEFORMATEXTENSIBLE</c> structure. For more information
		/// about <c>WAVEFORMATEX</c> and <c>WAVEFORMATEXTENSIBLE</c>, see the Windows DDK documentation.
		/// </para>
		/// <para>
		/// For more information about the <c>GetMixFormat</c> method, see Device Formats. For code examples that call <c>GetMixFormat</c>,
		/// see the following topics:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Capturing a Stream</term>
		/// </item>
		/// </list>
		/// </remarks>
		public static WAVEFORMATEX GetMixFormat(this IAudioClient client) { var hr = client.GetMixFormat(out var mem); return hr.Succeeded && !mem.IsInvalid ? mem.ToStructure<WAVEFORMATEX>() : throw hr.GetException(); }

		/// <summary>The <c>GetService</c> method accesses additional services from the audio client object.</summary>
		/// <param name="client">The client.</param>
		/// <returns>
		/// Pointer to a variable into which the method writes the address of an instance of the requested interface. Through this method,
		/// the caller obtains a counted reference to the interface. The caller is responsible for releasing the interface, when it is no
		/// longer needed, by calling the interface's <c>Release</c> method. If the <c>GetService</c> call fails, *ppv is <c>NULL</c>.
		/// </returns>
		/// <remarks>
		/// <para>
		/// This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error
		/// AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the IAudioClient::Initialize method.
		/// </para>
		/// <para>The <c>GetService</c> method supports the following service interfaces:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>IAudioCaptureClient</term>
		/// </item>
		/// <item>
		/// <term>IAudioClock</term>
		/// </item>
		/// <item>
		/// <term>IAudioRenderClient</term>
		/// </item>
		/// <item>
		/// <term>IAudioSessionControl</term>
		/// </item>
		/// <item>
		/// <term>IAudioStreamVolume</term>
		/// </item>
		/// <item>
		/// <term>IChannelAudioVolume</term>
		/// </item>
		/// <item>
		/// <term>IMFTrustedOutput</term>
		/// </item>
		/// <item>
		/// <term>ISimpleAudioVolume</term>
		/// </item>
		/// </list>
		/// <para>
		/// In Windows 7, a new service identifier, <c>IID_IMFTrustedOutput</c>, has been added that facilitates the use of output trust
		/// authority (OTA) objects. These objects can operate inside or outside the Media Foundation's protected media path (PMP) and send
		/// content outside the Media Foundation pipeline. If the caller is outside PMP, then the OTA may not operate in the PMP, and the
		/// protection settings are less robust. OTAs must implement the IMFTrustedOutput interface. By passing <c>IID_IMFTrustedOutput</c>
		/// in <c>GetService</c>, an application can retrieve a pointer to the object's <c>IMFTrustedOutput</c> interface. For more
		/// information about protected objects and <c>IMFTrustedOutput</c>, see "Protected Media Path" in the Media Foundation SDK documentation.
		/// </para>
		/// <para>For information about using trusted audio drivers in OTAs, see Protected User Mode Audio (PUMA).</para>
		/// <para>
		/// Note that activating IMFTrustedOutput through this mechanism works regardless of whether the caller is running in PMP. However,
		/// if the caller is not running in a protected process (that is, the caller is not within Media Foundation's PMP) then the audio
		/// OTA might not operate in the PMP and the protection settings are less robust.
		/// </para>
		/// <para>
		/// To obtain the interface ID for a service interface, use the <c>__uuidof</c> operator. For example, the interface ID of
		/// <c>IAudioCaptureClient</c> is defined as follows:
		/// </para>
		/// <para>For information about the <c>__uuidof</c> operator, see the Windows SDK documentation.</para>
		/// <para>
		/// To release the <c>IAudioClient</c> object and free all its associated resources, the client must release all references to any
		/// service objects that were created by calling <c>GetService</c>, in addition to calling <c>Release</c> on the <c>IAudioClient</c>
		/// interface itself. The client must release a service from the same thread that releases the <c>IAudioClient</c> object.
		/// </para>
		/// <para>
		/// The <c>IAudioSessionControl</c>, <c>IAudioStreamVolume</c>, <c>IChannelAudioVolume</c>, and <c>ISimpleAudioVolume</c> interfaces
		/// control and monitor aspects of audio sessions and shared-mode streams. These interfaces do not work with exclusive-mode streams.
		/// </para>
		/// <para>For code examples that call the <c>GetService</c> method, see the following topics:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Capturing a Stream</term>
		/// </item>
		/// </list>
		/// </remarks>
		public static T GetService<T>(this IAudioClient client) => (T)client.GetService(typeof(T).GUID);

		/// <summary>The <c>Initialize</c> method initializes the audio stream.</summary>
		/// <param name="client">The client.</param>
		/// <param name="ShareMode">
		/// <para>
		/// The sharing mode for the connection. Through this parameter, the client tells the audio engine whether it wants to share the
		/// audio endpoint device with other clients. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
		/// enumeration values:
		/// </para>
		/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
		/// <para>AUDCLNT_SHAREMODE_SHARED</para>
		/// </param>
		/// <param name="StreamFlags">
		/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of the
		/// AUDCLNT_STREAMFLAGS_XXX Constants or the AUDCLNT_SESSIONFLAGS_XXX Constants.
		/// </param>
		/// <param name="hnsBufferDuration">
		/// The buffer capacity as a time value. This parameter is of type <c>REFERENCE_TIME</c> and is expressed in 100-nanosecond units.
		/// This parameter contains the buffer size that the caller requests for the buffer that the audio application will share with the
		/// audio engine (in shared mode) or with the endpoint device (in exclusive mode). If the call succeeds, the method allocates a
		/// buffer that is a least this large. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK documentation. For more
		/// information about buffering requirements, see Remarks.
		/// </param>
		/// <param name="hnsPeriodicity">
		/// The device period. This parameter can be nonzero only in exclusive mode. In shared mode, always set this parameter to 0. In
		/// exclusive mode, this parameter specifies the requested scheduling period for successive buffer accesses by the audio endpoint
		/// device. If the requested device period lies outside the range that is set by the device's minimum period and the system's
		/// maximum period, then the method clamps the period to that range. If this parameter is 0, the method sets the device period to
		/// its default value. To obtain the default device period, call the IAudioClient::GetDevicePeriod method. If the
		/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK stream flag is set and AUDCLNT_SHAREMODE_EXCLUSIVE is set as the ShareMode, then
		/// hnsPeriodicity must be nonzero and equal to hnsBufferDuration.
		/// </param>
		/// <param name="pFormat">
		/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type <c>WAVEFORMATEX</c> (or
		/// <c>WAVEFORMATEXTENSIBLE</c>). For more information, see Remarks.
		/// </param>
		/// <param name="AudioSessionGuid">
		/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs to.
		/// If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the GUID does
		/// not identify an existing session, the method opens a new session and adds the stream to that session. The stream remains a
		/// member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a pointer to a
		/// GUID_NULL value.
		/// </param>
		/// <returns>
		/// <para>
		/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values shown in
		/// the following table.
		/// </para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>AUDCLNT_E_ALREADY_INITIALIZED</term>
		/// <term>The IAudioClient object is already initialized.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_WRONG_ENDPOINT_TYPE</term>
		/// <term>The AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but the endpoint device is a capture device, not a rendering device.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</term>
		/// <term>
		/// The requested buffer size is not aligned. This code can be returned for a render or a capture device if the caller specified
		/// AUDCLNT_SHAREMODE_EXCLUSIVE and the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flags. The caller must call Initialize again with the
		/// aligned buffer size. For more information, see Remarks.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
		/// <term>
		/// Indicates that the buffer duration value requested by an exclusive-mode client is out of range. The requested duration value for
		/// pull mode must not be greater than 500 milliseconds; for push mode the duration value must not be greater than 2 seconds.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_CPUUSAGE_EXCEEDED</term>
		/// <term>
		/// Indicates that the process-pass duration exceeded the maximum CPU usage. The audio engine keeps track of CPU usage by
		/// maintaining the number of times the process-pass duration exceeds the maximum CPU usage. The maximum CPU usage is calculated as
		/// a percent of the engine's periodicity. The percentage value is the system's CPU throttle value (within the range of 10% and
		/// 90%). If this value is not found, then the default value of 40% is used to calculate the maximum CPU usage.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
		/// <term>
		/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
		/// disabled, removed, or otherwise made unavailable for use.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_DEVICE_IN_USE</term>
		/// <term>
		/// The endpoint device is already in use. Either the device is being used in exclusive mode, or the device is being used in shared
		/// mode and the caller asked to use the device in exclusive mode.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_ENDPOINT_CREATE_FAILED</term>
		/// <term>
		/// The method failed to create the audio endpoint for the render or the capture device. This can occur if the audio endpoint device
		/// has been unplugged, or the audio hardware or associated hardware resources have been reconfigured, disabled, removed, or
		/// otherwise made unavailable for use.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_INVALID_DEVICE_PERIOD</term>
		/// <term>Indicates that the device period requested by an exclusive-mode client is greater than 500 milliseconds.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
		/// <term>The audio engine (shared mode) or audio endpoint device (exclusive mode) does not support the specified format.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED</term>
		/// <term>
		/// The caller is requesting exclusive-mode use of the endpoint device, but the user has disabled exclusive-mode use of the device.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL</term>
		/// <term>The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is set but parameters hnsBufferDuration and hnsPeriodicity are not equal.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
		/// <term>The Windows audio service is not running.</term>
		/// </item>
		/// <item>
		/// <term>E_POINTER</term>
		/// <term>Parameter pFormat is NULL.</term>
		/// </item>
		/// <item>
		/// <term>E_INVALIDARG</term>
		/// <term>
		/// Parameter pFormat points to an invalid format description; or the AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but ShareMode is not
		/// equal to AUDCLNT_SHAREMODE_SHARED; or the AUDCLNT_STREAMFLAGS_CROSSPROCESS flag is set but ShareMode is equal to
		/// AUDCLNT_SHAREMODE_EXCLUSIVE. A prior call to SetClientProperties was made with an invalid category for audio/render streams.
		/// </term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Out of memory.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>
		/// After activating an IAudioClient interface on an audio endpoint device, the client must successfully call <c>Initialize</c> once
		/// and only once to initialize the audio stream between the client and the device. The client can either connect directly to the
		/// audio hardware (exclusive mode) or indirectly through the audio engine (shared mode). In the <c>Initialize</c> call, the client
		/// specifies the audio data format, the buffer size, and audio session for the stream.
		/// </para>
		/// <para>
		/// <c>Note</c> In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from an
		/// MTA thread may result in undefined behavior.
		/// </para>
		/// <para>
		/// An attempt to create a shared-mode stream can succeed only if the audio device is already operating in shared mode or the device
		/// is currently unused. An attempt to create a shared-mode stream fails if the device is already operating in exclusive mode.
		/// </para>
		/// <para>
		/// If a stream is initialized to be event driven and in shared mode, ShareMode is set to AUDCLNT_SHAREMODE_SHARED and one of the
		/// stream flags that are set includes AUDCLNT_STREAMFLAGS_EVENTCALLBACK. For such a stream, the associated application must also
		/// obtain a handle by making a call to IAudioClient::SetEventHandle. When it is time to retire the stream, the audio engine can
		/// then use the handle to release the stream objects. Failure to call <c>IAudioClient::SetEventHandle</c> before releasing the
		/// stream objects can cause a delay of several seconds (a time-out period) while the audio engine waits for an available handle.
		/// After the time-out period expires, the audio engine then releases the stream objects.
		/// </para>
		/// <para>
		/// Whether an attempt to create an exclusive-mode stream succeeds depends on several factors, including the availability of the
		/// device and the user-controlled settings that govern exclusive-mode operation of the device. For more information, see
		/// Exclusive-Mode Streams.
		/// </para>
		/// <para>
		/// An <c>IAudioClient</c> object supports exactly one connection to the audio engine or audio hardware. This connection lasts for
		/// the lifetime of the <c>IAudioClient</c> object.
		/// </para>
		/// <para>The client should call the following methods only after calling <c>Initialize</c>:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>IAudioClient::GetBufferSize</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetCurrentPadding</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetService</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetStreamLatency</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Reset</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::SetEventHandle</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Start</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Stop</term>
		/// </item>
		/// </list>
		/// <para>The following methods do not require that <c>Initialize</c> be called first:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>IAudioClient::GetDevicePeriod</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetMixFormat</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::IsFormatSupported</term>
		/// </item>
		/// </list>
		/// <para>These methods can be called any time after activating the <c>IAudioClient</c> interface.</para>
		/// <para>
		/// Before calling <c>Initialize</c> to set up a shared-mode or exclusive-mode connection, the client can call the
		/// IAudioClient::IsFormatSupported method to discover whether the audio engine or audio endpoint device supports a particular
		/// format in that mode. Before opening a shared-mode connection, the client can obtain the audio engine's mix format by calling the
		/// IAudioClient::GetMixFormat method.
		/// </para>
		/// <para>
		/// The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from occurring
		/// in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client thread
		/// periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a capture
		/// endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the buffer. In
		/// either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough to accommodate
		/// the longer of the two periods without allowing glitches to occur.
		/// </para>
		/// <para>
		/// The client specifies a buffer size through the hnsBufferDuration parameter. The client is responsible for requesting a buffer
		/// that is large enough to ensure that glitches cannot occur between the periodic processing passes that it performs on the buffer.
		/// Similarly, the <c>Initialize</c> method ensures that the buffer is never smaller than the minimum buffer size needed to ensure
		/// that glitches do not occur between the periodic processing passes that the engine thread performs on the buffer. If the client
		/// requests a buffer size that is smaller than the audio engine's minimum required buffer size, the method sets the buffer size to
		/// this minimum buffer size rather than to the buffer size requested by the client.
		/// </para>
		/// <para>
		/// If the client requests a buffer size (through the hnsBufferDuration parameter) that is not an integral number of audio frames,
		/// the method rounds up the requested buffer size to the next integral number of frames.
		/// </para>
		/// <para>
		/// Following the <c>Initialize</c> call, the client should call the IAudioClient::GetBufferSize method to get the precise size of
		/// the endpoint buffer. During each processing pass, the client will need the actual buffer size to calculate how much data to
		/// transfer to or from the buffer. The client calls the IAudioClient::GetCurrentPadding method to determine how much of the data in
		/// the buffer is currently available for processing.
		/// </para>
		/// <para>
		/// To achieve the minimum stream latency between the client application and audio endpoint device, the client thread should run at
		/// the same period as the audio engine thread. The period of the engine thread is fixed and cannot be controlled by the client.
		/// Making the client's period smaller than the engine's period unnecessarily increases the client thread's load on the processor
		/// without improving latency or decreasing the buffer size. To determine the period of the engine thread, the client can call the
		/// IAudioClient::GetDevicePeriod method. To set the buffer to the minimum size required by the engine thread, the client should
		/// call <c>Initialize</c> with the hnsBufferDuration parameter set to 0. Following the <c>Initialize</c> call, the client can get
		/// the size of the resulting buffer by calling <c>IAudioClient::GetBufferSize</c>.
		/// </para>
		/// <para>
		/// A client has the option of requesting a buffer size that is larger than what is strictly necessary to make timing glitches rare
		/// or nonexistent. Increasing the buffer size does not necessarily increase the stream latency. For a rendering stream, the latency
		/// through the buffer is determined solely by the separation between the client's write pointer and the engine's read pointer. For
		/// a capture stream, the latency through the buffer is determined solely by the separation between the engine's write pointer and
		/// the client's read pointer.
		/// </para>
		/// <para>
		/// The loopback flag (AUDCLNT_STREAMFLAGS_LOOPBACK) enables audio loopback. A client can enable audio loopback only on a rendering
		/// endpoint with a shared-mode stream. Audio loopback is provided primarily to support acoustic echo cancellation (AEC).
		/// </para>
		/// <para>
		/// An AEC client requires both a rendering endpoint and the ability to capture the output stream from the audio engine. The
		/// engine's output stream is the global mix that the audio device plays through the speakers. If audio loopback is enabled, a
		/// client can open a capture buffer for the global audio mix by calling the IAudioClient::GetService method to obtain an
		/// IAudioCaptureClient interface on the rendering stream object. If audio loopback is not enabled, then an attempt to open a
		/// capture buffer on a rendering stream will fail. The loopback data in the capture buffer is in the device format, which the
		/// client can obtain by querying the device's PKEY_AudioEngine_DeviceFormat property.
		/// </para>
		/// <para>
		/// On Windows versions prior to Windows 10, a pull-mode capture client will not receive any events when a stream is initialized
		/// with event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) and is loopback-enabled (AUDCLNT_STREAMFLAGS_LOOPBACK). If the
		/// stream is opened with this configuration, the <c>Initialize</c> call succeeds, but relevant events are not raised to notify the
		/// capture client each time a buffer becomes ready for processing. To work around this, initialize a render stream in event-driven
		/// mode. Each time the client receives an event for the render stream, it must signal the capture client to run the capture thread
		/// that reads the next set of samples from the capture endpoint buffer. As of Windows 10 the relevant event handles are now set for
		/// loopback-enabled streams that are active.
		/// </para>
		/// <para>
		/// Note that all streams must be opened in share mode because exclusive-mode streams cannot operate in loopback mode. For more
		/// information about audio loopback, see Loopback Recording.
		/// </para>
		/// <para>
		/// The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag indicates that processing of the audio buffer by the client will be event driven.
		/// WASAPI supports event-driven buffering to enable low-latency processing of both shared-mode and exclusive-mode streams.
		/// </para>
		/// <para>
		/// The initial release of Windows Vista supports event-driven buffering (that is, the use of the AUDCLNT_STREAMFLAGS_EVENTCALLBACK
		/// flag) for rendering streams only.
		/// </para>
		/// <para>
		/// In the initial release of Windows Vista, for capture streams, the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is supported only in
		/// shared mode. Setting this flag has no effect for exclusive-mode capture streams. That is, although the application specifies
		/// this flag in exclusive mode through the <c>Initialize</c> call, the application will not receive any events that are usually
		/// required to capture the audio stream. In the Windows Vista Service Pack 1 release, this flag is functional in shared-mode and
		/// exclusive mode; an application can set this flag to enable event-buffering for capture streams. For more information about
		/// capturing an audio stream, see Capturing a Stream.
		/// </para>
		/// <para>
		/// To enable event-driven buffering, the client must provide an event handle to the system. Following the <c>Initialize</c> call
		/// and before calling the IAudioClient::Start method to start the stream, the client must call the IAudioClient::SetEventHandle
		/// method to set the event handle. While the stream is running, the system periodically signals the event to indicate to the client
		/// that audio data is available for processing. Between processing passes, the client thread waits on the event handle by calling a
		/// synchronization function such as <c>WaitForSingleObject</c>. For more information about synchronization functions, see the
		/// Windows SDK documentation.
		/// </para>
		/// <para>
		/// For a shared-mode stream that uses event-driven buffering, the caller must set both hnsPeriodicity and hnsBufferDuration to 0.
		/// The <c>Initialize</c> method determines how large a buffer to allocate based on the scheduling period of the audio engine.
		/// Although the client's buffer processing thread is event driven, the basic buffer management process, as described previously, is
		/// unaltered. Each time the thread awakens, it should call IAudioClient::GetCurrentPadding to determine how much data to write to a
		/// rendering buffer or read from a capture buffer. In contrast to the two buffers that the <c>Initialize</c> method allocates for
		/// an exclusive-mode stream that uses event-driven buffering, a shared-mode stream requires a single buffer.
		/// </para>
		/// <para>
		/// For an exclusive-mode stream that uses event-driven buffering, the caller must specify nonzero values for hnsPeriodicity and
		/// hnsBufferDuration, and the values of these two parameters must be equal. The <c>Initialize</c> method allocates two buffers for
		/// the stream. Each buffer is equal in duration to the value of the hnsBufferDuration parameter. Following the <c>Initialize</c>
		/// call for a rendering stream, the caller should fill the first of the two buffers before starting the stream. For a capture
		/// stream, the buffers are initially empty, and the caller should assume that each buffer remains empty until the event for that
		/// buffer is signaled. While the stream is running, the system alternately sends one buffer or the other to the client—this form of
		/// double buffering is referred to as "ping-ponging". Each time the client receives a buffer from the system (which the system
		/// indicates by signaling the event), the client must process the entire buffer. For example, if the client requests a packet size
		/// from the IAudioRenderClient::GetBuffer method that does not match the buffer size, the method fails. Calls to the
		/// <c>IAudioClient::GetCurrentPadding</c> method are unnecessary because the packet size must always equal the buffer size. In
		/// contrast to the buffering modes discussed previously, the latency for an event-driven, exclusive-mode stream depends directly on
		/// the buffer size.
		/// </para>
		/// <para>
		/// As explained in Audio Sessions, the default behavior for a session that contains rendering streams is that its volume and mute
		/// settings persist across system restarts. The AUDCLNT_STREAMFLAGS_NOPERSIST flag overrides the default behavior and makes the
		/// settings nonpersistent. This flag has no effect on sessions that contain capture streams—the settings for those sessions are
		/// never persistent. In addition, the settings for a session that contains a loopback stream (a stream that is initialized with the
		/// AUDCLNT_STREAMFLAGS_LOOPBACK flag) are not persistent.
		/// </para>
		/// <para>
		/// Only a session that connects to a rendering endpoint device can have persistent volume and mute settings. The first stream to be
		/// added to the session determines whether the session's settings are persistent. Thus, if the AUDCLNT_STREAMFLAGS_NOPERSIST or
		/// AUDCLNT_STREAMFLAGS_LOOPBACK flag is set during initialization of the first stream, the session's settings are not persistent.
		/// Otherwise, they are persistent. Their persistence is unaffected by additional streams that might be subsequently added or
		/// removed during the lifetime of the session object.
		/// </para>
		/// <para>
		/// After a call to <c>Initialize</c> has successfully initialized an <c>IAudioClient</c> interface instance, a subsequent
		/// <c>Initialize</c> call to initialize the same interface instance will fail and return error code E_ALREADY_INITIALIZED.
		/// </para>
		/// <para>
		/// If the initial call to <c>Initialize</c> fails, subsequent <c>Initialize</c> calls might fail and return error code
		/// E_ALREADY_INITIALIZED, even though the interface has not been initialized. If this occurs, release the <c>IAudioClient</c>
		/// interface and obtain a new <c>IAudioClient</c> interface from the MMDevice API before calling <c>Initialize</c> again.
		/// </para>
		/// <para>For code examples that call the <c>Initialize</c> method, see the following topics:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Capturing a Stream</term>
		/// </item>
		/// <item>
		/// <term>Exclusive-Mode Streams</term>
		/// </item>
		/// </list>
		/// <para>
		/// Starting with Windows 7, <c>Initialize</c> can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render or a capture device. This
		/// indicates that the buffer size, specified by the caller in the hnsBufferDuration parameter, is not aligned. This error code is
		/// returned only if the caller requested an exclusive-mode stream (AUDCLNT_SHAREMODE_EXCLUSIVE) and event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).
		/// </para>
		/// <para>
		/// If <c>Initialize</c> returns AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, the caller must call <c>Initialize</c> again and specify the
		/// aligned buffer size. Use the following steps:
		/// </para>
		/// <list type="number">
		/// <item>
		/// <term>Call IAudioClient::GetBufferSize and receive the next-highest-aligned buffer size (in frames).</term>
		/// </item>
		/// <item>
		/// <term>Call <c>IAudioClient::Release</c> to release the audio client used in the previous call that returned AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.</term>
		/// </item>
		/// <item>
		/// <term>
		/// Calculate the aligned buffer size in 100-nansecond units (hns). The buffer size is . In this formula, is the buffer size
		/// retrieved by GetBufferSize.
		/// </term>
		/// </item>
		/// <item>
		/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient to create a new audio client.</term>
		/// </item>
		/// <item>
		/// <term>Call <c>Initialize</c> again on the created audio client and specify the new buffer size and periodicity.</term>
		/// </item>
		/// </list>
		/// <para>
		/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
		/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must specify the
		/// <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to <c>IAudioClient::Initialize</c>.
		/// </para>
		/// <para>Examples</para>
		/// <para>The following example code shows how to respond to the <c>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</c> return code.</para>
		/// </remarks>
		public static HRESULT Initialize(this IAudioClient client, [In] AUDCLNT_SHAREMODE ShareMode, AUDCLNT_STREAMFLAGS StreamFlags, long hnsBufferDuration, long hnsPeriodicity, in WAVEFORMATEX pFormat, [In, Optional] in Guid AudioSessionGuid)
		{
			using var mem = SafeCoTaskMemHandle.CreateFromStructure(pFormat);
			return client.Initialize(ShareMode, StreamFlags, hnsBufferDuration, hnsPeriodicity, mem, AudioSessionGuid);
		}

		/// <summary>The <c>Initialize</c> method initializes the audio stream.</summary>
		/// <param name="client">The client.</param>
		/// <param name="ShareMode">
		/// <para>
		/// The sharing mode for the connection. Through this parameter, the client tells the audio engine whether it wants to share the
		/// audio endpoint device with other clients. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
		/// enumeration values:
		/// </para>
		/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
		/// <para>AUDCLNT_SHAREMODE_SHARED</para>
		/// </param>
		/// <param name="StreamFlags">
		/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of the
		/// AUDCLNT_STREAMFLAGS_XXX Constants or the AUDCLNT_SESSIONFLAGS_XXX Constants.
		/// </param>
		/// <param name="hnsBufferDuration">
		/// The buffer capacity as a time value. This parameter is of type <c>REFERENCE_TIME</c> and is expressed in 100-nanosecond units.
		/// This parameter contains the buffer size that the caller requests for the buffer that the audio application will share with the
		/// audio engine (in shared mode) or with the endpoint device (in exclusive mode). If the call succeeds, the method allocates a
		/// buffer that is a least this large. For more information about <c>REFERENCE_TIME</c>, see the Windows SDK documentation. For more
		/// information about buffering requirements, see Remarks.
		/// </param>
		/// <param name="hnsPeriodicity">
		/// The device period. This parameter can be nonzero only in exclusive mode. In shared mode, always set this parameter to 0. In
		/// exclusive mode, this parameter specifies the requested scheduling period for successive buffer accesses by the audio endpoint
		/// device. If the requested device period lies outside the range that is set by the device's minimum period and the system's
		/// maximum period, then the method clamps the period to that range. If this parameter is 0, the method sets the device period to
		/// its default value. To obtain the default device period, call the IAudioClient::GetDevicePeriod method. If the
		/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK stream flag is set and AUDCLNT_SHAREMODE_EXCLUSIVE is set as the ShareMode, then
		/// hnsPeriodicity must be nonzero and equal to hnsBufferDuration.
		/// </param>
		/// <param name="pFormat">
		/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type <c>WAVEFORMATEX</c> (or
		/// <c>WAVEFORMATEXTENSIBLE</c>). For more information, see Remarks.
		/// </param>
		/// <param name="AudioSessionGuid">
		/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs to.
		/// If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the GUID does
		/// not identify an existing session, the method opens a new session and adds the stream to that session. The stream remains a
		/// member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a pointer to a
		/// GUID_NULL value.
		/// </param>
		/// <returns>
		/// <para>
		/// If the method succeeds, it returns S_OK. If it fails, possible return codes include, but are not limited to, the values shown in
		/// the following table.
		/// </para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>AUDCLNT_E_ALREADY_INITIALIZED</term>
		/// <term>The IAudioClient object is already initialized.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_WRONG_ENDPOINT_TYPE</term>
		/// <term>The AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but the endpoint device is a capture device, not a rendering device.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</term>
		/// <term>
		/// The requested buffer size is not aligned. This code can be returned for a render or a capture device if the caller specified
		/// AUDCLNT_SHAREMODE_EXCLUSIVE and the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flags. The caller must call Initialize again with the
		/// aligned buffer size. For more information, see Remarks.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFFER_SIZE_ERROR</term>
		/// <term>
		/// Indicates that the buffer duration value requested by an exclusive-mode client is out of range. The requested duration value for
		/// pull mode must not be greater than 500 milliseconds; for push mode the duration value must not be greater than 2 seconds.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_CPUUSAGE_EXCEEDED</term>
		/// <term>
		/// Indicates that the process-pass duration exceeded the maximum CPU usage. The audio engine keeps track of CPU usage by
		/// maintaining the number of times the process-pass duration exceeds the maximum CPU usage. The maximum CPU usage is calculated as
		/// a percent of the engine's periodicity. The percentage value is the system's CPU throttle value (within the range of 10% and
		/// 90%). If this value is not found, then the default value of 40% is used to calculate the maximum CPU usage.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_DEVICE_INVALIDATED</term>
		/// <term>
		/// The audio endpoint device has been unplugged, or the audio hardware or associated hardware resources have been reconfigured,
		/// disabled, removed, or otherwise made unavailable for use.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_DEVICE_IN_USE</term>
		/// <term>
		/// The endpoint device is already in use. Either the device is being used in exclusive mode, or the device is being used in shared
		/// mode and the caller asked to use the device in exclusive mode.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_ENDPOINT_CREATE_FAILED</term>
		/// <term>
		/// The method failed to create the audio endpoint for the render or the capture device. This can occur if the audio endpoint device
		/// has been unplugged, or the audio hardware or associated hardware resources have been reconfigured, disabled, removed, or
		/// otherwise made unavailable for use.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_INVALID_DEVICE_PERIOD</term>
		/// <term>Indicates that the device period requested by an exclusive-mode client is greater than 500 milliseconds.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_UNSUPPORTED_FORMAT</term>
		/// <term>The audio engine (shared mode) or audio endpoint device (exclusive mode) does not support the specified format.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED</term>
		/// <term>
		/// The caller is requesting exclusive-mode use of the endpoint device, but the user has disabled exclusive-mode use of the device.
		/// </term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL</term>
		/// <term>The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is set but parameters hnsBufferDuration and hnsPeriodicity are not equal.</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_E_SERVICE_NOT_RUNNING</term>
		/// <term>The Windows audio service is not running.</term>
		/// </item>
		/// <item>
		/// <term>E_POINTER</term>
		/// <term>Parameter pFormat is NULL.</term>
		/// </item>
		/// <item>
		/// <term>E_INVALIDARG</term>
		/// <term>
		/// Parameter pFormat points to an invalid format description; or the AUDCLNT_STREAMFLAGS_LOOPBACK flag is set but ShareMode is not
		/// equal to AUDCLNT_SHAREMODE_SHARED; or the AUDCLNT_STREAMFLAGS_CROSSPROCESS flag is set but ShareMode is equal to
		/// AUDCLNT_SHAREMODE_EXCLUSIVE. A prior call to SetClientProperties was made with an invalid category for audio/render streams.
		/// </term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Out of memory.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>
		/// After activating an IAudioClient interface on an audio endpoint device, the client must successfully call <c>Initialize</c> once
		/// and only once to initialize the audio stream between the client and the device. The client can either connect directly to the
		/// audio hardware (exclusive mode) or indirectly through the audio engine (shared mode). In the <c>Initialize</c> call, the client
		/// specifies the audio data format, the buffer size, and audio session for the stream.
		/// </para>
		/// <para>
		/// <c>Note</c> In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from an
		/// MTA thread may result in undefined behavior.
		/// </para>
		/// <para>
		/// An attempt to create a shared-mode stream can succeed only if the audio device is already operating in shared mode or the device
		/// is currently unused. An attempt to create a shared-mode stream fails if the device is already operating in exclusive mode.
		/// </para>
		/// <para>
		/// If a stream is initialized to be event driven and in shared mode, ShareMode is set to AUDCLNT_SHAREMODE_SHARED and one of the
		/// stream flags that are set includes AUDCLNT_STREAMFLAGS_EVENTCALLBACK. For such a stream, the associated application must also
		/// obtain a handle by making a call to IAudioClient::SetEventHandle. When it is time to retire the stream, the audio engine can
		/// then use the handle to release the stream objects. Failure to call <c>IAudioClient::SetEventHandle</c> before releasing the
		/// stream objects can cause a delay of several seconds (a time-out period) while the audio engine waits for an available handle.
		/// After the time-out period expires, the audio engine then releases the stream objects.
		/// </para>
		/// <para>
		/// Whether an attempt to create an exclusive-mode stream succeeds depends on several factors, including the availability of the
		/// device and the user-controlled settings that govern exclusive-mode operation of the device. For more information, see
		/// Exclusive-Mode Streams.
		/// </para>
		/// <para>
		/// An <c>IAudioClient</c> object supports exactly one connection to the audio engine or audio hardware. This connection lasts for
		/// the lifetime of the <c>IAudioClient</c> object.
		/// </para>
		/// <para>The client should call the following methods only after calling <c>Initialize</c>:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>IAudioClient::GetBufferSize</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetCurrentPadding</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetService</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetStreamLatency</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Reset</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::SetEventHandle</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Start</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::Stop</term>
		/// </item>
		/// </list>
		/// <para>The following methods do not require that <c>Initialize</c> be called first:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>IAudioClient::GetDevicePeriod</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::GetMixFormat</term>
		/// </item>
		/// <item>
		/// <term>IAudioClient::IsFormatSupported</term>
		/// </item>
		/// </list>
		/// <para>These methods can be called any time after activating the <c>IAudioClient</c> interface.</para>
		/// <para>
		/// Before calling <c>Initialize</c> to set up a shared-mode or exclusive-mode connection, the client can call the
		/// IAudioClient::IsFormatSupported method to discover whether the audio engine or audio endpoint device supports a particular
		/// format in that mode. Before opening a shared-mode connection, the client can obtain the audio engine's mix format by calling the
		/// IAudioClient::GetMixFormat method.
		/// </para>
		/// <para>
		/// The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from occurring
		/// in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client thread
		/// periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a capture
		/// endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the buffer. In
		/// either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough to accommodate
		/// the longer of the two periods without allowing glitches to occur.
		/// </para>
		/// <para>
		/// The client specifies a buffer size through the hnsBufferDuration parameter. The client is responsible for requesting a buffer
		/// that is large enough to ensure that glitches cannot occur between the periodic processing passes that it performs on the buffer.
		/// Similarly, the <c>Initialize</c> method ensures that the buffer is never smaller than the minimum buffer size needed to ensure
		/// that glitches do not occur between the periodic processing passes that the engine thread performs on the buffer. If the client
		/// requests a buffer size that is smaller than the audio engine's minimum required buffer size, the method sets the buffer size to
		/// this minimum buffer size rather than to the buffer size requested by the client.
		/// </para>
		/// <para>
		/// If the client requests a buffer size (through the hnsBufferDuration parameter) that is not an integral number of audio frames,
		/// the method rounds up the requested buffer size to the next integral number of frames.
		/// </para>
		/// <para>
		/// Following the <c>Initialize</c> call, the client should call the IAudioClient::GetBufferSize method to get the precise size of
		/// the endpoint buffer. During each processing pass, the client will need the actual buffer size to calculate how much data to
		/// transfer to or from the buffer. The client calls the IAudioClient::GetCurrentPadding method to determine how much of the data in
		/// the buffer is currently available for processing.
		/// </para>
		/// <para>
		/// To achieve the minimum stream latency between the client application and audio endpoint device, the client thread should run at
		/// the same period as the audio engine thread. The period of the engine thread is fixed and cannot be controlled by the client.
		/// Making the client's period smaller than the engine's period unnecessarily increases the client thread's load on the processor
		/// without improving latency or decreasing the buffer size. To determine the period of the engine thread, the client can call the
		/// IAudioClient::GetDevicePeriod method. To set the buffer to the minimum size required by the engine thread, the client should
		/// call <c>Initialize</c> with the hnsBufferDuration parameter set to 0. Following the <c>Initialize</c> call, the client can get
		/// the size of the resulting buffer by calling <c>IAudioClient::GetBufferSize</c>.
		/// </para>
		/// <para>
		/// A client has the option of requesting a buffer size that is larger than what is strictly necessary to make timing glitches rare
		/// or nonexistent. Increasing the buffer size does not necessarily increase the stream latency. For a rendering stream, the latency
		/// through the buffer is determined solely by the separation between the client's write pointer and the engine's read pointer. For
		/// a capture stream, the latency through the buffer is determined solely by the separation between the engine's write pointer and
		/// the client's read pointer.
		/// </para>
		/// <para>
		/// The loopback flag (AUDCLNT_STREAMFLAGS_LOOPBACK) enables audio loopback. A client can enable audio loopback only on a rendering
		/// endpoint with a shared-mode stream. Audio loopback is provided primarily to support acoustic echo cancellation (AEC).
		/// </para>
		/// <para>
		/// An AEC client requires both a rendering endpoint and the ability to capture the output stream from the audio engine. The
		/// engine's output stream is the global mix that the audio device plays through the speakers. If audio loopback is enabled, a
		/// client can open a capture buffer for the global audio mix by calling the IAudioClient::GetService method to obtain an
		/// IAudioCaptureClient interface on the rendering stream object. If audio loopback is not enabled, then an attempt to open a
		/// capture buffer on a rendering stream will fail. The loopback data in the capture buffer is in the device format, which the
		/// client can obtain by querying the device's PKEY_AudioEngine_DeviceFormat property.
		/// </para>
		/// <para>
		/// On Windows versions prior to Windows 10, a pull-mode capture client will not receive any events when a stream is initialized
		/// with event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) and is loopback-enabled (AUDCLNT_STREAMFLAGS_LOOPBACK). If the
		/// stream is opened with this configuration, the <c>Initialize</c> call succeeds, but relevant events are not raised to notify the
		/// capture client each time a buffer becomes ready for processing. To work around this, initialize a render stream in event-driven
		/// mode. Each time the client receives an event for the render stream, it must signal the capture client to run the capture thread
		/// that reads the next set of samples from the capture endpoint buffer. As of Windows 10 the relevant event handles are now set for
		/// loopback-enabled streams that are active.
		/// </para>
		/// <para>
		/// Note that all streams must be opened in share mode because exclusive-mode streams cannot operate in loopback mode. For more
		/// information about audio loopback, see Loopback Recording.
		/// </para>
		/// <para>
		/// The AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag indicates that processing of the audio buffer by the client will be event driven.
		/// WASAPI supports event-driven buffering to enable low-latency processing of both shared-mode and exclusive-mode streams.
		/// </para>
		/// <para>
		/// The initial release of Windows Vista supports event-driven buffering (that is, the use of the AUDCLNT_STREAMFLAGS_EVENTCALLBACK
		/// flag) for rendering streams only.
		/// </para>
		/// <para>
		/// In the initial release of Windows Vista, for capture streams, the AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag is supported only in
		/// shared mode. Setting this flag has no effect for exclusive-mode capture streams. That is, although the application specifies
		/// this flag in exclusive mode through the <c>Initialize</c> call, the application will not receive any events that are usually
		/// required to capture the audio stream. In the Windows Vista Service Pack 1 release, this flag is functional in shared-mode and
		/// exclusive mode; an application can set this flag to enable event-buffering for capture streams. For more information about
		/// capturing an audio stream, see Capturing a Stream.
		/// </para>
		/// <para>
		/// To enable event-driven buffering, the client must provide an event handle to the system. Following the <c>Initialize</c> call
		/// and before calling the IAudioClient::Start method to start the stream, the client must call the IAudioClient::SetEventHandle
		/// method to set the event handle. While the stream is running, the system periodically signals the event to indicate to the client
		/// that audio data is available for processing. Between processing passes, the client thread waits on the event handle by calling a
		/// synchronization function such as <c>WaitForSingleObject</c>. For more information about synchronization functions, see the
		/// Windows SDK documentation.
		/// </para>
		/// <para>
		/// For a shared-mode stream that uses event-driven buffering, the caller must set both hnsPeriodicity and hnsBufferDuration to 0.
		/// The <c>Initialize</c> method determines how large a buffer to allocate based on the scheduling period of the audio engine.
		/// Although the client's buffer processing thread is event driven, the basic buffer management process, as described previously, is
		/// unaltered. Each time the thread awakens, it should call IAudioClient::GetCurrentPadding to determine how much data to write to a
		/// rendering buffer or read from a capture buffer. In contrast to the two buffers that the <c>Initialize</c> method allocates for
		/// an exclusive-mode stream that uses event-driven buffering, a shared-mode stream requires a single buffer.
		/// </para>
		/// <para>
		/// For an exclusive-mode stream that uses event-driven buffering, the caller must specify nonzero values for hnsPeriodicity and
		/// hnsBufferDuration, and the values of these two parameters must be equal. The <c>Initialize</c> method allocates two buffers for
		/// the stream. Each buffer is equal in duration to the value of the hnsBufferDuration parameter. Following the <c>Initialize</c>
		/// call for a rendering stream, the caller should fill the first of the two buffers before starting the stream. For a capture
		/// stream, the buffers are initially empty, and the caller should assume that each buffer remains empty until the event for that
		/// buffer is signaled. While the stream is running, the system alternately sends one buffer or the other to the client—this form of
		/// double buffering is referred to as "ping-ponging". Each time the client receives a buffer from the system (which the system
		/// indicates by signaling the event), the client must process the entire buffer. For example, if the client requests a packet size
		/// from the IAudioRenderClient::GetBuffer method that does not match the buffer size, the method fails. Calls to the
		/// <c>IAudioClient::GetCurrentPadding</c> method are unnecessary because the packet size must always equal the buffer size. In
		/// contrast to the buffering modes discussed previously, the latency for an event-driven, exclusive-mode stream depends directly on
		/// the buffer size.
		/// </para>
		/// <para>
		/// As explained in Audio Sessions, the default behavior for a session that contains rendering streams is that its volume and mute
		/// settings persist across system restarts. The AUDCLNT_STREAMFLAGS_NOPERSIST flag overrides the default behavior and makes the
		/// settings nonpersistent. This flag has no effect on sessions that contain capture streams—the settings for those sessions are
		/// never persistent. In addition, the settings for a session that contains a loopback stream (a stream that is initialized with the
		/// AUDCLNT_STREAMFLAGS_LOOPBACK flag) are not persistent.
		/// </para>
		/// <para>
		/// Only a session that connects to a rendering endpoint device can have persistent volume and mute settings. The first stream to be
		/// added to the session determines whether the session's settings are persistent. Thus, if the AUDCLNT_STREAMFLAGS_NOPERSIST or
		/// AUDCLNT_STREAMFLAGS_LOOPBACK flag is set during initialization of the first stream, the session's settings are not persistent.
		/// Otherwise, they are persistent. Their persistence is unaffected by additional streams that might be subsequently added or
		/// removed during the lifetime of the session object.
		/// </para>
		/// <para>
		/// After a call to <c>Initialize</c> has successfully initialized an <c>IAudioClient</c> interface instance, a subsequent
		/// <c>Initialize</c> call to initialize the same interface instance will fail and return error code E_ALREADY_INITIALIZED.
		/// </para>
		/// <para>
		/// If the initial call to <c>Initialize</c> fails, subsequent <c>Initialize</c> calls might fail and return error code
		/// E_ALREADY_INITIALIZED, even though the interface has not been initialized. If this occurs, release the <c>IAudioClient</c>
		/// interface and obtain a new <c>IAudioClient</c> interface from the MMDevice API before calling <c>Initialize</c> again.
		/// </para>
		/// <para>For code examples that call the <c>Initialize</c> method, see the following topics:</para>
		/// <list type="bullet">
		/// <item>
		/// <term>Rendering a Stream</term>
		/// </item>
		/// <item>
		/// <term>Capturing a Stream</term>
		/// </item>
		/// <item>
		/// <term>Exclusive-Mode Streams</term>
		/// </item>
		/// </list>
		/// <para>
		/// Starting with Windows 7, <c>Initialize</c> can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render or a capture device. This
		/// indicates that the buffer size, specified by the caller in the hnsBufferDuration parameter, is not aligned. This error code is
		/// returned only if the caller requested an exclusive-mode stream (AUDCLNT_SHAREMODE_EXCLUSIVE) and event-driven buffering (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).
		/// </para>
		/// <para>
		/// If <c>Initialize</c> returns AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, the caller must call <c>Initialize</c> again and specify the
		/// aligned buffer size. Use the following steps:
		/// </para>
		/// <list type="number">
		/// <item>
		/// <term>Call IAudioClient::GetBufferSize and receive the next-highest-aligned buffer size (in frames).</term>
		/// </item>
		/// <item>
		/// <term>Call <c>IAudioClient::Release</c> to release the audio client used in the previous call that returned AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.</term>
		/// </item>
		/// <item>
		/// <term>
		/// Calculate the aligned buffer size in 100-nansecond units (hns). The buffer size is . In this formula, is the buffer size
		/// retrieved by GetBufferSize.
		/// </term>
		/// </item>
		/// <item>
		/// <term>Call the IMMDevice::Activate method with parameter iid set to REFIID IID_IAudioClient to create a new audio client.</term>
		/// </item>
		/// <item>
		/// <term>Call <c>Initialize</c> again on the created audio client and specify the new buffer size and periodicity.</term>
		/// </item>
		/// </list>
		/// <para>
		/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
		/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the AudioClientProperties to TRUE, you must specify the
		/// <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to <c>IAudioClient::Initialize</c>.
		/// </para>
		/// <para>Examples</para>
		/// <para>The following example code shows how to respond to the <c>AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED</c> return code.</para>
		/// </remarks>
		public static HRESULT Initialize(this IAudioClient client, [In] AUDCLNT_SHAREMODE ShareMode, AUDCLNT_STREAMFLAGS StreamFlags, long hnsBufferDuration, long hnsPeriodicity, in WAVEFORMATEXTENSIBLE pFormat, [In, Optional] in Guid AudioSessionGuid)
		{
			using var mem = SafeCoTaskMemHandle.CreateFromStructure(pFormat);
			return client.Initialize(ShareMode, StreamFlags, hnsBufferDuration, hnsPeriodicity, mem, AudioSessionGuid);
		}

		/// <summary>Initializes a shared stream with the specified periodicity.</summary>
		/// <param name="client">The client.</param>
		/// <param name="StreamFlags">
		/// <para>Type: <c>DWORD</c></para>
		/// <para>
		/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of the
		/// supported AUDCLNT_STREAMFLAGS_XXX Constants or AUDCLNT_SESSIONFLAGS_XXX Constants. The supported AUDCLNT_STREAMFLAGS_XXX
		/// Constants for this parameter when using this method are:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY</term>
		/// </item>
		/// </list>
		/// </param>
		/// <param name="PeriodInFrames">
		/// <para>Type: <c>UINT32</c></para>
		/// <para>
		/// Periodicity requested by the client. This value must be an integral multiple of the value returned in the
		/// pFundamentalPeriodInFrames parameter to IAudioClient3::GetSharedModeEnginePeriod. PeriodInFrames must also be greater than or
		/// equal to the value returned in pMinPeriodInFrames and less than or equal to the value returned in pMaxPeriodInFrames.
		/// </para>
		/// </param>
		/// <param name="pFormat">
		/// <para>Type: <c>const WAVEFORMATEX*</c></para>
		/// <para>
		/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type WAVEFORMATEX or <c></c>
		/// WAVEFORMATEXTENSIBLE. For more information, see the Remarks section for IAudioClient::Initialize.
		/// </para>
		/// </param>
		/// <param name="AudioSessionGuid">
		/// <para>Type: <c>LPCGUID</c></para>
		/// <para>
		/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs to.
		/// If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the GUID does
		/// not identify an existing session, the method opens a new session and adds the stream to that session. The stream remains a
		/// member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a pointer to a
		/// GUID_NULL value.
		/// </para>
		/// </param>
		/// <remarks>
		/// <para>
		/// Unlike IAudioClient::Initialize, this method does not allow you to specify a buffer size. The buffer size is computed based on
		/// the periodicity requested with the PeriodInFrames parameter. It is the client app's responsibility to ensure that audio samples
		/// are transferred in and out of the buffer in a timely manner.
		/// </para>
		/// <para>
		/// Audio clients should check for allowed values for the PeriodInFrames parameter by calling
		/// IAudioClient3::GetSharedModeEnginePeriod. The value of PeriodInFrames must be an integral multiple of the value returned in the
		/// pFundamentalPeriodInFrames parameter. PeriodInFrames must also be greater than or equal to the value returned in
		/// pMinPeriodInFrames and less than or equal to the value of pMaxPeriodInFrames.
		/// </para>
		/// <para>For example, for a 44100 kHz format, <c>GetSharedModeEnginePeriod</c> might return:</para>
		/// <list type="bullet">
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// </list>
		/// <para>
		/// Allowed values for the PeriodInFrames parameter to <c>InitializeSharedAudioStream</c> would include 48 and 448. They would also
		/// include things like 96 and 128.
		/// </para>
		/// <para>
		/// They would NOT include 4 (which is smaller than the minimum allowed value) or 98 (which is not a multiple of the fundamental) or
		/// 1000 (which is larger than the maximum allowed value).
		/// </para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-initializesharedaudiostream HRESULT
		// InitializeSharedAudioStream( DWORD StreamFlags, UINT32 PeriodInFrames, const WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid );
		public static void InitializeSharedAudioStream(this IAudioClient3 client, AUDCLNT_STREAMFLAGS StreamFlags, [In] uint PeriodInFrames, in WAVEFORMATEX pFormat, [In, Optional] in Guid AudioSessionGuid)
		{
			using var mem = SafeCoTaskMemHandle.CreateFromStructure(pFormat);
			client.InitializeSharedAudioStream(StreamFlags, PeriodInFrames, mem, AudioSessionGuid);
		}

		/// <summary>Initializes a shared stream with the specified periodicity.</summary>
		/// <param name="client">The client.</param>
		/// <param name="StreamFlags">
		/// <para>Type: <c>DWORD</c></para>
		/// <para>
		/// Flags to control creation of the stream. The client should set this parameter to 0 or to the bitwise OR of one or more of the
		/// supported AUDCLNT_STREAMFLAGS_XXX Constants or AUDCLNT_SESSIONFLAGS_XXX Constants. The supported AUDCLNT_STREAMFLAGS_XXX
		/// Constants for this parameter when using this method are:
		/// </para>
		/// <list type="bullet">
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM</term>
		/// </item>
		/// <item>
		/// <term>AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY</term>
		/// </item>
		/// </list>
		/// </param>
		/// <param name="PeriodInFrames">
		/// <para>Type: <c>UINT32</c></para>
		/// <para>
		/// Periodicity requested by the client. This value must be an integral multiple of the value returned in the
		/// pFundamentalPeriodInFrames parameter to IAudioClient3::GetSharedModeEnginePeriod. PeriodInFrames must also be greater than or
		/// equal to the value returned in pMinPeriodInFrames and less than or equal to the value returned in pMaxPeriodInFrames.
		/// </para>
		/// </param>
		/// <param name="pFormat">
		/// <para>Type: <c>const WAVEFORMATEX*</c></para>
		/// <para>
		/// Pointer to a format descriptor. This parameter must point to a valid format descriptor of type WAVEFORMATEX or <c></c>
		/// WAVEFORMATEXTENSIBLE. For more information, see the Remarks section for IAudioClient::Initialize.
		/// </para>
		/// </param>
		/// <param name="AudioSessionGuid">
		/// <para>Type: <c>LPCGUID</c></para>
		/// <para>
		/// Pointer to a session GUID. This parameter points to a GUID value that identifies the audio session that the stream belongs to.
		/// If the GUID identifies a session that has been previously opened, the method adds the stream to that session. If the GUID does
		/// not identify an existing session, the method opens a new session and adds the stream to that session. The stream remains a
		/// member of the same session for its lifetime. Setting this parameter to <c>NULL</c> is equivalent to passing a pointer to a
		/// GUID_NULL value.
		/// </para>
		/// </param>
		/// <remarks>
		/// <para>
		/// Unlike IAudioClient::Initialize, this method does not allow you to specify a buffer size. The buffer size is computed based on
		/// the periodicity requested with the PeriodInFrames parameter. It is the client app's responsibility to ensure that audio samples
		/// are transferred in and out of the buffer in a timely manner.
		/// </para>
		/// <para>
		/// Audio clients should check for allowed values for the PeriodInFrames parameter by calling
		/// IAudioClient3::GetSharedModeEnginePeriod. The value of PeriodInFrames must be an integral multiple of the value returned in the
		/// pFundamentalPeriodInFrames parameter. PeriodInFrames must also be greater than or equal to the value returned in
		/// pMinPeriodInFrames and less than or equal to the value of pMaxPeriodInFrames.
		/// </para>
		/// <para>For example, for a 44100 kHz format, <c>GetSharedModeEnginePeriod</c> might return:</para>
		/// <list type="bullet">
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// <item>
		/// <term/>
		/// </item>
		/// </list>
		/// <para>
		/// Allowed values for the PeriodInFrames parameter to <c>InitializeSharedAudioStream</c> would include 48 and 448. They would also
		/// include things like 96 and 128.
		/// </para>
		/// <para>
		/// They would NOT include 4 (which is smaller than the minimum allowed value) or 98 (which is not a multiple of the fundamental) or
		/// 1000 (which is larger than the maximum allowed value).
		/// </para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-initializesharedaudiostream HRESULT
		// InitializeSharedAudioStream( DWORD StreamFlags, UINT32 PeriodInFrames, const WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid );
		public static void InitializeSharedAudioStream(this IAudioClient3 client, AUDCLNT_STREAMFLAGS StreamFlags, [In] uint PeriodInFrames, in WAVEFORMATEXTENSIBLE pFormat, [In, Optional] in Guid AudioSessionGuid)
		{
			using var mem = SafeCoTaskMemHandle.CreateFromStructure(pFormat);
			client.InitializeSharedAudioStream(StreamFlags, PeriodInFrames, mem, AudioSessionGuid);
		}

		/// <summary>The <c>IsFormatSupported</c> method indicates whether the audio endpoint device supports a particular stream format.</summary>
		/// <param name="client">The client.</param>
		/// <param name="ShareMode">
		/// <para>
		/// The sharing mode for the stream format. Through this parameter, the client indicates whether it wants to use the specified
		/// format in exclusive mode or shared mode. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
		/// enumeration values:
		/// </para>
		/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
		/// <para>AUDCLNT_SHAREMODE_SHARED</para>
		/// </param>
		/// <param name="pFormat">The specified stream format.</param>
		/// <param name="ppClosestMatch">
		/// A variable into which the method writes the address of a stream format structure. This structure specifies the supported format
		/// that is closest to the format that the client specified through the pFormat parameter.
		/// </param>
		/// <returns>
		/// <see langword="true"/> if the audio endpoint device supports the specified stream format; <see langword="false"/> if succeeded
		/// with a closest match to the specified format.
		/// </returns>
		/// <remarks>
		/// <para>
		/// This method provides a way for a client to determine, before calling IAudioClient::Initialize, whether the audio engine supports
		/// a particular stream format.
		/// </para>
		/// <para>
		/// For exclusive mode, <c>IsFormatSupported</c> returns S_OK if the audio endpoint device supports the caller-specified format, or
		/// it returns AUDCLNT_E_UNSUPPORTED_FORMAT if the device does not support the format. The ppClosestMatch parameter can be
		/// <c>NULL</c>. If it is not <c>NULL</c>, the method writes <c>NULL</c> to *ppClosestMatch.
		/// </para>
		/// <para>
		/// For shared mode, if the audio engine supports the caller-specified format, <c>IsFormatSupported</c> sets <c>*ppClosestMatch</c>
		/// to <c>NULL</c> and returns S_OK. If the audio engine does not support the caller-specified format but does support a similar
		/// format, the method retrieves the similar format through the ppClosestMatch parameter and returns S_FALSE. If the audio engine
		/// does not support the caller-specified format or any similar format, the method sets *ppClosestMatch to <c>NULL</c> and returns AUDCLNT_E_UNSUPPORTED_FORMAT.
		/// </para>
		/// <para>
		/// In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the
		/// IAudioClient::GetMixFormat method. In addition, the audio engine might support similar formats that have the same sample rate
		/// and number of channels as the mix format but differ in the representation of audio sample values. The audio engine represents
		/// sample values internally as floating-point numbers, but if the caller-specified format represents sample values as integers, the
		/// audio engine typically can convert between the integer sample values and its internal floating-point representation.
		/// </para>
		/// <para>
		/// The audio engine might be able to support an even wider range of shared-mode formats if the installation package for the audio
		/// device includes a local effects (LFX) audio processing object (APO) that can handle format conversions. An LFX APO is a software
		/// module that performs device-specific processing of an audio stream. The audio graph builder in the Windows audio service inserts
		/// the LFX APO into the stream between each client and the audio engine. When a client calls the <c>IsFormatSupported</c> method
		/// and the method determines that an LFX APO is installed for use with the device, the method directs the query to the LFX APO,
		/// which indicates whether it supports the caller-specified format.
		/// </para>
		/// <para>
		/// For example, a particular LFX APO might accept a 6-channel surround sound stream from a client and convert the stream to a
		/// stereo format that can be played through headphones. Typically, an LFX APO supports only client formats with sample rates that
		/// match the sample rate of the mix format.
		/// </para>
		/// <para>
		/// For more information about APOs, see the white papers titled "Custom Audio Effects in Windows Vista" and "Reusing the Windows
		/// Vista Audio System Effects" at the Audio Device Technologies for Windows website. For more information about the
		/// <c>IsFormatSupported</c> method, see Device Formats.
		/// </para>
		/// </remarks>
		public static bool IsFormatSupported(this IAudioClient client, [In] AUDCLNT_SHAREMODE ShareMode, in WAVEFORMATEX pFormat, out WAVEFORMATEX ppClosestMatch) =>
			IsFormatSupportedGeneric(client, ShareMode, pFormat, out ppClosestMatch);

		/// <summary>The <c>IsFormatSupported</c> method indicates whether the audio endpoint device supports a particular stream format.</summary>
		/// <param name="client">The client.</param>
		/// <param name="ShareMode">
		/// <para>
		/// The sharing mode for the stream format. Through this parameter, the client indicates whether it wants to use the specified
		/// format in exclusive mode or shared mode. The client should set this parameter to one of the following AUDCLNT_SHAREMODE
		/// enumeration values:
		/// </para>
		/// <para>AUDCLNT_SHAREMODE_EXCLUSIVE</para>
		/// <para>AUDCLNT_SHAREMODE_SHARED</para>
		/// </param>
		/// <param name="pFormat">The specified stream format.</param>
		/// <param name="ppClosestMatch">
		/// A variable into which the method writes the address of a stream format structure. This structure specifies the supported format
		/// that is closest to the format that the client specified through the pFormat parameter.
		/// </param>
		/// <returns>
		/// <see langword="true"/> if the audio endpoint device supports the specified stream format; <see langword="false"/> if succeeded
		/// with a closest match to the specified format.
		/// </returns>
		/// <remarks>
		/// <para>
		/// This method provides a way for a client to determine, before calling IAudioClient::Initialize, whether the audio engine supports
		/// a particular stream format.
		/// </para>
		/// <para>
		/// For exclusive mode, <c>IsFormatSupported</c> returns S_OK if the audio endpoint device supports the caller-specified format, or
		/// it returns AUDCLNT_E_UNSUPPORTED_FORMAT if the device does not support the format. The ppClosestMatch parameter can be
		/// <c>NULL</c>. If it is not <c>NULL</c>, the method writes <c>NULL</c> to *ppClosestMatch.
		/// </para>
		/// <para>
		/// For shared mode, if the audio engine supports the caller-specified format, <c>IsFormatSupported</c> sets <c>*ppClosestMatch</c>
		/// to <c>NULL</c> and returns S_OK. If the audio engine does not support the caller-specified format but does support a similar
		/// format, the method retrieves the similar format through the ppClosestMatch parameter and returns S_FALSE. If the audio engine
		/// does not support the caller-specified format or any similar format, the method sets *ppClosestMatch to <c>NULL</c> and returns AUDCLNT_E_UNSUPPORTED_FORMAT.
		/// </para>
		/// <para>
		/// In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the
		/// IAudioClient::GetMixFormat method. In addition, the audio engine might support similar formats that have the same sample rate
		/// and number of channels as the mix format but differ in the representation of audio sample values. The audio engine represents
		/// sample values internally as floating-point numbers, but if the caller-specified format represents sample values as integers, the
		/// audio engine typically can convert between the integer sample values and its internal floating-point representation.
		/// </para>
		/// <para>
		/// The audio engine might be able to support an even wider range of shared-mode formats if the installation package for the audio
		/// device includes a local effects (LFX) audio processing object (APO) that can handle format conversions. An LFX APO is a software
		/// module that performs device-specific processing of an audio stream. The audio graph builder in the Windows audio service inserts
		/// the LFX APO into the stream between each client and the audio engine. When a client calls the <c>IsFormatSupported</c> method
		/// and the method determines that an LFX APO is installed for use with the device, the method directs the query to the LFX APO,
		/// which indicates whether it supports the caller-specified format.
		/// </para>
		/// <para>
		/// For example, a particular LFX APO might accept a 6-channel surround sound stream from a client and convert the stream to a
		/// stereo format that can be played through headphones. Typically, an LFX APO supports only client formats with sample rates that
		/// match the sample rate of the mix format.
		/// </para>
		/// <para>
		/// For more information about APOs, see the white papers titled "Custom Audio Effects in Windows Vista" and "Reusing the Windows
		/// Vista Audio System Effects" at the Audio Device Technologies for Windows website. For more information about the
		/// <c>IsFormatSupported</c> method, see Device Formats.
		/// </para>
		/// </remarks>
		public static bool IsFormatSupported(this IAudioClient client, [In] AUDCLNT_SHAREMODE ShareMode, in WAVEFORMATEXTENSIBLE pFormat, out WAVEFORMATEXTENSIBLE ppClosestMatch) =>
			IsFormatSupportedGeneric(client, ShareMode, pFormat, out ppClosestMatch);

		private static bool IsFormatSupportedGeneric<T>(IAudioClient client, [In] AUDCLNT_SHAREMODE ShareMode, in T pFormat, out T ppClosestMatch) where T : struct
		{
			using var mem = SafeCoTaskMemHandle.CreateFromStructure<T>(pFormat);
			var hr = client.IsFormatSupported(ShareMode, mem, out var ret);
			if (hr != HRESULT.S_OK && hr != HRESULT.S_FALSE && hr != HRESULT.AUDCLNT_E_UNSUPPORTED_FORMAT)
				throw hr.GetException();
			ppClosestMatch = ret.ToStructure<T>();
			ret.Dispose();
			return hr == HRESULT.S_OK;
		}

		/// <summary>
		/// The <c>AudioClientProperties</c> structure is used to set the parameters that describe the properties of the client's audio stream.
		/// </summary>
		/// <remarks>
		/// Starting with Windows 10, hardware-offloaded audio streams must be event driven. This means that if you call
		/// IAudioClient2::SetClientProperties and set the bIsOffload parameter of the <c>AudioClientProperties</c> to TRUE, you must
		/// specify the <c>AUDCLNT_STREAMFLAGS_EVENTCALLBACK</c> flag in the StreamFlags parameter to IAudioClient::Initialize.
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/audioclient/ns-audioclient-audioclientproperties~r1 typedef struct
		// AudioClientProperties { UINT32 cbSize; BOOL bIsOffload; AUDIO_STREAM_CATEGORY eCategory; AUDCLNT_STREAMOPTIONS Options; } AudioClientProperties;
		[PInvokeData("audioclient.h")]
		[StructLayout(LayoutKind.Sequential)]
		public struct AudioClientProperties
		{
			/// <summary>The size of the <c>AudioClientProperties</c> structure, in bytes.</summary>
			public uint cbSize;

			/// <summary>Boolean value to indicate whether or not the audio stream is hardware-offloaded.</summary>
			[MarshalAs(UnmanagedType.Bool)] public bool bIsOffload;

			/// <summary>An enumeration that is used to specify the category of the audio stream.</summary>
			public AUDIO_STREAM_CATEGORY eCategory;

			/// <summary>
			/// <para>A member of the AUDCLNT_STREAMOPTIONS enumeration describing the characteristics of the stream.</para>
			/// <para>Supported in Windows 8.1 and later.</para>
			/// </summary>
			public AUDCLNT_STREAMOPTIONS Options;
		}
	}
}