using System; using System.Runtime.InteropServices; using Vanara.InteropServices; using static Vanara.PInvoke.PropSys; using IAudioMediaType = System.IntPtr; // TODO: Replace IAudioMediaType with reference to new library when done. namespace Vanara.PInvoke { /// Functions, structures and constants from Windows Core Audio Api. public static partial class CoreAudio { /// /// /// The APO_CONNECTION_BUFFER_TYPE enumeration defines constants that indicate whether the audio engine allocates the /// connection buffer or uses the buffer that is provided by the APO. These flags are used by the Type member of the /// APO_CONNECTION_DESCRIPTOR structure that stores the configuration settings of an APO connection. These settings are /// required by the audio engine when an APO connection is created. /// /// /// The Terminal Services AudioEndpoint API is for use in Remote Desktop scenarios; it is not for client applications. // https://docs.microsoft.com/en-us/previous-versions/dd408130(v=vs.85) typedef enum { APO_CONNECTION_BUFFER_TYPE_ALLOCATED = 0, // APO_CONNECTION_BUFFER_TYPE_EXTERNAL = 1, APO_CONNECTION_BUFFER_TYPE_DEPENDANT = 2 } APO_CONNECTION_BUFFER_TYPE; [PInvokeData("Audioenginebaseapo.h")] public enum APO_CONNECTION_BUFFER_TYPE { /// The connection buffer is internally allocated by the audio engine. APO_CONNECTION_BUFFER_TYPE_ALLOCATED = 0, /// /// The connection buffer is allocated by the APO, and the audio engine must use the connection buffer that is specified in the /// pBuffer member of the APO_CONNECTION_DESCRIPTOR structure. /// APO_CONNECTION_BUFFER_TYPE_EXTERNAL = 1, /// The connection buffer is extracted by the audio engine from another connection. APO_CONNECTION_BUFFER_TYPE_DEPENDANT = 2, } /// /// The APO_FLAG enumeration defines constants that are used as flags by an audio processing object (APO). /// This enumeration is used by the APO_REG_PROPERTIES structure to help describe the registration properties of an APO. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ne-audioenginebaseapo-apo_flag typedef enum APO_FLAG { // APO_FLAG_NONE, APO_FLAG_INPLACE, APO_FLAG_SAMPLESPERFRAME_MUST_MATCH, APO_FLAG_FRAMESPERSECOND_MUST_MATCH, // APO_FLAG_BITSPERSAMPLE_MUST_MATCH, APO_FLAG_MIXER, APO_FLAG_DEFAULT } ; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "42134625-A351-4CB6-B83C-3F2E662D1938")] [Flags] public enum APO_FLAG { /// Indicates that there are no flags enabled for this APO. APO_FLAG_NONE = 0x00, /// /// Indicates that this APO can perform in-place processing. This allows the processor to use a common buffer for input and output. /// APO_FLAG_INPLACE = 0x01, /// Indicates that the samples per frame for the input and output connections must match. APO_FLAG_SAMPLESPERFRAME_MUST_MATCH = 0x02, /// Indicates that the frames per second for the input and output connections must match. APO_FLAG_FRAMESPERSECOND_MUST_MATCH = 0x04, /// Indicates that bits per sample AND bytes per sample container for the input and output connections must match. APO_FLAG_BITSPERSAMPLE_MUST_MATCH = 0x08, /// APO_FLAG_MIXER = 0x10, /// /// The value of this member is determined by the logical OR result of the three preceding members. In other /// words:APO_FLAG_DEFAULT = ( APO_FLAG_SAMPLESPERFRAME_MUST_MATCH /// APO_FLAG_DEFAULT = APO_FLAG_SAMPLESPERFRAME_MUST_MATCH | APO_FLAG_FRAMESPERSECOND_MUST_MATCH | APO_FLAG_BITSPERSAMPLE_MUST_MATCH, } /// /// /// System Effects Audio Processing Objects (sAPOs) are typically used in or called from real-time process threads. However, it is /// sometimes necessary to use an sAPO in a non real-time mode. For example, when an sAPO is initialized, it is called from a non /// real-time thread. But when audio processing begins, the sAPO is called from a real-time thread. The interface exposes methods /// that enable a client to access the non real-time compliant parts of an sAPO. /// /// The interface supports the following methods: /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudioprocessingobject [PInvokeData("audioenginebaseapo.h", MSDNShortId = "71be0151-20dd-40e3-a478-d67e4d8d9c36")] [ComImport, Guid("FD7F2B29-24D0-4b5c-B177-592C39F9CA10"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioProcessingObject { /// /// The Reset method resets the APO to its original state. This method does not cause any changes in the connection objects that /// are attached to the input or the output of the APO. /// /// /// This method is not real-time compliant and must not be called from a real-time processing thread. The implementation of this /// method does not and must not touch paged memory. Additionally, it must not call any blocking system routines. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-reset // HRESULT Reset(); void Reset(); /// /// The GetLatency method returns the latency for this APO. Latency is the amount of time it takes a frame to traverse the /// processing pass of an APO. /// /// /// A MFTIME structure that will receive the number of units of delay that this APO introduces. Each unit of delay represents /// 100 nanoseconds. /// /// /// /// If the client that is calling this APO knows the sampling rate, the client can calculate the latency in terms of the number /// of frames. To get the total latency of the entire audio signal processing stream, the client must query every APO in the /// processing chain and add up the results. /// /// Important This method is not real-time compliant and must not be called from a real-time processing thread. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-getlatency // HRESULT GetLatency( HNSTIME *pTime ); long GetLatency(); /// GetRegistrationProperties returns the registration properties of the audio processing object (APO). /// The registration properties of the APO. This parameter is of type APO_REG_PROPERTIES. /// /// The caller must free the memory returned by . /// Note This method must not be called from a real-time processing thread. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-getregistrationproperties // HRESULT GetRegistrationProperties( APO_REG_PROPERTIES **ppRegProps ); SafeCoTaskMemHandle GetRegistrationProperties(); /// The Initialize method initializes the APO and supports data of variable length. /// This is the size, in bytes, of the initialization data. /// This is initialization data that is specific to this APO. /// /// If this method is used to initialize an APO without the need to initialize any data, it is acceptable to supply a /// NULL as the value of the pbyData parameter and a 0 (zero) as the value of the cbDataSize parameter. The data that is /// supplied is of variable length and must have the following format: /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-initialize // HRESULT Initialize( UINT32 cbDataSize, BYTE *pbyData ); void Initialize(uint cbDataSize, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] pbyData); /// /// This method negotiates with the Windows Vista audio engine to establish a data format for the stream of audio data. /// /// /// A pointer to an IAudioMediaType interface. This parameter is used to indicate the output format of the data. The value of /// pOppositeFormat must be set to NULL to indicate that the output format can be any type. /// /// /// A pointer to an IAudioMediaType interface. This parameter is used to indicate the input format that is to be verified. /// /// /// This parameter indicates the supported format that is closest to the format to be verified. /// /// /// /// If the call completed successfully, the ppSupportedInputFormat parameter returns a pRequestedInputFormat pointer and the /// IsInputFormatSupported method returns a value of S_OK. Otherwise, this method returns one of the following error codes: /// /// /// /// Return code /// Description /// /// /// S_FALSE /// The format of the input/output format pair is not supported. ppSupportedInputFormat returns a suggested new format. /// /// /// APOERR_FORMAT_NOT_SUPPORTED /// The format to be verified is not supported. The value of ppSupportedInputFormat does not change. /// /// /// E_POINTER /// Invalid pointer that is passed to the method. The value of ppSupportedInputFormat does not change. /// /// /// Other HRESULT values /// These additional error conditions are tracked by the audio engine. /// /// /// /// /// /// There are differences in the implementation of the method by the different APOs. For example, with certain implementations, /// the output can only be of type float when the input format is of type integer. /// /// /// To initiate format negotiation, the audio service first sets the output of the LFX sAPO to the default float32-based format. /// The audio service then calls the method of the LFX sAPO, suggests the default format, and monitors the HRESULT response of /// this method. If the input of the LFX sAPO can support the suggested format, it returns S_OK, together with a reference to /// the supported format. If the input of the LFX sAPO cannot support the suggested format, it returns S_FALSE together with a /// reference to a format that is the closest match to the suggested one. If the LFX sAPO cannot support the suggested format /// and does not have a close match, it returns APOERR_FORMAT_NOT_SUPPORTED. The GFX sAPO works with the output format of the /// LFX sAPO. So the GFX sAPO is not involved in the format negotiation process. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-isinputformatsupported // HRESULT IsInputFormatSupported( IAudioMediaType *pOppositeFormat, IAudioMediaType *pRequestedInputFormat, IAudioMediaType // **ppSupportedInputFormat ); [PreserveSig] HRESULT IsInputFormatSupported(IAudioMediaType pOppositeFormat, IAudioMediaType pRequestedInputFormat, out IAudioMediaType ppSupportedInputFormat); /// The method is used to verify that a specific output format is supported. /// /// A pointer to an IAudioMediaType interface. This parameter indicates the output format. This parameter must be set to /// NULL to indicate that the output format can be any type. /// /// /// A pointer to an IAudioMediaType interface. This parameter indicates the output format that is to be verified. /// /// /// This parameter indicates the supported output format that is closest to the format to be verified. /// /// /// /// If the call completes successfully, the ppSupportedOutputFormat parameter returns a pRequestedOutputFormat pointer and the /// IsOutputFormatSupported method returns a value of S_OK. Otherwise, this method returns one of the following error codes: /// /// /// /// Return code /// Description /// /// /// S_FALSE /// /// The format of Input/output format pair is not supported. The ppSupportedOutPutFormat parameter returns a suggested new format. /// /// /// /// APOERR_FORMAT_NOT_SUPPORTED /// The format is not supported. The value of ppSupportedOutputFormat does not change. /// /// /// E_POINTER /// An invalid pointer was passed to the function. The value of ppSupportedOutputFormat does not change. /// /// /// Other HRESULT values /// These additional error conditions are tracked by the audio engine. /// /// /// /// /// There are differences in the implementation of the method by the different APOs. For example, with certain implementations, /// the output can only be of type float when the input format is of type integer. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-isoutputformatsupported // HRESULT IsOutputFormatSupported( IAudioMediaType *pOppositeFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType // **ppSupportedOutputFormat ); [PreserveSig] HRESULT IsOutputFormatSupported(IAudioMediaType pOppositeFormat, IAudioMediaType pRequestedOutputFormat, out IAudioMediaType ppSupportedOutputFormat); /// GetInputChannelCount returns the input channel count (samples-per-frame) for this APO. /// The input channel count. /// The input channel count that is returned refers to the input side of the APO. // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobject-getinputchannelcount // HRESULT GetInputChannelCount( UINT32 *pu32ChannelCount ); uint GetInputChannelCount(); } /// /// The interface is used to configure the APO. This interface uses its methods to lock and unlock the APO for processing. /// The interface supports the following methods: /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudioprocessingobjectconfiguration [PInvokeData("audioenginebaseapo.h", MSDNShortId = "6311a5d1-b9d3-4c62-99aa-8feda32b4a2f")] [ComImport, Guid("0E5ED805-ABA6-49c3-8F9A-2B8C889C4FA8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioProcessingObjectConfiguration { /// The method is used to verify that the APO is locked and ready to process data. /// Number of input connections that are attached to this APO. /// Connection descriptor for each input connection that is attached to this APO. /// Number of output connections that are attached to this APO. /// Connection descriptor for each output connection that is attached to this APO. /// /// When the method is called, it first performs an internal check to see if the APO has been initialized and is ready to /// process data. Each APO has different initialization requirements so each APO must define its own Initialize method if needed. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobjectconfiguration-lockforprocess // HRESULT LockForProcess( UINT32 u32NumInputConnections, APO_CONNECTION_DESCRIPTOR **ppInputConnections, UINT32 // u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR **ppOutputConnections ); void LockForProcess([In] uint u32NumInputConnections, [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStruct, SizeParamIndex = 0)] APO_CONNECTION_DESCRIPTOR[] ppInputConnections, [In] uint u32NumOutputConnections, [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStruct, SizeParamIndex = 2)] APO_CONNECTION_DESCRIPTOR[] ppOutputConnections); /// The method releases the lock that was imposed on the APO by the LockForProcess method. /// /// The method places the APO in a mode that makes configuration changes possible. These changes include Add, Remove, and Swap /// of the input and output connections that are attached to the APO. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobjectconfiguration-unlockforprocess // HRESULT UnlockForProcess(); void UnlockForProcess(); } /// /// /// This interface can operate in real-time mode and its methods can be called form real-time processing threads. The implementation /// of the methods for this interface must not block or touch paged memory. Additionally, you must not call any blocking system /// routines in the implementation of the methods. /// /// The interface includes the following methods: /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudioprocessingobjectrt [PInvokeData("audioenginebaseapo.h", MSDNShortId = "640ac817-16f2-47c8-87e9-1ae0136e6e55")] [ComImport, Guid("9E1D6A6D-DDBC-4E95-A4C7-AD64BA37846C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioProcessingObjectRT { /// The APOProcess method causes the APO to make a processing pass. /// The number of input connections that are attached to this APO. /// An array of input connection property structures. There is one structure per input connection. /// The number of output connections that are attached to this APO. /// /// An array of output connection property structures. There is one structure per output connection. /// /// /// None /// /// /// Return code /// Description /// /// /// /// /// /// The method must not change the data in the ppOutputConnections array. But it must set the properties of the output /// connections after processing. /// /// /// The method is called from a real-time processing thread. The implementation of this method must not touch paged memory and /// it should not call any system blocking routines. /// /// /// For a detailed look at an implementation of this method, see the Swap sample code and refer to the Swapapolfx.cpp file. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobjectrt-apoprocess // void APOProcess( UINT32 u32NumInputConnections, APO_CONNECTION_PROPERTY **ppInputConnections, UINT32 u32NumOutputConnections, // APO_CONNECTION_PROPERTY **ppOutputConnections ); [PreserveSig] void APOProcess([In] uint u32NumInputConnections, [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStruct, SizeParamIndex = 0)] APO_CONNECTION_PROPERTY[] ppInputConnections, [In] uint u32NumOutputConnections, [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStruct, SizeParamIndex = 2)] APO_CONNECTION_PROPERTY[] ppOutputConnections); /// The method returns the number of input frames that an APO requires to generate a given number of output frames. /// This is a count of the number of output frames. /// /// The method returns the number of input frames that are required to generate the given number of output frames. /// /// /// Return code /// Description /// /// /// /// /// The method is called from a real-time processing thread. The implementation of this method must not touch paged memory and /// it should not call any system blocking routines. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobjectrt-calcinputframes // UINT32 CalcInputFrames( UINT32 u32OutputFrameCount ); [PreserveSig] uint CalcInputFrames(uint u32OutputFrameCount); /// The method returns the number of output frames that an APO requires for a given number of input frames. /// This is a count of the number of input frames. /// /// The method returns the number of output frames that an APO will generate for a given number of input frames. /// /// /// Return code /// Description /// /// /// /// /// The method can be called form a real-time processing thread. The implementation of this method must not block or touch paged /// memory and it should not call any system blocking routines. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudioprocessingobjectrt-calcoutputframes // UINT32 CalcOutputFrames( UINT32 u32InputFrameCount ); [PreserveSig] uint CalcOutputFrames([In] uint u32InputFrameCount); } /// /// /// The IAudioSystemEffects interface uses the basic methods that are inherited from IUnknown, and must implement an /// Initialize method. The parameters that are passed to this Initialize method must be passed directly to the /// IAudioProcessingObject::Initialize method. /// /// /// Refer to the IAudioProcessingObject::Initialize method for information about the structure and the parameters that are required /// to implement the IAudioSystemEffects::Initialize method. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudiosystemeffects [PInvokeData("audioenginebaseapo.h", MSDNShortId = "86429c51-6831-4266-9774-1547dc04bcb0")] [ComImport, Guid("5FA00F27-ADD6-499a-8A9D-6B98521FA75B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSystemEffects { } /// /// The IAudioSystemEffects2 interface was introduced with Windows 8.1 for retrieving information about the processing /// objects in a given mode. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudiosystemeffects2 [PInvokeData("audioenginebaseapo.h", MSDNShortId = "5989BAFB-6B2D-4186-9A8D-96C8974E0D18")] [ComImport, Guid("BAFE99D2-7436-44CE-9E0E-4D89AFBFFF56"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSystemEffects2 : IAudioSystemEffects { /// /// The GetEffectsList method is used for retrieving the list of audio processing effects that are currently active, and stores /// an event to be signaled if the list changes. /// /// /// Pointer to the list of GUIDs that represent audio processing effects. The caller is responsible for freeing this memory by /// calling CoTaskMemFree. /// /// A count of the audio processing effects in the list. /// The HANDLE of the event that will be signaled if the list changes. /// /// /// The APO signals the specified event when the list of audio processing effects changes from the list that was returned by /// GetEffectsList. The APO uses this event until either GetEffectsList is called again, or the APO is destroyed. /// The passed handle can be NULL, in which case the APO stops using any previous handle and does not signal an event. /// /// /// An APO implements this method to allow Windows to discover the current effects applied by the APO. The list of effects may /// depend on the processing mode that the APO initialized, and on any end user configuration. The processing mode is indicated /// by the AudioProcessingMode member of APOInitSystemEffects2. /// /// /// APOs should identify effects using GUIDs defined by Windows, such as AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION. An APO /// should only define and return a custom GUID in rare cases where the type of effect is clearly different from the ones /// defined by Windows. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudiosystemeffects2-geteffectslist // HRESULT GetEffectsList( LPGUID *ppEffectsIds, UINT *pcEffects, HANDLE Event ); void GetEffectsList(out SafeCoTaskMemHandle ppEffectsIds, out uint pcEffects, [In] IntPtr Event); } /// /// /// The interface is supported in Windows Vista and later versions of Windows. When you develop an audio processing object (APO) to /// drive an audio adapter with an atypical format, the APO must support the interface. /// /// /// The Windows operating system can instantiate your APO outside the audio engine and use the interface to retrieve information /// about the atypical format. The associated user interface displays the data that is retrieved. /// /// /// Important Although the interface continues to be supported in Windows, note that the type of APO to which you can apply /// this interface depends on the version of Windows you are targeting. The following table provides more information: /// /// /// /// Target OS /// Target APO type /// /// /// Windows Vista /// Global effects (GFX) /// /// /// Windows 7 /// Global effects (GFX) /// /// /// Windows 8 /// Global effects (GFX) /// /// /// Windows 8.1 /// Endpoint effects (EFX) /// /// /// The interface inherits from IUnknown and also supports the following methods: /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nn-audioenginebaseapo-iaudiosystemeffectscustomformats [PInvokeData("audioenginebaseapo.h", MSDNShortId = "29b758c0-5bbe-489c-9950-bc92a185fbaf")] [ComImport, Guid("B1176E34-BB7F-4f05-BEBD-1B18A534E097"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSystemEffectsCustomFormats { /// The method retrieves the number of custom formats supported by the system effects audio processing object (sAPO). /// /// Specifies a pointer to an unsigned integer. The unsigned integer represents the number of formats supported by the sAPO. /// /// For more information about sAPOs, see System Effects Audio Processing Objects. // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudiosystemeffectscustomformats-getformatcount // HRESULT GetFormatCount( UINT *pcFormats ); uint GetFormatCount(); /// The method retrieves an IAudioMediaType representation of a custom format. /// /// Specifies the index of a supported format. This parameter can be any value in the range from zero to one less than the /// return value of GetFormatCount. In other words, any value in the range from zero to GetFormatCount( ) - 1. /// /// /// Specifies a pointer to a pointer to an IAudioMediaType interface. It is the responsibility of the caller to release /// the IAudioMediaType interface to which the ppFormat parameter points. /// /// /// When the audio system calls the method, the sAPO creates an audio media type object and returns an IAudioMediaType /// interface. The sAPO implementation can use the CreateAudioMediaType utility function to create the audio media type object. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudiosystemeffectscustomformats-getformat // HRESULT GetFormat( UINT nFormat, IAudioMediaType **ppFormat ); IAudioMediaType GetFormat(uint nFormat); /// The method retrieves a string representation of the custom format so that it can be displayed on a user-interface. /// /// Specifies the index of a supported format. This parameter can be any value in the range from zero to one less than the /// return value of GetFormatCount. In other words, any value in the range from zero to GetFormatCount( ) - 1. /// /// /// Specifies the address of the buffer that receives a NULL-terminated Unicode string that describes the custom format. /// /// /// /// The method returns S_OK when the call is successful. Otherwise, it returns one of the error codes shown in the following table. /// /// /// /// Return code /// Description /// /// /// E_POINTER /// Invalid pointer passed to function /// /// /// E_OUTOFMEMORY /// Return buffer cannot be allocated /// /// /// E_INVALIDARG /// nFormat is out of range /// /// /// /// /// The sAPO uses CoTaskMemAlloc to allocate the returned string. The caller must use CoTaskMemFree to delete the buffer that is /// pointed to by the ppwstrFormatRep parameter. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/nf-audioenginebaseapo-iaudiosystemeffectscustomformats-getformatrepresentation // HRESULT GetFormatRepresentation( UINT nFormat, LPWSTR *ppwstrFormatRep ); void GetFormatRepresentation(uint nFormat, out SafeCoTaskMemString ppwstrFormatRep); } /// /// The GetEffectsList method is used for retrieving the list of audio processing effects that are currently active, and stores an /// event to be signaled if the list changes. /// /// The IAudioSystemEffects2 instance. /// The HANDLE of the event that will be signaled if the list changes. /// The list of GUIDs that represent audio processing effects. /// /// /// The APO signals the specified event when the list of audio processing effects changes from the list that was returned by /// GetEffectsList. The APO uses this event until either GetEffectsList is called again, or the APO is destroyed. The /// passed handle can be NULL, in which case the APO stops using any previous handle and does not signal an event. /// /// /// An APO implements this method to allow Windows to discover the current effects applied by the APO. The list of effects may /// depend on the processing mode that the APO initialized, and on any end user configuration. The processing mode is indicated by /// the AudioProcessingMode member of APOInitSystemEffects2. /// /// /// APOs should identify effects using GUIDs defined by Windows, such as AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION. An APO should /// only define and return a custom GUID in rare cases where the type of effect is clearly different from the ones defined by Windows. /// /// public static Guid[] GetEffectsList(this IAudioSystemEffects2 ase2, [In] IntPtr Event) { ase2.GetEffectsList(out var ids, out var i, Event); using (ids) return ids.ToArray((int)i); } /// The method retrieves a string representation of the custom format so that it can be displayed on a user-interface. /// The IAudioSystemEffectsCustomFormats instance. /// /// Specifies the index of a supported format. This parameter can be any value in the range from zero to one less than the return /// value of GetFormatCount. In other words, any value in the range from zero to GetFormatCount( ) - 1. /// /// A string that describes the custom format. public static string GetFormatRepresentation(this IAudioSystemEffectsCustomFormats fmts, uint nFormat) { fmts.GetFormatRepresentation(nFormat, out var rep); using (rep) return (string)rep; } /// The APO_CONNECTION_DESCRIPTOR structure stores the description of an APO connection buffer. /// The Terminal Services AudioEndpoint API is for use in Remote Desktop scenarios; it is not for client applications. [PInvokeData("Audioenginebaseapo.h")] [StructLayout(LayoutKind.Sequential)] public struct APO_CONNECTION_DESCRIPTOR { /// /// A value of the APO_CONNECTION_BUFFER_TYPE enumeration that indicates how the connection buffer inside the APO connection is /// allocated. This member is set only by the APO connection during initialization. It is a private member that should be /// cleared before creating the connection. /// public APO_CONNECTION_BUFFER_TYPE Type; /// /// A pointer to the buffer to be used for the APO connection. If this member is NULL, the audio engine allocates memory for the /// buffer and the Type member is set to APO_CONNECTION_BUFFER_TYPE_ALLOCATED. Otherwise, the audio engine uses the specified /// memory region as the connection buffer. The buffer to be used for the APO connection must be frame aligned or 128-bit /// aligned, both at the beginning of the buffer and at the start of the audio buffer section. The buffer to be used for the APO /// connection must be large enough to hold the number of frames indicated in u32MaxFrameCount. This member must point to the /// beginning of the audio buffer area. If the audio engine must use the memory pointed by this member, the Type member is set /// to APO_CONNECTION_BUFFER_TYPE_EXTERNAL. /// public IntPtr pBuffer; /// /// The maximum number of frames that the connection buffer can hold. The actual space allocated depends on the exact format of /// the audio data specified by the pFormat member. /// public uint u32MaxFrameCount; /// /// A pointer to the audio media object that specifies the format of the connection. This also represents the format of the data /// in the connection buffer. /// public IntPtr pFormat; /// A tag that identifies a valid APO_CONNECTION_DESCRIPTOR structure. A valid structure is marked as APO_CONNECTION_DESCRIPTOR_SIGNATURE. public uint u32Signature; } /// /// The APO_REG_PROPERTIES structure is used by IAudioProcessingObject::GetRegistrationProperties for returning the registration /// properties of an audio processing object (APO). /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ns-audioenginebaseapo-apo_reg_properties typedef struct // APO_REG_PROPERTIES { CLSID clsid; APO_FLAG Flags; WCHAR szFriendlyName[256]; WCHAR szCopyrightInfo[256]; UINT32 u32MajorVersion; // UINT32 u32MinorVersion; UINT32 u32MinInputConnections; UINT32 u32MaxInputConnections; UINT32 u32MinOutputConnections; UINT32 // u32MaxOutputConnections; UINT32 u32MaxInstances; UINT32 u32NumAPOInterfaces; IID iidAPOInterfaceList[1]; } APO_REG_PROPERTIES, *PAPO_REG_PROPERTIES; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "466215E5-5345-4570-A29B-086562882F5D")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct APO_REG_PROPERTIES { /// The class ID for this APO. public Guid clsid; /// The flags for this APO. This parameter is an enumerated constant of type APO_FLAG. public APO_FLAG Flags; /// The friendly name of this APO. This is a string of characters with a max length of 256. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szFriendlyName; /// The copyright info for this APO. This is a string of characters with a max length of 256. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szCopyrightInfo; /// The major version number for this APO. public uint u32MajorVersion; /// The minor version number for this APO. public uint u32MinorVersion; /// The minimum number of input connections for this APO. public uint u32MinInputConnections; /// The maximum number of input connections for this APO. public uint u32MaxInputConnections; /// The minimum number of output connections for this APO. public uint u32MinOutputConnections; /// The maximum number of output connections for this APO. public uint u32MaxOutputConnections; /// The maximum number of instances of this APO. public uint u32MaxInstances; /// The number of interfaces for this APO. public uint u32NumAPOInterfaces; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public Guid[] iidAPOInterfaceList; } /// /// The APOInitBaseStruct structure is the base initialization header that must precede other initialization data in IAudioProcessingObject::Initialize. /// /// /// If the specified CLSID does not match, then the APOInitBaseStruct structure was not designed for this APO, and this is an error /// condition. And if the CLSID of the APO changes between versions, then the CLSID may also be used for version management. In the /// case where the CLSID is used for version management, a previous version may still be supported by the APO. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ns-audioenginebaseapo-apoinitbasestruct typedef struct // APOInitBaseStruct { UINT32 cbSize; CLSID clsid; } APOInitBaseStruct; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "15C973AE-B0E8-42FD-9F34-671A6A915B47")] [StructLayout(LayoutKind.Sequential)] public struct APOInitBaseStruct { /// The total size of the structure in bytes. public uint cbSize; /// The Class ID (CLSID) of the APO. public Guid clsid; } /// The APOInitSystemEffects structure gets passed to the system effects APO for initialization. // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ns-audioenginebaseapo-apoinitsystemeffects typedef struct // APOInitSystemEffects { APOInitBaseStruct APOInit; IPropertyStore *pAPOEndpointProperties; IPropertyStore // *pAPOSystemEffectsProperties; void *pReserved; IMMDeviceCollection *pDeviceCollection; } APOInitSystemEffects; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "E33B1F94-4E3A-4EC1-AFB5-FD803FA391BC")] [StructLayout(LayoutKind.Sequential)] public struct APOInitSystemEffects { /// An APOInitBaseStruct structure. public APOInitBaseStruct APOInit; /// A pointer to an IPropertyStore object. public IPropertyStore pAPOEndpointProperties; /// A pointer to an IPropertyStore object. public IPropertyStore pAPOSystemEffectsProperties; /// Reserved for future use. public IntPtr pReserved; /// A pointer to an IMMDeviceCollection object. public IMMDeviceCollection pDeviceCollection; } /// /// The APOInitSystemEffects2 structure was introduced with Windows 8.1, to make it possible to provide additional initialization /// context to the audio processing object (APO) for initialization. /// // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ns-audioenginebaseapo-apoinitsystemeffects2 typedef struct // APOInitSystemEffects2 { APOInitBaseStruct APOInit; IPropertyStore *pAPOEndpointProperties; IPropertyStore // *pAPOSystemEffectsProperties; void *pReserved; IMMDeviceCollection *pDeviceCollection; UINT nSoftwareIoDeviceInCollection; UINT // nSoftwareIoConnectorIndex; GUID AudioProcessingMode; BOOL InitializeForDiscoveryOnly; } APOInitSystemEffects2; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "87E59FCE-1965-4B23-B1F5-F54FEDD5A83E")] [StructLayout(LayoutKind.Sequential)] public struct APOInitSystemEffects2 { /// An APOInitBaseStruct structure. public APOInitBaseStruct APOInit; /// A pointer to an IPropertyStore object. public IPropertyStore pAPOEndpointProperties; /// A pointer to an IPropertyStore object. public IPropertyStore pAPOSystemEffectsProperties; /// Reserved for future use. public IntPtr pReserved; /// A pointer to an IMMDeviceCollection object. public IMMDeviceCollection pDeviceCollection; /// /// Specifies the MMDevice that implements the DeviceTopology that includes the software connector for which the APO is /// initializing. The MMDevice is contained in pDeviceCollection. /// public uint nSoftwareIoDeviceInCollection; /// Specifies the index of a Software_IO connector in the DeviceTopology. public uint nSoftwareIoConnectorIndex; /// Specifies the processing mode for the audio graph. public Guid AudioProcessingMode; /// Indicates whether the audio system is initializing the APO for effects discovery only. [MarshalAs(UnmanagedType.Bool)] public bool InitializeForDiscoveryOnly; } /// The AudioFXExtensionParams structure is passed to the system effects ControlPanel Extension PropertyPage via IShellPropSheetExt::AddPages. // https://docs.microsoft.com/en-us/windows/win32/api/audioenginebaseapo/ns-audioenginebaseapo-audiofxextensionparams typedef struct // __MIDL___MIDL_itf_audioenginebaseapo_0000_0008_0001 { LPARAM AddPageParam; LPWSTR pwstrEndpointID; IPropertyStore *pFxProperties; // } AudioFXExtensionParams; [PInvokeData("audioenginebaseapo.h", MSDNShortId = "832F1190-ED3E-4059-AB45-18C23D98663B")] [StructLayout(LayoutKind.Sequential)] public struct AudioFXExtensionParams { /// Parameters for the Property Page extension. public IntPtr AddPageParam; /// The ID for the audio endpoint. [MarshalAs(UnmanagedType.LPWStr)] public string pwstrEndpointID; /// An IPropertyStore object. public IPropertyStore pFxProperties; } } }