using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; using NAudio.Dmo; using NAudio.Dmo.Effect; using NAudio.MediaFoundation; using NAudio.Utils; using NAudio.Wasapi.CoreAudioApi; using NAudio.Wasapi.CoreAudioApi.Interfaces; using NAudio.Wave; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mark Heath")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2026")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+c89fee940ee6f8d7374d18714a6b85d8b7a18ab0")] [assembly: AssemblyProduct("NAudio.Wasapi")] [assembly: AssemblyTitle("NAudio.Wasapi")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace NAudio.MediaFoundation { public static class AudioSubtypes { [FieldDescription("AAC")] public static readonly Guid MFAudioFormat_AAC = new Guid("00001610-0000-0010-8000-00aa00389b71"); [FieldDescription("ADTS")] public static readonly Guid MFAudioFormat_ADTS = new Guid("00001600-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby AC3 SPDIF")] public static readonly Guid MFAudioFormat_Dolby_AC3_SPDIF = new Guid("00000092-0000-0010-8000-00aa00389b71"); [FieldDescription("DRM")] public static readonly Guid MFAudioFormat_DRM = new Guid("00000009-0000-0010-8000-00aa00389b71"); [FieldDescription("DTS")] public static readonly Guid MFAudioFormat_DTS = new Guid("00000008-0000-0010-8000-00aa00389b71"); [FieldDescription("IEEE floating-point")] public static readonly Guid MFAudioFormat_Float = new Guid("00000003-0000-0010-8000-00aa00389b71"); [FieldDescription("MP3")] public static readonly Guid MFAudioFormat_MP3 = new Guid("00000055-0000-0010-8000-00aa00389b71"); [FieldDescription("MPEG")] public static readonly Guid MFAudioFormat_MPEG = new Guid("00000050-0000-0010-8000-00aa00389b71"); [FieldDescription("WMA 9 Voice codec")] public static readonly Guid MFAudioFormat_MSP1 = new Guid("0000000a-0000-0010-8000-00aa00389b71"); [FieldDescription("PCM")] public static readonly Guid MFAudioFormat_PCM = new Guid("00000001-0000-0010-8000-00aa00389b71"); [FieldDescription("WMA SPDIF")] public static readonly Guid MFAudioFormat_WMASPDIF = new Guid("00000164-0000-0010-8000-00aa00389b71"); [FieldDescription("WMAudio Lossless")] public static readonly Guid MFAudioFormat_WMAudio_Lossless = new Guid("00000163-0000-0010-8000-00aa00389b71"); [FieldDescription("Windows Media Audio")] public static readonly Guid MFAudioFormat_WMAudioV8 = new Guid("00000161-0000-0010-8000-00aa00389b71"); [FieldDescription("Windows Media Audio Professional")] public static readonly Guid MFAudioFormat_WMAudioV9 = new Guid("00000162-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby AC3")] public static readonly Guid MFAudioFormat_Dolby_AC3 = new Guid("e06d802c-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid MFAudioFormat_FLAC = new Guid("0000f1ac-0000-0010-8000-00aa00389b71"); public static readonly Guid MFAudioFormat_ALAC = new Guid("63616c61-0000-0010-8000-00aa00389b71"); [FieldDescription("MPEG-4 and AAC Audio Types")] public static readonly Guid MEDIASUBTYPE_RAW_AAC1 = new Guid("000000ff-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Audio Types")] public static readonly Guid MEDIASUBTYPE_DVM = new Guid("00002000-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Audio Types")] public static readonly Guid MEDIASUBTYPE_DOLBY_DDPLUS = new Guid("a7fb87af-2d02-42fb-a4d4-05cd93843bdd"); [FieldDescription("μ-law")] public static readonly Guid KSDATAFORMAT_SUBTYPE_MULAW = new Guid("00000007-0000-0010-8000-00aa00389b71"); [FieldDescription("ADPCM")] public static readonly Guid KSDATAFORMAT_SUBTYPE_ADPCM = new Guid("00000002-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Digital Plus for HDMI")] public static readonly Guid KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS = new Guid("0000000a-0cea-0010-8000-00aa00389b71"); [FieldDescription("MSAudio1")] public static readonly Guid MEDIASUBTYPE_MSAUDIO1 = new Guid("00000160-0000-0010-8000-00aa00389b71"); [FieldDescription("IMA ADPCM")] public static readonly Guid ImaAdpcm = new Guid("00000011-0000-0010-8000-00aa00389b71"); [FieldDescription("WMSP2")] public static readonly Guid WMMEDIASUBTYPE_WMSP2 = new Guid("0000000b-0000-0010-8000-00aa00389b71"); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("7FEE9E9A-4A89-47a6-899C-B6A53A70FB67")] public interface IMFActivate : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void ActivateObject([In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv); void ShutdownObject(); void DetachObject(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("2CD2D921-C447-44A7-A13C-4ADABFC247E3")] public interface IMFAttributes { void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value); void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); void DeleteAllItems(); void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); void LockStore(); void UnlockStore(); void GetCount(out int pcItems); void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("ad4c1b00-4bf7-422f-9175-756693d9130d")] public interface IMFByteStream { void GetCapabilities(ref int pdwCapabiities); void GetLength(ref long pqwLength); void SetLength(long qwLength); void GetCurrentPosition(ref long pqwPosition); void SetCurrentPosition(long qwPosition); void IsEndOfStream([MarshalAs(UnmanagedType.Bool)] ref bool pfEndOfStream); void Read(IntPtr pb, int cb, ref int pcbRead); void BeginRead(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); void EndRead(IntPtr pResult, ref int pcbRead); void Write(IntPtr pb, int cb, ref int pcbWritten); void BeginWrite(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); void EndWrite(IntPtr pResult, ref int pcbWritten); void Seek(int SeekOrigin, long llSeekOffset, int dwSeekFlags, ref long pqwCurrentPosition); void Flush(); void Close(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("5BC8A76B-869A-46A3-9B03-FA218A66AEBE")] public interface IMFCollection { void GetElementCount(out int pcElements); void GetElement([In] int dwElementIndex, [MarshalAs(UnmanagedType.IUnknown)] out object ppUnkElement); void AddElement([In][MarshalAs(UnmanagedType.IUnknown)] object pUnkElement); void RemoveElement([In] int dwElementIndex, [MarshalAs(UnmanagedType.IUnknown)] out object ppUnkElement); void InsertElementAt([In] int dwIndex, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); void RemoveAllElements(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("045FA593-8799-42b8-BC8D-8968C6453507")] public interface IMFMediaBuffer { void Lock(out IntPtr ppbBuffer, out int pcbMaxLength, out int pcbCurrentLength); void Unlock(); void GetCurrentLength(out int pcbCurrentLength); void SetCurrentLength(int cbCurrentLength); void GetMaxLength(out int pcbMaxLength); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("DF598932-F10C-4E39-BBA2-C308F101DAA3")] public interface IMFMediaEvent : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetType(out MediaEventType pmet); void GetExtendedType(out Guid pguidExtendedType); void GetStatus([MarshalAs(UnmanagedType.Error)] out int phrStatus); void GetValue([Out] IntPtr pvValue); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("44AE0FA8-EA31-4109-8D2E-4CAE4997C555")] public interface IMFMediaType : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetMajorType(out Guid pguidMajorType); void IsCompressedFormat([MarshalAs(UnmanagedType.Bool)] out bool pfCompressed); [PreserveSig] int IsEqual([In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pIMediaType, ref int pdwFlags); void GetRepresentation([In] Guid guidRepresentation, ref IntPtr ppvRepresentation); void FreeRepresentation([In] Guid guidRepresentation, [In] IntPtr pvRepresentation); } [ComImport] [Guid("E7FE2E12-661C-40DA-92F9-4F002AB67627")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMFReadWriteClassFactory { void CreateInstanceFromURL([In][MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In][MarshalAs(UnmanagedType.LPWStr)] string pwszURL, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pAttributes, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); void CreateInstanceFromObject([In][MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In][MarshalAs(UnmanagedType.IUnknown)] object punkObject, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pAttributes, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); } [ComImport] [Guid("48e2ed0f-98c2-4a37-bed5-166312ddd83f")] public class MFReadWriteClassFactory { } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("c40a00f2-b93a-4d80-ae8c-5a1c634f58e4")] public interface IMFSample : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetSampleFlags(out int pdwSampleFlags); void SetSampleFlags(int dwSampleFlags); void GetSampleTime(out long phnsSampletime); void SetSampleTime(long hnsSampleTime); void GetSampleDuration(out long phnsSampleDuration); void SetSampleDuration(long hnsSampleDuration); void GetBufferCount(out int pdwBufferCount); void GetBufferByIndex(int dwIndex, out IMFMediaBuffer ppBuffer); void ConvertToContiguousBuffer(out IMFMediaBuffer ppBuffer); void AddBuffer(IMFMediaBuffer pBuffer); void RemoveBufferByIndex(int dwIndex); void RemoveAllBuffers(); void GetTotalLength(out int pcbTotalLength); void CopyToBuffer(IMFMediaBuffer pBuffer); } [ComImport] [Guid("3137f1cd-fe5e-4805-a5d8-fb477448cb3d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMFSinkWriter { void AddStream([In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pTargetMediaType, out int pdwStreamIndex); void SetInputMediaType([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pInputMediaType, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pEncodingParameters); void BeginWriting(); void WriteSample([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Interface)] IMFSample pSample); void SendStreamTick([In] int dwStreamIndex, [In] long llTimestamp); void PlaceMarker([In] int dwStreamIndex, [In] IntPtr pvContext); void NotifyEndOfSegment([In] int dwStreamIndex); void Flush([In] int dwStreamIndex); void DoFinalize(); void GetServiceForStream([In] int dwStreamIndex, [In] ref Guid guidService, [In] ref Guid riid, out IntPtr ppvObject); void GetStatistics([In] int dwStreamIndex, [In][Out] MF_SINK_WRITER_STATISTICS pStats); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("70ae66f2-c809-4e4f-8915-bdcb406b7993")] public interface IMFSourceReader { void GetStreamSelection([In] int dwStreamIndex, [MarshalAs(UnmanagedType.Bool)] out bool pSelected); void SetStreamSelection([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Bool)] bool pSelected); void GetNativeMediaType([In] int dwStreamIndex, [In] int dwMediaTypeIndex, out IMFMediaType ppMediaType); void GetCurrentMediaType([In] int dwStreamIndex, out IMFMediaType ppMediaType); void SetCurrentMediaType([In] int dwStreamIndex, IntPtr pdwReserved, [In] IMFMediaType pMediaType); void SetCurrentPosition([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidTimeFormat, [In] IntPtr varPosition); void ReadSample([In] int dwStreamIndex, [In] int dwControlFlags, out int pdwActualStreamIndex, out MF_SOURCE_READER_FLAG pdwStreamFlags, out ulong pllTimestamp, out IMFSample ppSample); void Flush([In] int dwStreamIndex); void GetServiceForStream([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppvObject); [PreserveSig] int GetPresentationAttribute([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidAttribute, [Out] IntPtr pvarAttribute); } [Flags] public enum MF_SOURCE_READER_FLAG { None = 0, MF_SOURCE_READERF_ERROR = 1, MF_SOURCE_READERF_ENDOFSTREAM = 2, MF_SOURCE_READERF_NEWSTREAM = 4, MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED = 0x10, MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED = 0x20, MF_SOURCE_READERF_STREAMTICK = 0x100, MF_SOURCE_READERF_ALLEFFECTSREMOVED = 0x200 } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("bf94c121-5b05-4e6f-8000-ba598961414d")] public interface IMFTransform { void GetStreamLimits(out int pdwInputMinimum, out int pdwInputMaximum, out int pdwOutputMinimum, out int pdwOutputMaximum); void GetStreamCount(out int pcInputStreams, out int pcOutputStreams); void GetStreamIds([In] int dwInputIdArraySize, [In][Out] IntPtr pdwInputIDs, [In] int dwOutputIdArraySize, [In][Out] IntPtr pdwOutputIDs); void GetInputStreamInfo([In] int dwInputStreamId, out MFT_INPUT_STREAM_INFO pStreamInfo); void GetOutputStreamInfo([In] int dwOutputStreamId, out MFT_OUTPUT_STREAM_INFO pStreamInfo); void GetAttributes(out IMFAttributes pAttributes); void GetInputStreamAttributes([In] int dwInputStreamId, out IMFAttributes pAttributes); void GetOutputStreamAttributes([In] int dwOutputStreamId, out IMFAttributes pAttributes); void DeleteInputStream([In] int dwOutputStreamId); void AddInputStreams([In] int cStreams, [In] IntPtr adwStreamIDs); void GetInputAvailableType([In] int dwInputStreamId, [In] int dwTypeIndex, out IMFMediaType ppType); void GetOutputAvailableType([In] int dwOutputStreamId, [In] int dwTypeIndex, out IMFMediaType ppType); void SetInputType([In] int dwInputStreamId, [In] IMFMediaType pType, [In] _MFT_SET_TYPE_FLAGS dwFlags); void SetOutputType([In] int dwOutputStreamId, [In] IMFMediaType pType, [In] _MFT_SET_TYPE_FLAGS dwFlags); void GetInputCurrentType([In] int dwInputStreamId, out IMFMediaType ppType); void GetOutputCurrentType([In] int dwOutputStreamId, out IMFMediaType ppType); void GetInputStatus([In] int dwInputStreamId, out _MFT_INPUT_STATUS_FLAGS pdwFlags); void GetOutputStatus([In] int dwInputStreamId, out _MFT_OUTPUT_STATUS_FLAGS pdwFlags); void SetOutputBounds([In] long hnsLowerBound, [In] long hnsUpperBound); void ProcessEvent([In] int dwInputStreamId, [In] IMFMediaEvent pEvent); void ProcessMessage([In] MFT_MESSAGE_TYPE eMessage, [In] IntPtr ulParam); void ProcessInput([In] int dwInputStreamId, [In] IMFSample pSample, int dwFlags); [PreserveSig] int ProcessOutput([In] _MFT_PROCESS_OUTPUT_FLAGS dwFlags, [In] int cOutputBufferCount, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] MFT_OUTPUT_DATA_BUFFER[] pOutputSamples, out _MFT_PROCESS_OUTPUT_STATUS pdwStatus); } public enum MediaEventType { MEUnknown = 0, MEError = 1, MEExtendedType = 2, MENonFatalError = 3, MESessionUnknown = 100, MESessionTopologySet = 101, MESessionTopologiesCleared = 102, MESessionStarted = 103, MESessionPaused = 104, MESessionStopped = 105, MESessionClosed = 106, MESessionEnded = 107, MESessionRateChanged = 108, MESessionScrubSampleComplete = 109, MESessionCapabilitiesChanged = 110, MESessionTopologyStatus = 111, MESessionNotifyPresentationTime = 112, MENewPresentation = 113, MELicenseAcquisitionStart = 114, MELicenseAcquisitionCompleted = 115, MEIndividualizationStart = 116, MEIndividualizationCompleted = 117, MEEnablerProgress = 118, MEEnablerCompleted = 119, MEPolicyError = 120, MEPolicyReport = 121, MEBufferingStarted = 122, MEBufferingStopped = 123, MEConnectStart = 124, MEConnectEnd = 125, MEReconnectStart = 126, MEReconnectEnd = 127, MERendererEvent = 128, MESessionStreamSinkFormatChanged = 129, MESourceUnknown = 200, MESourceStarted = 201, MEStreamStarted = 202, MESourceSeeked = 203, MEStreamSeeked = 204, MENewStream = 205, MEUpdatedStream = 206, MESourceStopped = 207, MEStreamStopped = 208, MESourcePaused = 209, MEStreamPaused = 210, MEEndOfPresentation = 211, MEEndOfStream = 212, MEMediaSample = 213, MEStreamTick = 214, MEStreamThinMode = 215, MEStreamFormatChanged = 216, MESourceRateChanged = 217, MEEndOfPresentationSegment = 218, MESourceCharacteristicsChanged = 219, MESourceRateChangeRequested = 220, MESourceMetadataChanged = 221, MESequencerSourceTopologyUpdated = 222, MESinkUnknown = 300, MEStreamSinkStarted = 301, MEStreamSinkStopped = 302, MEStreamSinkPaused = 303, MEStreamSinkRateChanged = 304, MEStreamSinkRequestSample = 305, MEStreamSinkMarker = 306, MEStreamSinkPrerolled = 307, MEStreamSinkScrubSampleComplete = 308, MEStreamSinkFormatChanged = 309, MEStreamSinkDeviceChanged = 310, MEQualityNotify = 311, MESinkInvalidated = 312, MEAudioSessionNameChanged = 313, MEAudioSessionVolumeChanged = 314, MEAudioSessionDeviceRemoved = 315, MEAudioSessionServerShutdown = 316, MEAudioSessionGroupingParamChanged = 317, MEAudioSessionIconChanged = 318, MEAudioSessionFormatChanged = 319, MEAudioSessionDisconnected = 320, MEAudioSessionExclusiveModeOverride = 321, METrustUnknown = 400, MEPolicyChanged = 401, MEContentProtectionMessage = 402, MEPolicySet = 403, MEWMDRMLicenseBackupCompleted = 500, MEWMDRMLicenseBackupProgress = 501, MEWMDRMLicenseRestoreCompleted = 502, MEWMDRMLicenseRestoreProgress = 503, MEWMDRMLicenseAcquisitionCompleted = 506, MEWMDRMIndividualizationCompleted = 508, MEWMDRMIndividualizationProgress = 513, MEWMDRMProximityCompleted = 514, MEWMDRMLicenseStoreCleaned = 515, MEWMDRMRevocationDownloadCompleted = 516, METransformUnknown = 600, METransformNeedInput = 601, METransformHaveOutput = 602, METransformDrainComplete = 603, METransformMarker = 604 } public static class MediaFoundationAttributes { public static readonly Guid MF_TRANSFORM_ASYNC = new Guid("f81a699a-649a-497d-8c73-29f8fed6ad7a"); public static readonly Guid MF_TRANSFORM_ASYNC_UNLOCK = new Guid("e5666d6b-3422-4eb6-a421-da7db1f8e207"); [FieldDescription("Transform Flags")] public static readonly Guid MF_TRANSFORM_FLAGS_Attribute = new Guid("9359bb7e-6275-46c4-a025-1c01e45f1a86"); [FieldDescription("Transform Category")] public static readonly Guid MF_TRANSFORM_CATEGORY_Attribute = new Guid("ceabba49-506d-4757-a6ff-66c184987e4e"); [FieldDescription("Class identifier")] public static readonly Guid MFT_TRANSFORM_CLSID_Attribute = new Guid("6821c42b-65a4-4e82-99bc-9a88205ecd0c"); [FieldDescription("Container type")] public static readonly Guid MF_TRANSCODE_CONTAINERTYPE = new Guid(353366591, 19132, 18315, 172, 79, 225, 145, 111, 186, 28, 202); [FieldDescription("Input Types")] public static readonly Guid MFT_INPUT_TYPES_Attributes = new Guid("4276c9b1-759d-4bf3-9cd0-0d723d138f96"); [FieldDescription("Output Types")] public static readonly Guid MFT_OUTPUT_TYPES_Attributes = new Guid("8eae8cf3-a44f-4306-ba5c-bf5dda242818"); public static readonly Guid MFT_ENUM_HARDWARE_URL_Attribute = new Guid("2fb866ac-b078-4942-ab6c-003d05cda674"); [FieldDescription("Name")] public static readonly Guid MFT_FRIENDLY_NAME_Attribute = new Guid("314ffbae-5b41-4c95-9c19-4e7d586face3"); public static readonly Guid MFT_CONNECTED_STREAM_ATTRIBUTE = new Guid("71eeb820-a59f-4de2-bcec-38db1dd611a4"); public static readonly Guid MFT_CONNECTED_TO_HW_STREAM = new Guid("34e6e728-06d6-4491-a553-4795650db912"); [FieldDescription("Preferred Output Format")] public static readonly Guid MFT_PREFERRED_OUTPUTTYPE_Attribute = new Guid("7e700499-396a-49ee-b1b4-f628021e8c9d"); public static readonly Guid MFT_PROCESS_LOCAL_Attribute = new Guid("543186e4-4649-4e65-b588-4aa352aff379"); public static readonly Guid MFT_PREFERRED_ENCODER_PROFILE = new Guid("53004909-1ef5-46d7-a18e-5a75f8b5905f"); public static readonly Guid MFT_HW_TIMESTAMP_WITH_QPC_Attribute = new Guid("8d030fb8-cc43-4258-a22e-9210bef89be4"); public static readonly Guid MFT_FIELDOFUSE_UNLOCK_Attribute = new Guid("8ec2e9fd-9148-410d-831e-702439461a8e"); public static readonly Guid MFT_CODEC_MERIT_Attribute = new Guid("88a7cb15-7b07-4a34-9128-e64c6703c4d3"); public static readonly Guid MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE = new Guid("111ea8cd-b62a-4bdb-89f6-67ffcdc2458b"); [FieldDescription("PMP Host Context")] public static readonly Guid MF_PD_PMPHOST_CONTEXT = new Guid("6c990d31-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("App Context")] public static readonly Guid MF_PD_APP_CONTEXT = new Guid("6c990d32-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Duration")] public static readonly Guid MF_PD_DURATION = new Guid("6c990d33-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Total File Size")] public static readonly Guid MF_PD_TOTAL_FILE_SIZE = new Guid("6c990d34-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Audio encoding bitrate")] public static readonly Guid MF_PD_AUDIO_ENCODING_BITRATE = new Guid("6c990d35-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Video Encoding Bitrate")] public static readonly Guid MF_PD_VIDEO_ENCODING_BITRATE = new Guid("6c990d36-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("MIME Type")] public static readonly Guid MF_PD_MIME_TYPE = new Guid("6c990d37-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Last Modified Time")] public static readonly Guid MF_PD_LAST_MODIFIED_TIME = new Guid("6c990d38-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Element ID")] public static readonly Guid MF_PD_PLAYBACK_ELEMENT_ID = new Guid("6c990d39-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Preferred Language")] public static readonly Guid MF_PD_PREFERRED_LANGUAGE = new Guid("6c990d3a-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Playback boundary time")] public static readonly Guid MF_PD_PLAYBACK_BOUNDARY_TIME = new Guid("6c990d3b-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Audio is variable bitrate")] public static readonly Guid MF_PD_AUDIO_ISVARIABLEBITRATE = new Guid("33026ee0-e387-4582-ae0a-34a2ad3baa18"); [FieldDescription("Major Media Type")] public static readonly Guid MF_MT_MAJOR_TYPE = new Guid("48eba18e-f8c9-4687-bf11-0a74c9f96a8f"); [FieldDescription("Media Subtype")] public static readonly Guid MF_MT_SUBTYPE = new Guid("f7e34c9a-42e8-4714-b74b-cb29d72c35e5"); [FieldDescription("Audio block alignment")] public static readonly Guid MF_MT_AUDIO_BLOCK_ALIGNMENT = new Guid("322de230-9eeb-43bd-ab7a-ff412251541d"); [FieldDescription("Audio average bytes per second")] public static readonly Guid MF_MT_AUDIO_AVG_BYTES_PER_SECOND = new Guid("1aab75c8-cfef-451c-ab95-ac034b8e1731"); [FieldDescription("Audio number of channels")] public static readonly Guid MF_MT_AUDIO_NUM_CHANNELS = new Guid("37e48bf5-645e-4c5b-89de-ada9e29b696a"); [FieldDescription("Audio samples per second")] public static readonly Guid MF_MT_AUDIO_SAMPLES_PER_SECOND = new Guid("5faeeae7-0290-4c31-9e8a-c534f68d9dba"); [FieldDescription("Audio bits per sample")] public static readonly Guid MF_MT_AUDIO_BITS_PER_SAMPLE = new Guid("f2deb57f-40fa-4764-aa33-ed4f2d1ff669"); [FieldDescription("Enable Hardware Transforms")] public static readonly Guid MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS = new Guid("a634a91c-822b-41b9-a494-4de4643612b0"); [FieldDescription("Disable Sink Writer Throttling")] public static readonly Guid MF_SINK_WRITER_DISABLE_THROTTLING = new Guid("08b845d8-2b74-4afe-9d53-be16d2d5ae4f"); [FieldDescription("User data")] public static readonly Guid MF_MT_USER_DATA = new Guid("b6bc765f-4c3b-40a4-bd51-2535b66fe09d"); [FieldDescription("All samples independent")] public static readonly Guid MF_MT_ALL_SAMPLES_INDEPENDENT = new Guid("c9173739-5e56-461c-b713-46fb995cb95f"); [FieldDescription("Fixed size samples")] public static readonly Guid MF_MT_FIXED_SIZE_SAMPLES = new Guid("b8ebefaf-b718-4e04-b0a9-116775e3321b"); [FieldDescription("DirectShow Format Guid")] public static readonly Guid MF_MT_AM_FORMAT_TYPE = new Guid("73d1072d-1870-4174-a063-29ff4ff6c11e"); [FieldDescription("Preferred legacy format structure")] public static readonly Guid MF_MT_AUDIO_PREFER_WAVEFORMATEX = new Guid("a901aaba-e037-458a-bdf6-545be2074042"); [FieldDescription("Is Compressed")] public static readonly Guid MF_MT_COMPRESSED = new Guid("3afd0cee-18f2-4ba5-a110-8bea502e1f92"); [FieldDescription("Average bitrate")] public static readonly Guid MF_MT_AVG_BITRATE = new Guid("20332624-fb0d-4d9e-bd0d-cbf6786c102e"); [FieldDescription("AAC payload type")] public static readonly Guid MF_MT_AAC_PAYLOAD_TYPE = new Guid("bfbabe79-7434-4d1c-94f0-72a3b9e17188"); [FieldDescription("AAC Audio Profile Level Indication")] public static readonly Guid MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION = new Guid("7632f0e6-9538-4d61-acda-ea29c8c14456"); } public static class MediaFoundationErrors { public const int MF_E_PLATFORM_NOT_INITIALIZED = -1072875856; public const int MF_E_BUFFERTOOSMALL = -1072875855; public const int MF_E_INVALIDREQUEST = -1072875854; public const int MF_E_INVALIDSTREAMNUMBER = -1072875853; public const int MF_E_INVALIDMEDIATYPE = -1072875852; public const int MF_E_NOTACCEPTING = -1072875851; public const int MF_E_NOT_INITIALIZED = -1072875850; public const int MF_E_UNSUPPORTED_REPRESENTATION = -1072875849; public const int MF_E_NO_MORE_TYPES = -1072875847; public const int MF_E_UNSUPPORTED_SERVICE = -1072875846; public const int MF_E_UNEXPECTED = -1072875845; public const int MF_E_INVALIDNAME = -1072875844; public const int MF_E_INVALIDTYPE = -1072875843; public const int MF_E_INVALID_FILE_FORMAT = -1072875842; public const int MF_E_INVALIDINDEX = -1072875841; public const int MF_E_INVALID_TIMESTAMP = -1072875840; public const int MF_E_UNSUPPORTED_SCHEME = -1072875837; public const int MF_E_UNSUPPORTED_BYTESTREAM_TYPE = -1072875836; public const int MF_E_UNSUPPORTED_TIME_FORMAT = -1072875835; public const int MF_E_NO_SAMPLE_TIMESTAMP = -1072875832; public const int MF_E_NO_SAMPLE_DURATION = -1072875831; public const int MF_E_INVALID_STREAM_DATA = -1072875829; public const int MF_E_RT_UNAVAILABLE = -1072875825; public const int MF_E_UNSUPPORTED_RATE = -1072875824; public const int MF_E_THINNING_UNSUPPORTED = -1072875823; public const int MF_E_REVERSE_UNSUPPORTED = -1072875822; public const int MF_E_UNSUPPORTED_RATE_TRANSITION = -1072875821; public const int MF_E_RATE_CHANGE_PREEMPTED = -1072875820; public const int MF_E_NOT_FOUND = -1072875819; public const int MF_E_NOT_AVAILABLE = -1072875818; public const int MF_E_NO_CLOCK = -1072875817; public const int MF_S_MULTIPLE_BEGIN = 866008; public const int MF_E_MULTIPLE_BEGIN = -1072875815; public const int MF_E_MULTIPLE_SUBSCRIBERS = -1072875814; public const int MF_E_TIMER_ORPHANED = -1072875813; public const int MF_E_STATE_TRANSITION_PENDING = -1072875812; public const int MF_E_UNSUPPORTED_STATE_TRANSITION = -1072875811; public const int MF_E_UNRECOVERABLE_ERROR_OCCURRED = -1072875810; public const int MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS = -1072875809; public const int MF_E_SAMPLE_NOT_WRITABLE = -1072875808; public const int MF_E_INVALID_KEY = -1072875806; public const int MF_E_BAD_STARTUP_VERSION = -1072875805; public const int MF_E_UNSUPPORTED_CAPTION = -1072875804; public const int MF_E_INVALID_POSITION = -1072875803; public const int MF_E_ATTRIBUTENOTFOUND = -1072875802; public const int MF_E_PROPERTY_TYPE_NOT_ALLOWED = -1072875801; public const int MF_E_PROPERTY_TYPE_NOT_SUPPORTED = -1072875800; public const int MF_E_PROPERTY_EMPTY = -1072875799; public const int MF_E_PROPERTY_NOT_EMPTY = -1072875798; public const int MF_E_PROPERTY_VECTOR_NOT_ALLOWED = -1072875797; public const int MF_E_PROPERTY_VECTOR_REQUIRED = -1072875796; public const int MF_E_OPERATION_CANCELLED = -1072875795; public const int MF_E_BYTESTREAM_NOT_SEEKABLE = -1072875794; public const int MF_E_DISABLED_IN_SAFEMODE = -1072875793; public const int MF_E_CANNOT_PARSE_BYTESTREAM = -1072875792; public const int MF_E_SOURCERESOLVER_MUTUALLY_EXCLUSIVE_FLAGS = -1072875791; public const int MF_E_MEDIAPROC_WRONGSTATE = -1072875790; public const int MF_E_RT_THROUGHPUT_NOT_AVAILABLE = -1072875789; public const int MF_E_RT_TOO_MANY_CLASSES = -1072875788; public const int MF_E_RT_WOULDBLOCK = -1072875787; public const int MF_E_NO_BITPUMP = -1072875786; public const int MF_E_RT_OUTOFMEMORY = -1072875785; public const int MF_E_RT_WORKQUEUE_CLASS_NOT_SPECIFIED = -1072875784; public const int MF_E_INSUFFICIENT_BUFFER = -1072860816; public const int MF_E_CANNOT_CREATE_SINK = -1072875782; public const int MF_E_BYTESTREAM_UNKNOWN_LENGTH = -1072875781; public const int MF_E_SESSION_PAUSEWHILESTOPPED = -1072875780; public const int MF_S_ACTIVATE_REPLACED = 866045; public const int MF_E_FORMAT_CHANGE_NOT_SUPPORTED = -1072875778; public const int MF_E_INVALID_WORKQUEUE = -1072875777; public const int MF_E_DRM_UNSUPPORTED = -1072875776; public const int MF_E_UNAUTHORIZED = -1072875775; public const int MF_E_OUT_OF_RANGE = -1072875774; public const int MF_E_INVALID_CODEC_MERIT = -1072875773; public const int MF_E_HW_MFT_FAILED_START_STREAMING = -1072875772; public const int MF_S_ASF_PARSEINPROGRESS = 1074608792; public const int MF_E_ASF_PARSINGINCOMPLETE = -1072874856; public const int MF_E_ASF_MISSINGDATA = -1072874855; public const int MF_E_ASF_INVALIDDATA = -1072874854; public const int MF_E_ASF_OPAQUEPACKET = -1072874853; public const int MF_E_ASF_NOINDEX = -1072874852; public const int MF_E_ASF_OUTOFRANGE = -1072874851; public const int MF_E_ASF_INDEXNOTLOADED = -1072874850; public const int MF_E_ASF_TOO_MANY_PAYLOADS = -1072874849; public const int MF_E_ASF_UNSUPPORTED_STREAM_TYPE = -1072874848; public const int MF_E_ASF_DROPPED_PACKET = -1072874847; public const int MF_E_NO_EVENTS_AVAILABLE = -1072873856; public const int MF_E_INVALID_STATE_TRANSITION = -1072873854; public const int MF_E_END_OF_STREAM = -1072873852; public const int MF_E_SHUTDOWN = -1072873851; public const int MF_E_MP3_NOTFOUND = -1072873850; public const int MF_E_MP3_OUTOFDATA = -1072873849; public const int MF_E_MP3_NOTMP3 = -1072873848; public const int MF_E_MP3_NOTSUPPORTED = -1072873847; public const int MF_E_NO_DURATION = -1072873846; public const int MF_E_INVALID_FORMAT = -1072873844; public const int MF_E_PROPERTY_NOT_FOUND = -1072873843; public const int MF_E_PROPERTY_READ_ONLY = -1072873842; public const int MF_E_PROPERTY_NOT_ALLOWED = -1072873841; public const int MF_E_MEDIA_SOURCE_NOT_STARTED = -1072873839; public const int MF_E_UNSUPPORTED_FORMAT = -1072873832; public const int MF_E_MP3_BAD_CRC = -1072873831; public const int MF_E_NOT_PROTECTED = -1072873830; public const int MF_E_MEDIA_SOURCE_WRONGSTATE = -1072873829; public const int MF_E_MEDIA_SOURCE_NO_STREAMS_SELECTED = -1072873828; public const int MF_E_CANNOT_FIND_KEYFRAME_SAMPLE = -1072873827; public const int MF_E_NETWORK_RESOURCE_FAILURE = -1072872856; public const int MF_E_NET_WRITE = -1072872855; public const int MF_E_NET_READ = -1072872854; public const int MF_E_NET_REQUIRE_NETWORK = -1072872853; public const int MF_E_NET_REQUIRE_ASYNC = -1072872852; public const int MF_E_NET_BWLEVEL_NOT_SUPPORTED = -1072872851; public const int MF_E_NET_STREAMGROUPS_NOT_SUPPORTED = -1072872850; public const int MF_E_NET_MANUALSS_NOT_SUPPORTED = -1072872849; public const int MF_E_NET_INVALID_PRESENTATION_DESCRIPTOR = -1072872848; public const int MF_E_NET_CACHESTREAM_NOT_FOUND = -1072872847; public const int MF_I_MANUAL_PROXY = 1074610802; public const int MF_E_NET_REQUIRE_INPUT = -1072872844; public const int MF_E_NET_REDIRECT = -1072872843; public const int MF_E_NET_REDIRECT_TO_PROXY = -1072872842; public const int MF_E_NET_TOO_MANY_REDIRECTS = -1072872841; public const int MF_E_NET_TIMEOUT = -1072872840; public const int MF_E_NET_CLIENT_CLOSE = -1072872839; public const int MF_E_NET_BAD_CONTROL_DATA = -1072872838; public const int MF_E_NET_INCOMPATIBLE_SERVER = -1072872837; public const int MF_E_NET_UNSAFE_URL = -1072872836; public const int MF_E_NET_CACHE_NO_DATA = -1072872835; public const int MF_E_NET_EOL = -1072872834; public const int MF_E_NET_BAD_REQUEST = -1072872833; public const int MF_E_NET_INTERNAL_SERVER_ERROR = -1072872832; public const int MF_E_NET_SESSION_NOT_FOUND = -1072872831; public const int MF_E_NET_NOCONNECTION = -1072872830; public const int MF_E_NET_CONNECTION_FAILURE = -1072872829; public const int MF_E_NET_INCOMPATIBLE_PUSHSERVER = -1072872828; public const int MF_E_NET_SERVER_ACCESSDENIED = -1072872827; public const int MF_E_NET_PROXY_ACCESSDENIED = -1072872826; public const int MF_E_NET_CANNOTCONNECT = -1072872825; public const int MF_E_NET_INVALID_PUSH_TEMPLATE = -1072872824; public const int MF_E_NET_INVALID_PUSH_PUBLISHING_POINT = -1072872823; public const int MF_E_NET_BUSY = -1072872822; public const int MF_E_NET_RESOURCE_GONE = -1072872821; public const int MF_E_NET_ERROR_FROM_PROXY = -1072872820; public const int MF_E_NET_PROXY_TIMEOUT = -1072872819; public const int MF_E_NET_SERVER_UNAVAILABLE = -1072872818; public const int MF_E_NET_TOO_MUCH_DATA = -1072872817; public const int MF_E_NET_SESSION_INVALID = -1072872816; public const int MF_E_OFFLINE_MODE = -1072872815; public const int MF_E_NET_UDP_BLOCKED = -1072872814; public const int MF_E_NET_UNSUPPORTED_CONFIGURATION = -1072872813; public const int MF_E_NET_PROTOCOL_DISABLED = -1072872812; public const int MF_E_ALREADY_INITIALIZED = -1072871856; public const int MF_E_BANDWIDTH_OVERRUN = -1072871855; public const int MF_E_LATE_SAMPLE = -1072871854; public const int MF_E_FLUSH_NEEDED = -1072871853; public const int MF_E_INVALID_PROFILE = -1072871852; public const int MF_E_INDEX_NOT_COMMITTED = -1072871851; public const int MF_E_NO_INDEX = -1072871850; public const int MF_E_CANNOT_INDEX_IN_PLACE = -1072871849; public const int MF_E_MISSING_ASF_LEAKYBUCKET = -1072871848; public const int MF_E_INVALID_ASF_STREAMID = -1072871847; public const int MF_E_STREAMSINK_REMOVED = -1072870856; public const int MF_E_STREAMSINKS_OUT_OF_SYNC = -1072870854; public const int MF_E_STREAMSINKS_FIXED = -1072870853; public const int MF_E_STREAMSINK_EXISTS = -1072870852; public const int MF_E_SAMPLEALLOCATOR_CANCELED = -1072870851; public const int MF_E_SAMPLEALLOCATOR_EMPTY = -1072870850; public const int MF_E_SINK_ALREADYSTOPPED = -1072870849; public const int MF_E_ASF_FILESINK_BITRATE_UNKNOWN = -1072870848; public const int MF_E_SINK_NO_STREAMS = -1072870847; public const int MF_S_SINK_NOT_FINALIZED = 870978; public const int MF_E_METADATA_TOO_LONG = -1072870845; public const int MF_E_SINK_NO_SAMPLES_PROCESSED = -1072870844; public const int MF_E_VIDEO_REN_NO_PROCAMP_HW = -1072869856; public const int MF_E_VIDEO_REN_NO_DEINTERLACE_HW = -1072869855; public const int MF_E_VIDEO_REN_COPYPROT_FAILED = -1072869854; public const int MF_E_VIDEO_REN_SURFACE_NOT_SHARED = -1072869853; public const int MF_E_VIDEO_DEVICE_LOCKED = -1072869852; public const int MF_E_NEW_VIDEO_DEVICE = -1072869851; public const int MF_E_NO_VIDEO_SAMPLE_AVAILABLE = -1072869850; public const int MF_E_NO_AUDIO_PLAYBACK_DEVICE = -1072869756; public const int MF_E_AUDIO_PLAYBACK_DEVICE_IN_USE = -1072869755; public const int MF_E_AUDIO_PLAYBACK_DEVICE_INVALIDATED = -1072869754; public const int MF_E_AUDIO_SERVICE_NOT_RUNNING = -1072869753; public const int MF_E_TOPO_INVALID_OPTIONAL_NODE = -1072868850; public const int MF_E_TOPO_CANNOT_FIND_DECRYPTOR = -1072868847; public const int MF_E_TOPO_CODEC_NOT_FOUND = -1072868846; public const int MF_E_TOPO_CANNOT_CONNECT = -1072868845; public const int MF_E_TOPO_UNSUPPORTED = -1072868844; public const int MF_E_TOPO_INVALID_TIME_ATTRIBUTES = -1072868843; public const int MF_E_TOPO_LOOPS_IN_TOPOLOGY = -1072868842; public const int MF_E_TOPO_MISSING_PRESENTATION_DESCRIPTOR = -1072868841; public const int MF_E_TOPO_MISSING_STREAM_DESCRIPTOR = -1072868840; public const int MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED = -1072868839; public const int MF_E_TOPO_MISSING_SOURCE = -1072868838; public const int MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED = -1072868837; public const int MF_E_SEQUENCER_UNKNOWN_SEGMENT_ID = -1072864852; public const int MF_S_SEQUENCER_CONTEXT_CANCELED = 876973; public const int MF_E_NO_SOURCE_IN_CACHE = -1072864850; public const int MF_S_SEQUENCER_SEGMENT_AT_END_OF_STREAM = 876975; public const int MF_E_TRANSFORM_TYPE_NOT_SET = -1072861856; public const int MF_E_TRANSFORM_STREAM_CHANGE = -1072861855; public const int MF_E_TRANSFORM_INPUT_REMAINING = -1072861854; public const int MF_E_TRANSFORM_PROFILE_MISSING = -1072861853; public const int MF_E_TRANSFORM_PROFILE_INVALID_OR_CORRUPT = -1072861852; public const int MF_E_TRANSFORM_PROFILE_TRUNCATED = -1072861851; public const int MF_E_TRANSFORM_PROPERTY_PID_NOT_RECOGNIZED = -1072861850; public const int MF_E_TRANSFORM_PROPERTY_VARIANT_TYPE_WRONG = -1072861849; public const int MF_E_TRANSFORM_PROPERTY_NOT_WRITEABLE = -1072861848; public const int MF_E_TRANSFORM_PROPERTY_ARRAY_VALUE_WRONG_NUM_DIM = -1072861847; public const int MF_E_TRANSFORM_PROPERTY_VALUE_SIZE_WRONG = -1072861846; public const int MF_E_TRANSFORM_PROPERTY_VALUE_OUT_OF_RANGE = -1072861845; public const int MF_E_TRANSFORM_PROPERTY_VALUE_INCOMPATIBLE = -1072861844; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_OUTPUT_MEDIATYPE = -1072861843; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_INPUT_MEDIATYPE = -1072861842; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION = -1072861841; public const int MF_E_TRANSFORM_CONFLICTS_WITH_OTHER_CURRENTLY_ENABLED_FEATURES = -1072861840; public const int MF_E_TRANSFORM_NEED_MORE_INPUT = -1072861838; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_SPKR_CONFIG = -1072861837; public const int MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING = -1072861836; public const int MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT = 879989; public const int MF_E_UNSUPPORTED_D3D_TYPE = -1072861834; public const int MF_E_TRANSFORM_ASYNC_LOCKED = -1072861833; public const int MF_E_TRANSFORM_CANNOT_INITIALIZE_ACM_DRIVER = -1072861832; public const int MF_E_LICENSE_INCORRECT_RIGHTS = -1072860856; public const int MF_E_LICENSE_OUTOFDATE = -1072860855; public const int MF_E_LICENSE_REQUIRED = -1072860854; public const int MF_E_DRM_HARDWARE_INCONSISTENT = -1072860853; public const int MF_E_NO_CONTENT_PROTECTION_MANAGER = -1072860852; public const int MF_E_LICENSE_RESTORE_NO_RIGHTS = -1072860851; public const int MF_E_BACKUP_RESTRICTED_LICENSE = -1072860850; public const int MF_E_LICENSE_RESTORE_NEEDS_INDIVIDUALIZATION = -1072860849; public const int MF_S_PROTECTION_NOT_REQUIRED = 880976; public const int MF_E_COMPONENT_REVOKED = -1072860847; public const int MF_E_TRUST_DISABLED = -1072860846; public const int MF_E_WMDRMOTA_NO_ACTION = -1072860845; public const int MF_E_WMDRMOTA_ACTION_ALREADY_SET = -1072860844; public const int MF_E_WMDRMOTA_DRM_HEADER_NOT_AVAILABLE = -1072860843; public const int MF_E_WMDRMOTA_DRM_ENCRYPTION_SCHEME_NOT_SUPPORTED = -1072860842; public const int MF_E_WMDRMOTA_ACTION_MISMATCH = -1072860841; public const int MF_E_WMDRMOTA_INVALID_POLICY = -1072860840; public const int MF_E_POLICY_UNSUPPORTED = -1072860839; public const int MF_E_OPL_NOT_SUPPORTED = -1072860838; public const int MF_E_TOPOLOGY_VERIFICATION_FAILED = -1072860837; public const int MF_E_SIGNATURE_VERIFICATION_FAILED = -1072860836; public const int MF_E_DEBUGGING_NOT_ALLOWED = -1072860835; public const int MF_E_CODE_EXPIRED = -1072860834; public const int MF_E_GRL_VERSION_TOO_LOW = -1072860833; public const int MF_E_GRL_RENEWAL_NOT_FOUND = -1072860832; public const int MF_E_GRL_EXTENSIBLE_ENTRY_NOT_FOUND = -1072860831; public const int MF_E_KERNEL_UNTRUSTED = -1072860830; public const int MF_E_PEAUTH_UNTRUSTED = -1072860829; public const int MF_E_NON_PE_PROCESS = -1072860827; public const int MF_E_REBOOT_REQUIRED = -1072860825; public const int MF_S_WAIT_FOR_POLICY_SET = 881000; public const int MF_S_VIDEO_DISABLED_WITH_UNKNOWN_SOFTWARE_OUTPUT = 881001; public const int MF_E_GRL_INVALID_FORMAT = -1072860822; public const int MF_E_GRL_UNRECOGNIZED_FORMAT = -1072860821; public const int MF_E_ALL_PROCESS_RESTART_REQUIRED = -1072860820; public const int MF_E_PROCESS_RESTART_REQUIRED = -1072860819; public const int MF_E_USERMODE_UNTRUSTED = -1072860818; public const int MF_E_PEAUTH_SESSION_NOT_STARTED = -1072860817; public const int MF_E_PEAUTH_PUBLICKEY_REVOKED = -1072860815; public const int MF_E_GRL_ABSENT = -1072860814; public const int MF_S_PE_TRUSTED = 881011; public const int MF_E_PE_UNTRUSTED = -1072860812; public const int MF_E_PEAUTH_NOT_STARTED = -1072860811; public const int MF_E_INCOMPATIBLE_SAMPLE_PROTECTION = -1072860810; public const int MF_E_PE_SESSIONS_MAXED = -1072860809; public const int MF_E_HIGH_SECURITY_LEVEL_CONTENT_NOT_ALLOWED = -1072860808; public const int MF_E_TEST_SIGNED_COMPONENTS_NOT_ALLOWED = -1072860807; public const int MF_E_ITA_UNSUPPORTED_ACTION = -1072860806; public const int MF_E_ITA_ERROR_PARSING_SAP_PARAMETERS = -1072860805; public const int MF_E_POLICY_MGR_ACTION_OUTOFBOUNDS = -1072860804; public const int MF_E_BAD_OPL_STRUCTURE_FORMAT = -1072860803; public const int MF_E_ITA_UNRECOGNIZED_ANALOG_VIDEO_PROTECTION_GUID = -1072860802; public const int MF_E_NO_PMP_HOST = -1072860801; public const int MF_E_ITA_OPL_DATA_NOT_INITIALIZED = -1072860800; public const int MF_E_ITA_UNRECOGNIZED_ANALOG_VIDEO_OUTPUT = -1072860799; public const int MF_E_ITA_UNRECOGNIZED_DIGITAL_VIDEO_OUTPUT = -1072860798; public const int MF_E_CLOCK_INVALID_CONTINUITY_KEY = -1072849856; public const int MF_E_CLOCK_NO_TIME_SOURCE = -1072849855; public const int MF_E_CLOCK_STATE_ALREADY_SET = -1072849854; public const int MF_E_CLOCK_NOT_SIMPLE = -1072849853; public const int MF_S_CLOCK_STOPPED = 891972; public const int MF_E_NO_MORE_DROP_MODES = -1072848856; public const int MF_E_NO_MORE_QUALITY_LEVELS = -1072848855; public const int MF_E_DROPTIME_NOT_SUPPORTED = -1072848854; public const int MF_E_QUALITYKNOB_WAIT_LONGER = -1072848853; public const int MF_E_QM_INVALIDSTATE = -1072848852; public const int MF_E_TRANSCODE_NO_CONTAINERTYPE = -1072847856; public const int MF_E_TRANSCODE_PROFILE_NO_MATCHING_STREAMS = -1072847855; public const int MF_E_TRANSCODE_NO_MATCHING_ENCODER = -1072847854; public const int MF_E_ALLOCATOR_NOT_INITIALIZED = -1072846856; public const int MF_E_ALLOCATOR_NOT_COMMITED = -1072846855; public const int MF_E_ALLOCATOR_ALREADY_COMMITED = -1072846854; public const int MF_E_STREAM_ERROR = -1072846853; public const int MF_E_INVALID_STREAM_STATE = -1072846852; public const int MF_E_HW_STREAM_NOT_CONNECTED = -1072846851; } public static class MediaFoundationApi { [CompilerGenerated] private sealed class d__2 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private IMFActivate <>2__current; private int <>l__initialThreadId; private Guid category; public Guid <>3__category; private IntPtr 5__2; private IMFActivate[] <>7__wrap2; private int <>7__wrap3; IMFActivate IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MediaFoundationInterop.MFTEnumEx(category, _MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, null, null, out 5__2, out var pcMFTActivate); IMFActivate[] array = new IMFActivate[pcMFTActivate]; for (int i = 0; i < pcMFTActivate; i++) { IntPtr pUnk = Marshal.ReadIntPtr(new IntPtr(5__2.ToInt64() + i * Marshal.SizeOf(5__2))); array[i] = (IMFActivate)Marshal.GetObjectForIUnknown(pUnk); } <>7__wrap2 = array; <>7__wrap3 = 0; break; } case 1: <>1__state = -1; <>7__wrap3++; break; } if (<>7__wrap3 < <>7__wrap2.Length) { IMFActivate iMFActivate = <>7__wrap2[<>7__wrap3]; <>2__current = iMFActivate; <>1__state = 1; return true; } <>7__wrap2 = null; Marshal.FreeCoTaskMem(5__2); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__2 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__2(0); } d__.category = <>3__category; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static bool initialized; public static void Startup() { if (!initialized) { int num = 2; OperatingSystem oSVersion = Environment.OSVersion; if (oSVersion.Version.Major == 6 && oSVersion.Version.Minor == 0) { num = 1; } MediaFoundationInterop.MFStartup((num << 16) | 0x70); initialized = true; } } [IteratorStateMachine(typeof(d__2))] public static IEnumerable EnumerateTransforms(Guid category) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__2(-2) { <>3__category = category }; } public static void Shutdown() { if (initialized) { MediaFoundationInterop.MFShutdown(); initialized = false; } } public static IMFMediaType CreateMediaType() { MediaFoundationInterop.MFCreateMediaType(out var ppMFType); return ppMFType; } public static IMFMediaType CreateMediaTypeFromWaveFormat(WaveFormat waveFormat) { IMFMediaType iMFMediaType = CreateMediaType(); try { MediaFoundationInterop.MFInitMediaTypeFromWaveFormatEx(iMFMediaType, waveFormat, Marshal.SizeOf(waveFormat)); return iMFMediaType; } catch (Exception) { Marshal.ReleaseComObject(iMFMediaType); throw; } } public static IMFMediaBuffer CreateMemoryBuffer(int bufferSize) { MediaFoundationInterop.MFCreateMemoryBuffer(bufferSize, out var ppBuffer); return ppBuffer; } public static IMFSample CreateSample() { MediaFoundationInterop.MFCreateSample(out var ppIMFSample); return ppIMFSample; } public static IMFAttributes CreateAttributes(int initialSize) { MediaFoundationInterop.MFCreateAttributes(out var ppMFAttributes, initialSize); return ppMFAttributes; } public static IMFByteStream CreateByteStream(object stream) { if (stream is IStream) { MediaFoundationInterop.MFCreateMFByteStreamOnStream(stream as IStream, out var ppByteStream); return ppByteStream; } throw new ArgumentException("Stream must be IStream in desktop apps"); } public static IMFSourceReader CreateSourceReaderFromByteStream(IMFByteStream byteStream) { MediaFoundationInterop.MFCreateSourceReaderFromByteStream(byteStream, null, out var ppSourceReader); return ppSourceReader; } } public static class MediaFoundationInterop { public const int MF_SOURCE_READER_ALL_STREAMS = -2; public const int MF_SOURCE_READER_FIRST_AUDIO_STREAM = -3; public const int MF_SOURCE_READER_FIRST_VIDEO_STREAM = -4; public const int MF_SOURCE_READER_MEDIASOURCE = -1; public const int MF_SDK_VERSION = 2; public const int MF_API_VERSION = 112; public const int MF_VERSION = 131184; [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFStartup(int version, int dwFlags = 0); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFShutdown(); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateMediaType(out IMFMediaType ppMFType); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFInitMediaTypeFromWaveFormatEx([In] IMFMediaType pMFType, [In] WaveFormat pWaveFormat, [In] int cbBufSize); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateWaveFormatExFromMFMediaType(IMFMediaType pMFType, ref IntPtr ppWF, ref int pcbSize, int flags = 0); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSourceReaderFromURL([In][MarshalAs(UnmanagedType.LPWStr)] string pwszURL, [In] IMFAttributes pAttributes, [MarshalAs(UnmanagedType.Interface)] out IMFSourceReader ppSourceReader); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSourceReaderFromByteStream([In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, [MarshalAs(UnmanagedType.Interface)] out IMFSourceReader ppSourceReader); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSinkWriterFromURL([In][MarshalAs(UnmanagedType.LPWStr)] string pwszOutputURL, [In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, out IMFSinkWriter ppSinkWriter); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateMFByteStreamOnStreamEx([MarshalAs(UnmanagedType.IUnknown)] object punkStream, out IMFByteStream ppByteStream); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateMFByteStreamOnStream([In] IStream punkStream, out IMFByteStream ppByteStream); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFTEnumEx([In] Guid guidCategory, [In] _MFT_ENUM_FLAG flags, [In] MFT_REGISTER_TYPE_INFO pInputType, [In] MFT_REGISTER_TYPE_INFO pOutputType, out IntPtr pppMFTActivate, out int pcMFTActivate); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateSample(out IMFSample ppIMFSample); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateMemoryBuffer(int cbMaxLength, out IMFMediaBuffer ppBuffer); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateAttributes([MarshalAs(UnmanagedType.Interface)] out IMFAttributes ppMFAttributes, [In] int cInitialSize); [DllImport("mf.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFTranscodeGetAudioOutputAvailableTypes([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidSubType, [In] _MFT_ENUM_FLAG dwMFTFlags, [In] IMFAttributes pCodecConfig, [MarshalAs(UnmanagedType.Interface)] out IMFCollection ppAvailableTypes); } public abstract class MediaFoundationTransform : IWaveProvider, IDisposable { protected readonly IWaveProvider sourceProvider; protected readonly WaveFormat outputWaveFormat; private readonly byte[] sourceBuffer; private byte[] outputBuffer; private int outputBufferOffset; private int outputBufferCount; private IMFTransform transform; private bool disposed; private long inputPosition; private long outputPosition; private bool initializedForStreaming; public WaveFormat WaveFormat => outputWaveFormat; public MediaFoundationTransform(IWaveProvider sourceProvider, WaveFormat outputFormat) { outputWaveFormat = outputFormat; this.sourceProvider = sourceProvider; sourceBuffer = new byte[sourceProvider.WaveFormat.AverageBytesPerSecond]; outputBuffer = new byte[outputWaveFormat.AverageBytesPerSecond + outputWaveFormat.BlockAlign]; } private void InitializeTransformForStreaming() { transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_COMMAND_FLUSH, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_START_OF_STREAM, IntPtr.Zero); initializedForStreaming = true; } protected abstract IMFTransform CreateTransform(); protected virtual void Dispose(bool disposing) { if (transform != null) { Marshal.ReleaseComObject(transform); } } public void Dispose() { if (!disposed) { disposed = true; Dispose(disposing: true); GC.SuppressFinalize(this); } } ~MediaFoundationTransform() { Dispose(disposing: false); } public int Read(byte[] buffer, int offset, int count) { if (transform == null) { transform = CreateTransform(); InitializeTransformForStreaming(); } int i = 0; if (outputBufferCount > 0) { i += ReadFromOutputBuffer(buffer, offset, count - i); } for (; i < count; i += ReadFromOutputBuffer(buffer, offset + i, count - i)) { IMFSample iMFSample = ReadFromSource(); if (iMFSample == null) { EndStreamAndDrain(); i += ReadFromOutputBuffer(buffer, offset + i, count - i); ClearOutputBuffer(); break; } if (!initializedForStreaming) { InitializeTransformForStreaming(); } transform.ProcessInput(0, iMFSample, 0); Marshal.ReleaseComObject(iMFSample); ReadFromTransform(); } return i; } private void EndStreamAndDrain() { transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_END_OF_STREAM, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_COMMAND_DRAIN, IntPtr.Zero); int num; do { num = ReadFromTransform(); } while (num > 0); inputPosition = 0L; outputPosition = 0L; transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_END_STREAMING, IntPtr.Zero); initializedForStreaming = false; } private void ClearOutputBuffer() { outputBufferCount = 0; outputBufferOffset = 0; } private int ReadFromTransform() { MFT_OUTPUT_DATA_BUFFER[] array = new MFT_OUTPUT_DATA_BUFFER[1]; IMFSample iMFSample = MediaFoundationApi.CreateSample(); IMFMediaBuffer iMFMediaBuffer = MediaFoundationApi.CreateMemoryBuffer(outputBuffer.Length); iMFSample.AddBuffer(iMFMediaBuffer); iMFSample.SetSampleTime(outputPosition); array[0].pSample = iMFSample; _MFT_PROCESS_OUTPUT_STATUS pdwStatus; int num = transform.ProcessOutput(_MFT_PROCESS_OUTPUT_FLAGS.None, 1, array, out pdwStatus); switch (num) { case -1072861838: Marshal.ReleaseComObject(iMFMediaBuffer); Marshal.ReleaseComObject(iMFSample); return 0; default: Marshal.ThrowExceptionForHR(num); break; case 0: break; } array[0].pSample.ConvertToContiguousBuffer(out var ppBuffer); ppBuffer.Lock(out var ppbBuffer, out var _, out var pcbCurrentLength); outputBuffer = BufferHelpers.Ensure(outputBuffer, pcbCurrentLength); Marshal.Copy(ppbBuffer, outputBuffer, 0, pcbCurrentLength); outputBufferOffset = 0; outputBufferCount = pcbCurrentLength; ppBuffer.Unlock(); outputPosition += BytesToNsPosition(outputBufferCount, WaveFormat); Marshal.ReleaseComObject(iMFMediaBuffer); iMFSample.RemoveAllBuffers(); Marshal.ReleaseComObject(iMFSample); Marshal.ReleaseComObject(ppBuffer); return pcbCurrentLength; } private static long BytesToNsPosition(int bytes, WaveFormat waveFormat) { return 10000000L * (long)bytes / waveFormat.AverageBytesPerSecond; } private IMFSample ReadFromSource() { int num = sourceProvider.Read(sourceBuffer, 0, sourceBuffer.Length); if (num == 0) { return null; } IMFMediaBuffer iMFMediaBuffer = MediaFoundationApi.CreateMemoryBuffer(num); iMFMediaBuffer.Lock(out var ppbBuffer, out var _, out var _); Marshal.Copy(sourceBuffer, 0, ppbBuffer, num); iMFMediaBuffer.Unlock(); iMFMediaBuffer.SetCurrentLength(num); IMFSample iMFSample = MediaFoundationApi.CreateSample(); iMFSample.AddBuffer(iMFMediaBuffer); iMFSample.SetSampleTime(inputPosition); long num2 = BytesToNsPosition(num, sourceProvider.WaveFormat); iMFSample.SetSampleDuration(num2); inputPosition += num2; Marshal.ReleaseComObject(iMFMediaBuffer); return iMFSample; } private int ReadFromOutputBuffer(byte[] buffer, int offset, int needed) { int num = Math.Min(needed, outputBufferCount); Array.Copy(outputBuffer, outputBufferOffset, buffer, offset, num); outputBufferOffset += num; outputBufferCount -= num; if (outputBufferCount == 0) { outputBufferOffset = 0; } return num; } public void Reposition() { if (initializedForStreaming) { EndStreamAndDrain(); ClearOutputBuffer(); InitializeTransformForStreaming(); } } } public static class MediaFoundationTransformCategories { [FieldDescription("Video Decoder")] public static readonly Guid VideoDecoder = new Guid("{d6c02d4b-6833-45b4-971a-05a4b04bab91}"); [FieldDescription("Video Encoder")] public static readonly Guid VideoEncoder = new Guid("{f79eac7d-e545-4387-bdee-d647d7bde42a}"); [FieldDescription("Video Effect")] public static readonly Guid VideoEffect = new Guid("{12e17c21-532c-4a6e-8a1c-40825a736397}"); [FieldDescription("Multiplexer")] public static readonly Guid Multiplexer = new Guid("{059c561e-05ae-4b61-b69d-55b61ee54a7b}"); [FieldDescription("Demultiplexer")] public static readonly Guid Demultiplexer = new Guid("{a8700a7a-939b-44c5-99d7-76226b23b3f1}"); [FieldDescription("Audio Decoder")] public static readonly Guid AudioDecoder = new Guid("{9ea73fb4-ef7a-4559-8d5d-719d8f0426c7}"); [FieldDescription("Audio Encoder")] public static readonly Guid AudioEncoder = new Guid("{91c64bd0-f91e-4d8c-9276-db248279d975}"); [FieldDescription("Audio Effect")] public static readonly Guid AudioEffect = new Guid("{11064c48-3648-4ed0-932e-05ce8ac811b7}"); [FieldDescription("Video Processor")] public static readonly Guid VideoProcessor = new Guid("{302EA3FC-AA5F-47f9-9F7A-C2188BB16302}"); [FieldDescription("Other")] public static readonly Guid Other = new Guid("{90175d57-b7ea-4901-aeb3-933a8747756f}"); } public class MediaType { private readonly IMFMediaType mediaType; public int SampleRate { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_SAMPLES_PER_SECOND); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_SAMPLES_PER_SECOND, value); } } public int ChannelCount { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_NUM_CHANNELS); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_NUM_CHANNELS, value); } } public int BitsPerSample { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_BITS_PER_SAMPLE); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_BITS_PER_SAMPLE, value); } } public int AverageBytesPerSecond => GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_AVG_BYTES_PER_SECOND); public Guid SubType { get { return GetGuid(MediaFoundationAttributes.MF_MT_SUBTYPE); } set { mediaType.SetGUID(MediaFoundationAttributes.MF_MT_SUBTYPE, value); } } public Guid MajorType { get { return GetGuid(MediaFoundationAttributes.MF_MT_MAJOR_TYPE); } set { mediaType.SetGUID(MediaFoundationAttributes.MF_MT_MAJOR_TYPE, value); } } public IMFMediaType MediaFoundationObject => mediaType; public MediaType(IMFMediaType mediaType) { this.mediaType = mediaType; } public MediaType() { mediaType = MediaFoundationApi.CreateMediaType(); } public MediaType(WaveFormat waveFormat) { mediaType = MediaFoundationApi.CreateMediaTypeFromWaveFormat(waveFormat); } private int GetUInt32(Guid key) { mediaType.GetUINT32(key, out var punValue); return punValue; } private Guid GetGuid(Guid key) { mediaType.GetGUID(key, out var pguidValue); return pguidValue; } public int TryGetUInt32(Guid key, int defaultValue = -1) { int punValue = defaultValue; try { mediaType.GetUINT32(key, out punValue); } catch (COMException ex) { if (HResult.GetHResult(ex) != -1072875802) { if (HResult.GetHResult(ex) == -1072875843) { throw new ArgumentException("Not a UINT32 parameter"); } throw; } } return punValue; } public void SetUInt32(Guid key, int value) { mediaType.SetUINT32(key, value); } } public static class MediaTypes { public static readonly Guid MFMediaType_Default = new Guid("81A412E6-8103-4B06-857F-1862781024AC"); [FieldDescription("Audio")] public static readonly Guid MFMediaType_Audio = new Guid("73647561-0000-0010-8000-00aa00389b71"); [FieldDescription("Video")] public static readonly Guid MFMediaType_Video = new Guid("73646976-0000-0010-8000-00aa00389b71"); [FieldDescription("Protected Media")] public static readonly Guid MFMediaType_Protected = new Guid("7b4b6fe6-9d04-4494-be14-7e0bd076c8e4"); [FieldDescription("SAMI captions")] public static readonly Guid MFMediaType_SAMI = new Guid("e69669a0-3dcd-40cb-9e2e-3708387c0616"); [FieldDescription("Script stream")] public static readonly Guid MFMediaType_Script = new Guid("72178c22-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("Still image stream")] public static readonly Guid MFMediaType_Image = new Guid("72178c23-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("HTML stream")] public static readonly Guid MFMediaType_HTML = new Guid("72178c24-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("Binary stream")] public static readonly Guid MFMediaType_Binary = new Guid("72178c25-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("File transfer")] public static readonly Guid MFMediaType_FileTransfer = new Guid("72178c26-e45b-11d5-bc2a-00b0d0f3f4ab"); } public struct MFT_INPUT_STREAM_INFO { public long hnsMaxLatency; public _MFT_INPUT_STREAM_INFO_FLAGS dwFlags; public int cbSize; public int cbMaxLookahead; public int cbAlignment; } public enum MFT_MESSAGE_TYPE { MFT_MESSAGE_COMMAND_FLUSH = 0, MFT_MESSAGE_COMMAND_DRAIN = 1, MFT_MESSAGE_SET_D3D_MANAGER = 2, MFT_MESSAGE_DROP_SAMPLES = 3, MFT_MESSAGE_COMMAND_TICK = 4, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING = 268435456, MFT_MESSAGE_NOTIFY_END_STREAMING = 268435457, MFT_MESSAGE_NOTIFY_END_OF_STREAM = 268435458, MFT_MESSAGE_NOTIFY_START_OF_STREAM = 268435459, MFT_MESSAGE_COMMAND_MARKER = 536870912 } public struct MFT_OUTPUT_DATA_BUFFER { public int dwStreamID; public IMFSample pSample; public _MFT_OUTPUT_DATA_BUFFER_FLAGS dwStatus; public IMFCollection pEvents; } public struct MFT_OUTPUT_STREAM_INFO { public _MFT_OUTPUT_STREAM_INFO_FLAGS dwFlags; public int cbSize; public int cbAlignment; } [StructLayout(LayoutKind.Sequential)] public class MFT_REGISTER_TYPE_INFO { public Guid guidMajorType; public Guid guidSubtype; } [StructLayout(LayoutKind.Sequential)] public class MF_SINK_WRITER_STATISTICS { public int cb; public long llLastTimestampReceived; public long llLastTimestampEncoded; public long llLastTimestampProcessed; public long llLastStreamTickReceived; public long llLastSinkSampleRequest; public long qwNumSamplesReceived; public long qwNumSamplesEncoded; public long qwNumSamplesProcessed; public long qwNumStreamTicksReceived; public int dwByteCountQueued; public long qwByteCountProcessed; public int dwNumOutstandingSinkSampleRequests; public int dwAverageSampleRateReceived; public int dwAverageSampleRateEncoded; public int dwAverageSampleRateProcessed; } public static class TranscodeContainerTypes { public static readonly Guid MFTranscodeContainerType_ASF = new Guid(1125085038u, 46783, 20417, 160, 189, 158, 228, 110, 238, 42, 251); public static readonly Guid MFTranscodeContainerType_MPEG4 = new Guid(3698118749u, 47568, 16623, 189, 53, 250, 98, 44, 26, 178, 138); public static readonly Guid MFTranscodeContainerType_MP3 = new Guid(3828922642u, 33777, 19942, 158, 58, 159, 251, 198, 221, 36, 209); public static readonly Guid MFTranscodeContainerType_3GP = new Guid(885326183, 17522, 20276, 158, 160, 196, 159, 186, 207, 3, 125); public static readonly Guid MFTranscodeContainerType_AC3 = new Guid(1837994435u, 35985, 20177, 135, 66, 140, 52, 125, 91, 68, 208); public static readonly Guid MFTranscodeContainerType_ADTS = new Guid(321901181, 3842, 17374, 163, 1, 56, 251, 187, 179, 131, 78); public static readonly Guid MFTranscodeContainerType_MPEG2 = new Guid(3217218553u, 31668, 20367, 175, 222, 225, 18, 196, 75, 168, 130); public static readonly Guid MFTranscodeContainerType_FMPEG4 = new Guid(2611508977u, 16799, 19319, 161, 224, 53, 149, 157, 157, 64, 4); public static readonly Guid MFTranscodeContainerType_WAVE = new Guid(1690518844, 3878, 18241, 190, 99, 135, 189, 248, 187, 147, 91); public static readonly Guid MFTranscodeContainerType_AVI = new Guid(2128603311, 16431, 19830, 163, 60, 97, 159, 209, 87, 208, 241); public static readonly Guid MFTranscodeContainerType_AMR = new Guid(39672531, 25114, 18267, 150, 77, 102, 177, 200, 36, 240, 121); } [Flags] public enum _MFT_ENUM_FLAG { None = 0, MFT_ENUM_FLAG_SYNCMFT = 1, MFT_ENUM_FLAG_ASYNCMFT = 2, MFT_ENUM_FLAG_HARDWARE = 4, MFT_ENUM_FLAG_FIELDOFUSE = 8, MFT_ENUM_FLAG_LOCALMFT = 0x10, MFT_ENUM_FLAG_TRANSCODE_ONLY = 0x20, MFT_ENUM_FLAG_SORTANDFILTER = 0x40, MFT_ENUM_FLAG_ALL = 0x3F } [Flags] public enum _MFT_INPUT_STATUS_FLAGS { None = 0, MFT_INPUT_STATUS_ACCEPT_DATA = 1 } [Flags] public enum _MFT_INPUT_STREAM_INFO_FLAGS { None = 0, MFT_INPUT_STREAM_WHOLE_SAMPLES = 1, MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER = 2, MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE = 4, MFT_INPUT_STREAM_HOLDS_BUFFERS = 8, MFT_INPUT_STREAM_DOES_NOT_ADDREF = 0x100, MFT_INPUT_STREAM_REMOVABLE = 0x200, MFT_INPUT_STREAM_OPTIONAL = 0x400, MFT_INPUT_STREAM_PROCESSES_IN_PLACE = 0x800 } [Flags] public enum _MFT_OUTPUT_DATA_BUFFER_FLAGS { None = 0, MFT_OUTPUT_DATA_BUFFER_INCOMPLETE = 0x1000000, MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE = 0x100, MFT_OUTPUT_DATA_BUFFER_STREAM_END = 0x200, MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE = 0x300 } [Flags] public enum _MFT_OUTPUT_STATUS_FLAGS { None = 0, MFT_OUTPUT_STATUS_SAMPLE_READY = 1 } [Flags] public enum _MFT_OUTPUT_STREAM_INFO_FLAGS { None = 0, MFT_OUTPUT_STREAM_WHOLE_SAMPLES = 1, MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER = 2, MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE = 4, MFT_OUTPUT_STREAM_DISCARDABLE = 8, MFT_OUTPUT_STREAM_OPTIONAL = 0x10, MFT_OUTPUT_STREAM_PROVIDES_SAMPLES = 0x100, MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES = 0x200, MFT_OUTPUT_STREAM_LAZY_READ = 0x400, MFT_OUTPUT_STREAM_REMOVABLE = 0x800 } [Flags] public enum _MFT_PROCESS_OUTPUT_FLAGS { None = 0, MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER = 1, MFT_PROCESS_OUTPUT_REGENERATE_LAST_OUTPUT = 2 } [Flags] public enum _MFT_PROCESS_OUTPUT_STATUS { None = 0, MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS = 0x100 } [Flags] public enum _MFT_SET_TYPE_FLAGS { None = 0, MFT_SET_TYPE_TEST_ONLY = 1 } } namespace NAudio.Dmo { public class DmoDescriptor { public string Name { get; private set; } public Guid Clsid { get; private set; } public DmoDescriptor(string name, Guid clsid) { Name = name; Clsid = clsid; } } public class DmoEnumerator { [CompilerGenerated] private sealed class d__3 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private DmoDescriptor <>2__current; private int <>l__initialThreadId; private Guid category; public Guid <>3__category; private IEnumDmo 5__2; private int 5__3; DmoDescriptor IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_007c; } <>1__state = -1; Marshal.ThrowExceptionForHR(DmoInterop.DMOEnum(ref category, DmoEnumFlags.None, 0, null, 0, null, out 5__2)); goto IL_0032; IL_007c: if (5__3 <= 0) { return false; } goto IL_0032; IL_0032: 5__2.Next(1, out var clsid, out var name, out 5__3); if (5__3 == 1) { string name2 = Marshal.PtrToStringUni(name); Marshal.FreeCoTaskMem(name); <>2__current = new DmoDescriptor(name2, clsid); <>1__state = 1; return true; } goto IL_007c; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__3 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__3(0); } d__.category = <>3__category; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } public static IEnumerable GetAudioEffectNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_EFFECT); } public static IEnumerable GetAudioEncoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_ENCODER); } public static IEnumerable GetAudioDecoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_DECODER); } [IteratorStateMachine(typeof(d__3))] private static IEnumerable GetDmos(Guid category) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(-2) { <>3__category = category }; } } [Flags] internal enum DmoEnumFlags { None = 0, DMO_ENUMF_INCLUDE_KEYED = 1 } internal static class DmoGuids { public static readonly Guid DMOCATEGORY_AUDIO_DECODER = new Guid("57f2db8b-e6bb-4513-9d43-dcd2a6593125"); public static readonly Guid DMOCATEGORY_AUDIO_ENCODER = new Guid("33D9A761-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_VIDEO_DECODER = new Guid("4a69b442-28be-4991-969c-b500adf5d8a8"); public static readonly Guid DMOCATEGORY_VIDEO_ENCODER = new Guid("33D9A760-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_AUDIO_EFFECT = new Guid("f3602b3f-0592-48df-a4cd-674721e7ebeb"); public static readonly Guid DMOCATEGORY_VIDEO_EFFECT = new Guid("d990ee14-776c-4723-be46-3da2f56f10b9"); public static readonly Guid DMOCATEGORY_AUDIO_CAPTURE_EFFECT = new Guid("f665aaba-3e09-4920-aa5f-219811148f09"); } internal static class DmoMediaTypeGuids { public static readonly Guid FORMAT_None = new Guid("0F6417D6-C318-11D0-A43F-00A0C9223196"); public static readonly Guid FORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_VideoInfo2 = new Guid("F72A76A0-EB0A-11d0-ACE4-0000C0CC16BA"); public static readonly Guid FORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGVideo = new Guid("05589f82-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGStreams = new Guid("05589f83-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_DvInfo = new Guid("05589f84-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_525WSS = new Guid("C7ECF04D-4582-4869-9ABB-BFB523B62EDF"); } internal enum DmoHResults { DMO_E_INVALIDSTREAMINDEX = -2147220991, DMO_E_INVALIDTYPE, DMO_E_TYPE_NOT_SET, DMO_E_NOTACCEPTING, DMO_E_TYPE_NOT_ACCEPTED, DMO_E_NO_MORE_ITEMS } [Flags] public enum DmoInPlaceProcessFlags { Normal = 0, Zero = 1 } public enum DmoInPlaceProcessReturn { Normal, HasEffectTail } [Flags] public enum DmoInputDataBufferFlags { None = 0, SyncPoint = 1, Time = 2, TimeLength = 4 } [Flags] internal enum DmoInputStatusFlags { None = 0, DMO_INPUT_STATUSF_ACCEPT_DATA = 1 } internal static class DmoInterop { [DllImport("msdmo.dll")] public static extern int DMOEnum([In] ref Guid guidCategory, DmoEnumFlags flags, int inTypes, [In] DmoPartialMediaType[] inTypesArray, int outTypes, [In] DmoPartialMediaType[] outTypesArray, out IEnumDmo enumDmo); [DllImport("msdmo.dll")] public static extern int MoFreeMediaType([In] ref DmoMediaType mediaType); [DllImport("msdmo.dll")] public static extern int MoInitMediaType([In][Out] ref DmoMediaType mediaType, int formatBlockBytes); [DllImport("msdmo.dll")] public static extern int DMOGetName([In] ref Guid clsidDMO, [Out] StringBuilder name); } public struct DmoMediaType { private Guid majortype; private Guid subtype; private bool bFixedSizeSamples; private bool bTemporalCompression; private int lSampleSize; private Guid formattype; private IntPtr pUnk; private int cbFormat; private IntPtr pbFormat; public Guid MajorType => majortype; public string MajorTypeName => MediaTypes.GetMediaTypeName(majortype); public Guid SubType => subtype; public string SubTypeName { get { if (majortype == MediaTypes.MEDIATYPE_Audio) { return AudioMediaSubtypes.GetAudioSubtypeName(subtype); } return subtype.ToString(); } } public bool FixedSizeSamples => bFixedSizeSamples; public int SampleSize => lSampleSize; public Guid FormatType => formattype; public string FormatTypeName { get { if (formattype == DmoMediaTypeGuids.FORMAT_None) { return "None"; } if (formattype == Guid.Empty) { return "Null"; } if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx) { return "WaveFormatEx"; } return FormatType.ToString(); } } public WaveFormat GetWaveFormat() { if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx) { return WaveFormat.MarshalFromPtr(pbFormat); } throw new InvalidOperationException("Not a WaveFormat type"); } public void SetWaveFormat(WaveFormat waveFormat) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0066: Unknown result type (might be due to invalid IL or missing references) majortype = MediaTypes.MEDIATYPE_Audio; WaveFormatExtensible val = (WaveFormatExtensible)(object)((waveFormat is WaveFormatExtensible) ? waveFormat : null); if (val != null) { subtype = val.SubFormat; } else { WaveFormatEncoding encoding = waveFormat.Encoding; if ((int)encoding != 1) { if ((int)encoding != 3) { if ((int)encoding != 85) { throw new ArgumentException($"Not a supported encoding {waveFormat.Encoding}"); } subtype = AudioMediaSubtypes.WMMEDIASUBTYPE_MP3; } else { subtype = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; } } else { subtype = AudioMediaSubtypes.MEDIASUBTYPE_PCM; } } bFixedSizeSamples = SubType == AudioMediaSubtypes.MEDIASUBTYPE_PCM || SubType == AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; formattype = DmoMediaTypeGuids.FORMAT_WaveFormatEx; if (cbFormat < Marshal.SizeOf(waveFormat)) { throw new InvalidOperationException("Not enough memory assigned for a WaveFormat structure"); } Marshal.StructureToPtr(waveFormat, pbFormat, fDeleteOld: false); } } [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct DmoOutputDataBuffer : IDisposable { [MarshalAs(UnmanagedType.Interface)] private IMediaBuffer pBuffer; private DmoOutputDataBufferFlags dwStatus; private long rtTimestamp; private long referenceTimeDuration; public IMediaBuffer MediaBuffer { get { return pBuffer; } internal set { pBuffer = value; } } public int Length => ((MediaBuffer)pBuffer).Length; public DmoOutputDataBufferFlags StatusFlags { get { return dwStatus; } internal set { dwStatus = value; } } public long Timestamp { get { return rtTimestamp; } internal set { rtTimestamp = value; } } public long Duration { get { return referenceTimeDuration; } internal set { referenceTimeDuration = value; } } public bool MoreDataAvailable => (StatusFlags & DmoOutputDataBufferFlags.Incomplete) == DmoOutputDataBufferFlags.Incomplete; public DmoOutputDataBuffer(int maxBufferSize) { pBuffer = new MediaBuffer(maxBufferSize); dwStatus = DmoOutputDataBufferFlags.None; rtTimestamp = 0L; referenceTimeDuration = 0L; } public void Dispose() { if (pBuffer != null) { ((MediaBuffer)pBuffer).Dispose(); pBuffer = null; GC.SuppressFinalize(this); } } public void RetrieveData(byte[] data, int offset) { ((MediaBuffer)pBuffer).RetrieveData(data, offset); } } [Flags] public enum DmoOutputDataBufferFlags { None = 0, SyncPoint = 1, Time = 2, TimeLength = 4, Incomplete = 0x1000000 } internal struct DmoPartialMediaType { private Guid type; private Guid subtype; public Guid Type { get { return type; } internal set { type = value; } } public Guid Subtype { get { return subtype; } internal set { subtype = value; } } } [Flags] public enum DmoProcessOutputFlags { None = 0, DiscardWhenNoBuffer = 1 } [Flags] internal enum DmoSetTypeFlags { None = 0, DMO_SET_TYPEF_TEST_ONLY = 1, DMO_SET_TYPEF_CLEAR = 2 } [ComImport] [Guid("2c3cd98a-2bfa-4a53-9c27-5249ba64ba0f")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IEnumDmo { int Next(int itemsToFetch, out Guid clsid, out IntPtr name, out int itemsFetched); int Skip(int itemsToSkip); int Reset(); int Clone(out IEnumDmo enumPointer); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("59eff8b9-938c-4a26-82f2-95cb84cdc837")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMediaBuffer { [PreserveSig] int SetLength(int length); [PreserveSig] int GetMaxLength(out int maxLength); [PreserveSig] int GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("d8ad0f58-5494-4102-97c5-ec798e59bcf4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaObject { [PreserveSig] int GetStreamCount(out int inputStreams, out int outputStreams); [PreserveSig] int GetInputStreamInfo(int inputStreamIndex, out InputStreamInfoFlags flags); [PreserveSig] int GetOutputStreamInfo(int outputStreamIndex, out OutputStreamInfoFlags flags); [PreserveSig] int GetInputType(int inputStreamIndex, int typeIndex, out DmoMediaType mediaType); [PreserveSig] int GetOutputType(int outputStreamIndex, int typeIndex, out DmoMediaType mediaType); [PreserveSig] int SetInputType(int inputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags); [PreserveSig] int SetOutputType(int outputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags); [PreserveSig] int GetInputCurrentType(int inputStreamIndex, out DmoMediaType mediaType); [PreserveSig] int GetOutputCurrentType(int outputStreamIndex, out DmoMediaType mediaType); [PreserveSig] int GetInputSizeInfo(int inputStreamIndex, out int size, out int maxLookahead, out int alignment); [PreserveSig] int GetOutputSizeInfo(int outputStreamIndex, out int size, out int alignment); [PreserveSig] int GetInputMaxLatency(int inputStreamIndex, out long referenceTimeMaxLatency); [PreserveSig] int SetInputMaxLatency(int inputStreamIndex, long referenceTimeMaxLatency); [PreserveSig] int Flush(); [PreserveSig] int Discontinuity(int inputStreamIndex); [PreserveSig] int AllocateStreamingResources(); [PreserveSig] int FreeStreamingResources(); [PreserveSig] int GetInputStatus(int inputStreamIndex, out DmoInputStatusFlags flags); [PreserveSig] int ProcessInput(int inputStreamIndex, [In] IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long referenceTimeTimestamp, long referenceTimeDuration); [PreserveSig] int ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DmoOutputDataBuffer[] outputBuffers, out int statusReserved); [PreserveSig] int Lock(bool acquireLock); } [ComImport] [SuppressUnmanagedCodeSecurity] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("651B9AD0-0FC7-4AA9-9538-D89931010741")] internal interface IMediaObjectInPlace { [PreserveSig] int Process([In] int size, [In] IntPtr data, [In] long refTimeStart, [In] DmoInPlaceProcessFlags dwFlags); [PreserveSig] int Clone([MarshalAs(UnmanagedType.Interface)] out IMediaObjectInPlace mediaObjectInPlace); [PreserveSig] int GetLatency(out long latencyTime); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("6d6cbb60-a223-44aa-842f-a2f06750be6d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaParamInfo { [PreserveSig] int GetParamCount(out int paramCount); [PreserveSig] int GetParamInfo(int paramIndex, ref MediaParamInfo paramInfo); [PreserveSig] int GetParamText(int paramIndex, out IntPtr paramText); [PreserveSig] int GetNumTimeFormats(out int numTimeFormats); [PreserveSig] int GetSupportedTimeFormat(int formatIndex, out Guid guidTimeFormat); [PreserveSig] int GetCurrentTimeFormat(out Guid guidTimeFormat, out int mediaTimeData); } [Flags] internal enum InputStreamInfoFlags { None = 0, DMO_INPUT_STREAMF_WHOLE_SAMPLES = 1, DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER = 2, DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE = 4, DMO_INPUT_STREAMF_HOLDS_BUFFERS = 8 } [ComImport] [Guid("E7E9984F-F09F-4da4-903F-6E2E0EFE56B5")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IWMResamplerProps { int SetHalfFilterLength(int outputQuality); int SetUserChannelMtx([In] float[] channelConversionMatrix); } public class MediaBuffer : IMediaBuffer, IDisposable { private IntPtr buffer; private int length; private readonly int maxLength; public int Length { get { return length; } set { if (length > maxLength) { throw new ArgumentException("Cannot be greater than maximum buffer size"); } length = value; } } public MediaBuffer(int maxLength) { buffer = Marshal.AllocCoTaskMem(maxLength); this.maxLength = maxLength; } public void Dispose() { if (buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(buffer); buffer = IntPtr.Zero; GC.SuppressFinalize(this); } } ~MediaBuffer() { Dispose(); } int IMediaBuffer.SetLength(int length) { if (length > maxLength) { return -2147483645; } this.length = length; return 0; } int IMediaBuffer.GetMaxLength(out int maxLength) { maxLength = this.maxLength; return 0; } int IMediaBuffer.GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer) { if (bufferPointerPointer != IntPtr.Zero) { Marshal.WriteIntPtr(bufferPointerPointer, buffer); } if (validDataLengthPointer != IntPtr.Zero) { Marshal.WriteInt32(validDataLengthPointer, length); } return 0; } public void LoadData(byte[] data, int bytes) { Length = bytes; Marshal.Copy(data, 0, buffer, bytes); } public void RetrieveData(byte[] data, int offset) { Marshal.Copy(buffer, data, offset, Length); } } public class MediaObject : IDisposable { [CompilerGenerated] private sealed class d__11 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private DmoMediaType <>2__current; private int <>l__initialThreadId; public MediaObject <>4__this; private int inputStreamIndex; public int <>3__inputStreamIndex; private int 5__2; DmoMediaType IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; MediaObject mediaObject = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } DmoMediaType? inputType; DmoMediaType? dmoMediaType = (inputType = mediaObject.GetInputType(inputStreamIndex, 5__2)); if (dmoMediaType.HasValue) { <>2__current = inputType.Value; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__11 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__11(0) { <>4__this = <>4__this }; } d__.inputStreamIndex = <>3__inputStreamIndex; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__12 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private DmoMediaType <>2__current; private int <>l__initialThreadId; public MediaObject <>4__this; private int outputStreamIndex; public int <>3__outputStreamIndex; private int 5__2; DmoMediaType IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__12(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; MediaObject mediaObject = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } DmoMediaType? outputType; DmoMediaType? dmoMediaType = (outputType = mediaObject.GetOutputType(outputStreamIndex, 5__2)); if (dmoMediaType.HasValue) { <>2__current = outputType.Value; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__12 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__12(0) { <>4__this = <>4__this }; } d__.outputStreamIndex = <>3__outputStreamIndex; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private IMediaObject mediaObject; private readonly int inputStreams; private readonly int outputStreams; public int InputStreamCount => inputStreams; public int OutputStreamCount => outputStreams; internal MediaObject(IMediaObject mediaObject) { this.mediaObject = mediaObject; mediaObject.GetStreamCount(out inputStreams, out outputStreams); } public DmoMediaType? GetInputType(int inputStream, int inputTypeIndex) { try { if (mediaObject.GetInputType(inputStream, inputTypeIndex, out var mediaType) == 0) { DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; } } catch (COMException ex) { if (HResult.GetHResult(ex) != -2147220986) { throw; } } return null; } public DmoMediaType? GetOutputType(int outputStream, int outputTypeIndex) { try { if (mediaObject.GetOutputType(outputStream, outputTypeIndex, out var mediaType) == 0) { DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; } } catch (COMException ex) { if (HResult.GetHResult(ex) != -2147220986) { throw; } } return null; } public DmoMediaType GetOutputCurrentType(int outputStreamIndex) { DmoMediaType mediaType; int outputCurrentType = mediaObject.GetOutputCurrentType(outputStreamIndex, out mediaType); switch (outputCurrentType) { case 0: DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; case -2147220989: throw new InvalidOperationException("Media type was not set."); default: throw Marshal.GetExceptionForHR(outputCurrentType); } } [IteratorStateMachine(typeof(d__11))] public IEnumerable GetInputTypes(int inputStreamIndex) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(-2) { <>4__this = this, <>3__inputStreamIndex = inputStreamIndex }; } [IteratorStateMachine(typeof(d__12))] public IEnumerable GetOutputTypes(int outputStreamIndex) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__12(-2) { <>4__this = this, <>3__outputStreamIndex = outputStreamIndex }; } public bool SupportsInputType(int inputStreamIndex, DmoMediaType mediaType) { return SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); } private bool SetInputType(int inputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags) { switch (mediaObject.SetInputType(inputStreamIndex, ref mediaType, flags)) { case -2147220991: throw new ArgumentException("Invalid stream index"); default: _ = -2147220987; return false; case 0: return true; } } public void SetInputType(int inputStreamIndex, DmoMediaType mediaType) { if (!SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None)) { throw new ArgumentException("Media Type not supported"); } } public void SetInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool num = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None); DmoInterop.MoFreeMediaType(ref mediaType); if (!num) { throw new ArgumentException("Media Type not supported"); } } public bool SupportsInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool result = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); DmoInterop.MoFreeMediaType(ref mediaType); return result; } private DmoMediaType CreateDmoMediaTypeForWaveFormat(WaveFormat waveFormat) { DmoMediaType mediaType = default(DmoMediaType); int formatBlockBytes = Marshal.SizeOf(waveFormat); DmoInterop.MoInitMediaType(ref mediaType, formatBlockBytes); mediaType.SetWaveFormat(waveFormat); return mediaType; } public bool SupportsOutputType(int outputStreamIndex, DmoMediaType mediaType) { return SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); } public bool SupportsOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool result = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); DmoInterop.MoFreeMediaType(ref mediaType); return result; } private bool SetOutputType(int outputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags) { int num = mediaObject.SetOutputType(outputStreamIndex, ref mediaType, flags); return num switch { -2147220987 => false, 0 => true, _ => throw Marshal.GetExceptionForHR(num), }; } public void SetOutputType(int outputStreamIndex, DmoMediaType mediaType) { if (!SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None)) { throw new ArgumentException("Media Type not supported"); } } public void SetOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool num = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None); DmoInterop.MoFreeMediaType(ref mediaType); if (!num) { throw new ArgumentException("Media Type not supported"); } } public MediaObjectSizeInfo GetInputSizeInfo(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputSizeInfo(inputStreamIndex, out var size, out var maxLookahead, out var alignment)); return new MediaObjectSizeInfo(size, maxLookahead, alignment); } public MediaObjectSizeInfo GetOutputSizeInfo(int outputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetOutputSizeInfo(outputStreamIndex, out var size, out var alignment)); return new MediaObjectSizeInfo(size, 0, alignment); } public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long timestamp, long duration) { Marshal.ThrowExceptionForHR(mediaObject.ProcessInput(inputStreamIndex, mediaBuffer, flags, timestamp, duration)); } public void ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, DmoOutputDataBuffer[] outputBuffers) { Marshal.ThrowExceptionForHR(mediaObject.ProcessOutput(flags, outputBufferCount, outputBuffers, out var _)); } public void AllocateStreamingResources() { Marshal.ThrowExceptionForHR(mediaObject.AllocateStreamingResources()); } public void FreeStreamingResources() { Marshal.ThrowExceptionForHR(mediaObject.FreeStreamingResources()); } public long GetInputMaxLatency(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputMaxLatency(inputStreamIndex, out var referenceTimeMaxLatency)); return referenceTimeMaxLatency; } public void Flush() { Marshal.ThrowExceptionForHR(mediaObject.Flush()); } public void Discontinuity(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.Discontinuity(inputStreamIndex)); } public bool IsAcceptingData(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputStatus(inputStreamIndex, out var flags)); return (flags & DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA) == DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA; } public void Dispose() { if (mediaObject != null) { Marshal.ReleaseComObject(mediaObject); mediaObject = null; } } } public class MediaObjectInPlace : IDisposable { private IMediaObjectInPlace mediaObjectInPlace; internal MediaObjectInPlace(IMediaObjectInPlace mediaObjectInPlace) { this.mediaObjectInPlace = mediaObjectInPlace; } public DmoInPlaceProcessReturn Process(int size, int offset, byte[] data, long timeStart, DmoInPlaceProcessFlags inPlaceFlag) { IntPtr intPtr = Marshal.AllocHGlobal(size); Marshal.Copy(data, offset, intPtr, size); int num = mediaObjectInPlace.Process(size, intPtr, timeStart, inPlaceFlag); Marshal.ThrowExceptionForHR(num); Marshal.Copy(intPtr, data, offset, size); Marshal.FreeHGlobal(intPtr); return (DmoInPlaceProcessReturn)num; } public MediaObjectInPlace Clone() { Marshal.ThrowExceptionForHR(this.mediaObjectInPlace.Clone(out var mediaObjectInPlace)); return new MediaObjectInPlace(mediaObjectInPlace); } public long GetLatency() { Marshal.ThrowExceptionForHR(mediaObjectInPlace.GetLatency(out var latencyTime)); return latencyTime; } public MediaObject GetMediaObject() { return new MediaObject((IMediaObject)mediaObjectInPlace); } public void Dispose() { if (mediaObjectInPlace != null) { Marshal.ReleaseComObject(mediaObjectInPlace); mediaObjectInPlace = null; } } } public class MediaObjectSizeInfo { public int Size { get; private set; } public int MaxLookahead { get; } public int Alignment { get; } public MediaObjectSizeInfo(int size, int maxLookahead, int alignment) { Size = size; MaxLookahead = maxLookahead; Alignment = alignment; } public override string ToString() { return $"Size: {Size}, Alignment {Alignment}, MaxLookahead {MaxLookahead}"; } } internal struct MediaParamInfo { public MediaParamType mpType; public MediaParamCurveType mopCaps; public float mpdMinValue; public float mpdMaxValue; public float mpdNeutralValue; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szUnitText; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szLabel; } internal enum MediaParamType { Int, Float, Bool, Enum, Max } [Flags] internal enum MediaParamCurveType { MP_CURVE_JUMP = 1, MP_CURVE_LINEAR = 2, MP_CURVE_SQUARE = 4, MP_CURVE_INVSQUARE = 8, MP_CURVE_SINE = 0x10 } internal static class MediaTypes { public static readonly Guid MEDIATYPE_AnalogAudio = new Guid("0482DEE1-7817-11cf-8a03-00aa006ecb65"); public static readonly Guid MEDIATYPE_AnalogVideo = new Guid("0482DDE1-7817-11cf-8A03-00AA006ECB65"); public static readonly Guid MEDIATYPE_Audio = new Guid("73647561-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_AUXLine21Data = new Guid("670AEA80-3A82-11d0-B79B-00AA003767A7"); public static readonly Guid MEDIATYPE_File = new Guid("656c6966-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Interleaved = new Guid("73766169-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Midi = new Guid("7364696D-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_ScriptCommand = new Guid("73636d64-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Stream = new Guid("e436eb83-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIATYPE_Text = new Guid("73747874-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Timecode = new Guid("0482DEE3-7817-11cf-8a03-00aa006ecb65"); public static readonly Guid MEDIATYPE_Video = new Guid("73646976-0000-0010-8000-00AA00389B71"); public static readonly Guid[] MajorTypes = new Guid[12] { MEDIATYPE_AnalogAudio, MEDIATYPE_AnalogVideo, MEDIATYPE_Audio, MEDIATYPE_AUXLine21Data, MEDIATYPE_File, MEDIATYPE_Interleaved, MEDIATYPE_Midi, MEDIATYPE_ScriptCommand, MEDIATYPE_Stream, MEDIATYPE_Text, MEDIATYPE_Timecode, MEDIATYPE_Video }; public static readonly string[] MajorTypeNames = new string[12] { "Analog Audio", "Analog Video", "Audio", "AUXLine21Data", "File", "Interleaved", "Midi", "ScriptCommand", "Stream", "Text", "Timecode", "Video" }; public static string GetMediaTypeName(Guid majorType) { for (int i = 0; i < MajorTypes.Length; i++) { if (majorType == MajorTypes[i]) { return MajorTypeNames[i]; } } throw new ArgumentException("Major Type not found"); } } [Flags] internal enum OutputStreamInfoFlags { DMO_OUTPUT_STREAMF_WHOLE_SAMPLES = 1, DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER = 2, DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE = 4, DMO_OUTPUT_STREAMF_DISCARDABLE = 8, DMO_OUTPUT_STREAMF_OPTIONAL = 0x10 } [ComImport] [Guid("f447b69e-1884-4a7e-8055-346f74d6edb3")] internal class ResamplerMediaComObject { } public class DmoResampler : IDisposable { private MediaObject mediaObject; private IPropertyStore propertyStoreInterface; private IWMResamplerProps resamplerPropsInterface; private ResamplerMediaComObject mediaComObject; public MediaObject MediaObject => mediaObject; public DmoResampler() { mediaComObject = new ResamplerMediaComObject(); mediaObject = new MediaObject((IMediaObject)mediaComObject); propertyStoreInterface = (IPropertyStore)mediaComObject; resamplerPropsInterface = (IWMResamplerProps)mediaComObject; } public void Dispose() { if (propertyStoreInterface != null) { Marshal.ReleaseComObject(propertyStoreInterface); propertyStoreInterface = null; } if (resamplerPropsInterface != null) { Marshal.ReleaseComObject(resamplerPropsInterface); resamplerPropsInterface = null; } if (mediaObject != null) { mediaObject.Dispose(); mediaObject = null; } if (mediaComObject != null) { Marshal.ReleaseComObject(mediaComObject); mediaComObject = null; } } } [ComImport] [Guid("bbeea841-0a63-4f52-a7ab-a9b3a84ed38a")] internal class WindowsMediaMp3DecoderComObject { } public class WindowsMediaMp3Decoder : IDisposable { private MediaObject mediaObject; private IPropertyStore propertyStoreInterface; private WindowsMediaMp3DecoderComObject mediaComObject; public MediaObject MediaObject => mediaObject; public WindowsMediaMp3Decoder() { mediaComObject = new WindowsMediaMp3DecoderComObject(); mediaObject = new MediaObject((IMediaObject)mediaComObject); propertyStoreInterface = (IPropertyStore)mediaComObject; } public void Dispose() { if (propertyStoreInterface != null) { Marshal.ReleaseComObject(propertyStoreInterface); propertyStoreInterface = null; } if (mediaObject != null) { mediaObject.Dispose(); mediaObject = null; } if (mediaComObject != null) { Marshal.ReleaseComObject(mediaComObject); mediaComObject = null; } } } } namespace NAudio.Dmo.Effect { public enum ChorusPhase { Neg180, Neg90, Zero, Pos90, Pos180 } public enum ChorusWaveForm { Triangle, Sin } internal struct DsFxChorus { public float WetDryMix; public float Depth; public float FeedBack; public float Frequency; public ChorusWaveForm WaveForm; public float Delay; public ChorusPhase Phase; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("880842e3-145f-43e6-a934-a71806e50547")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXChorus { [PreserveSig] int SetAllParameters([In] ref DsFxChorus param); [PreserveSig] int GetAllParameters(out DsFxChorus param); } public class DmoChorus : IDmoEffector, IDisposable { public struct Params { public const float WetDryMixMin = 0f; public const float WetDryMixMax = 100f; public const float WetDrtMixDefault = 50f; public const float DepthMin = 0f; public const float DepthMax = 100f; public const float DepthDefault = 10f; public const float FeedBackMin = -99f; public const float FeedBackMax = 99f; public const float FeedBaclDefault = 25f; public const float FrequencyMin = 0f; public const float FrequencyMax = 10f; public const float FrequencyDefault = 1.1f; public const ChorusWaveForm WaveFormDefault = ChorusWaveForm.Sin; public const float DelayMin = 0f; public const float DelayMax = 20f; public const float DelayDefault = 16f; public const ChorusPhase PhaseDefault = ChorusPhase.Pos90; private readonly IDirectSoundFXChorus fxChorus; public float WetDryMix { get { return GetAllParameters().WetDryMix; } set { DsFxChorus allParameters = GetAllParameters(); allParameters.WetDryMix = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float Depth { get { return GetAllParameters().Depth; } set { DsFxChorus allParameters = GetAllParameters(); allParameters.Depth = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float FeedBack { get { return GetAllParameters().FeedBack; } set { DsFxChorus allParameters = GetAllParameters(); allParameters.FeedBack = Math.Max(Math.Min(99f, value), -99f); SetAllParameters(allParameters); } } public float Frequency { get { return GetAllParameters().Frequency; } set { DsFxChorus allParameters = GetAllParameters(); allParameters.Frequency = Math.Max(Math.Min(10f, value), 0f); SetAllParameters(allParameters); } } public ChorusWaveForm WaveForm { get { return GetAllParameters().WaveForm; } set { DsFxChorus allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(ChorusWaveForm), value)) { allParameters.WaveForm = value; } SetAllParameters(allParameters); } } public float Delay { get { return GetAllParameters().Delay; } set { DsFxChorus allParameters = GetAllParameters(); allParameters.Delay = Math.Max(Math.Min(20f, value), 0f); SetAllParameters(allParameters); } } public ChorusPhase Phase { get { return GetAllParameters().Phase; } set { DsFxChorus allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(ChorusPhase), value)) { allParameters.Phase = value; } SetAllParameters(allParameters); } } internal Params(IDirectSoundFXChorus dsFxObject) { fxChorus = dsFxObject; } private void SetAllParameters(DsFxChorus param) { Marshal.ThrowExceptionForHR(fxChorus.SetAllParameters(ref param)); } private DsFxChorus GetAllParameters() { Marshal.ThrowExceptionForHR(fxChorus.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Chorus = new Guid("EFE6629C-81F7-4281-BD91-C9D604A95AF6"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoChorus() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Chorus)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXChorus)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxCompressor { public float Gain; public float Attack; public float Release; public float Threshold; public float Ratio; public float PreDelay; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("4bbd1154-62f6-4e2c-a15c-d3b6c417f7a0")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXCompressor { [PreserveSig] int SetAllParameters([In] ref DsFxCompressor param); [PreserveSig] int GetAllParameters(out DsFxCompressor param); } public class DmoCompressor : IDmoEffector, IDisposable { public struct Params { public const float GainMin = -60f; public const float GainMax = 60f; public const float GainDefault = 0f; public const float AttackMin = 0.01f; public const float AttackMax = 500f; public const float AttackDefault = 10f; public const float ReleaseMin = 50f; public const float ReleaseMax = 3000f; public const float ReleaseDefault = 200f; public const float ThresholdMin = -60f; public const float ThresholdMax = 0f; public const float TjresholdDefault = -20f; public const float RatioMin = 1f; public const float RatioMax = 100f; public const float RatioDefault = 3f; public const float PreDelayMin = 0f; public const float PreDelayMax = 4f; public const float PreDelayDefault = 4f; private readonly IDirectSoundFXCompressor fxCompressor; public float Gain { get { return GetAllParameters().Gain; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.Gain = Math.Max(Math.Min(60f, value), -60f); SetAllParameters(allParameters); } } public float Attack { get { return GetAllParameters().Attack; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.Attack = Math.Max(Math.Min(500f, value), 0.01f); SetAllParameters(allParameters); } } public float Release { get { return GetAllParameters().Release; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.Release = Math.Max(Math.Min(3000f, value), 50f); SetAllParameters(allParameters); } } public float Threshold { get { return GetAllParameters().Threshold; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.Threshold = Math.Max(Math.Min(0f, value), -60f); SetAllParameters(allParameters); } } public float Ratio { get { return GetAllParameters().Ratio; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.Ratio = Math.Max(Math.Min(100f, value), 1f); SetAllParameters(allParameters); } } public float PreDelay { get { return GetAllParameters().PreDelay; } set { DsFxCompressor allParameters = GetAllParameters(); allParameters.PreDelay = Math.Max(Math.Min(4f, value), 0f); SetAllParameters(allParameters); } } internal Params(IDirectSoundFXCompressor dsFxObject) { fxCompressor = dsFxObject; } private void SetAllParameters(DsFxCompressor param) { Marshal.ThrowExceptionForHR(fxCompressor.SetAllParameters(ref param)); } private DsFxCompressor GetAllParameters() { Marshal.ThrowExceptionForHR(fxCompressor.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Compressor = new Guid("EF011F79-4000-406D-87AF-BFFB3FC39D57"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoCompressor() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Compressor)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXCompressor)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxDistortion { public float Gain; public float Edge; public float PostEqCenterFrequency; public float PostEqBandWidth; public float PreLowPassCutoff; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("8ecf4326-455f-4d8b-bda9-8d5d3e9e3e0b")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXDistortion { [PreserveSig] int SetAllParameters([In] ref DsFxDistortion param); [PreserveSig] int GetAllParameters(out DsFxDistortion param); } public class DmoDistortion : IDmoEffector, IDisposable { public struct Params { public const float GainMin = -60f; public const float GainMax = 0f; public const float GainDefault = -18f; public const float EdgeMin = 0f; public const float EdgeMax = 100f; public const float EdgeDefault = 15f; public const float PostEqCenterFrequencyMin = 100f; public const float PostEqCenterFrequencyMax = 8000f; public const float PostEqCenterFrequencyDefault = 2400f; public const float PostEqBandWidthMin = 100f; public const float PostEqBandWidthMax = 8000f; public const float PostEqBandWidthDefault = 2400f; public const float PreLowPassCutoffMin = 100f; public const float PreLowPassCutoffMax = 8000f; public const float PreLowPassCutoffDefault = 8000f; private readonly IDirectSoundFXDistortion fxDistortion; public float Gain { get { return GetAllParameters().Gain; } set { DsFxDistortion allParameters = GetAllParameters(); allParameters.Gain = Math.Max(Math.Min(0f, value), -60f); SetAllParameters(allParameters); } } public float Edge { get { return GetAllParameters().Edge; } set { DsFxDistortion allParameters = GetAllParameters(); allParameters.Edge = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float PostEqCenterFrequency { get { return GetAllParameters().PostEqCenterFrequency; } set { DsFxDistortion allParameters = GetAllParameters(); allParameters.PostEqCenterFrequency = Math.Max(Math.Min(8000f, value), 100f); SetAllParameters(allParameters); } } public float PostEqBandWidth { get { return GetAllParameters().PostEqBandWidth; } set { DsFxDistortion allParameters = GetAllParameters(); allParameters.PostEqBandWidth = Math.Max(Math.Min(8000f, value), 100f); SetAllParameters(allParameters); } } public float PreLowPassCutoff { get { return GetAllParameters().PreLowPassCutoff; } set { DsFxDistortion allParameters = GetAllParameters(); allParameters.PreLowPassCutoff = Math.Max(Math.Min(8000f, value), 100f); SetAllParameters(allParameters); } } internal Params(IDirectSoundFXDistortion dsFxObject) { fxDistortion = dsFxObject; } private void SetAllParameters(DsFxDistortion param) { Marshal.ThrowExceptionForHR(fxDistortion.SetAllParameters(ref param)); } private DsFxDistortion GetAllParameters() { Marshal.ThrowExceptionForHR(fxDistortion.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Distortion = new Guid("EF114C90-CD1D-484E-96E5-09CFAF912A21"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoDistortion() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Distortion)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXDistortion)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxEcho { public float WetDryMix; public float FeedBack; public float LeftDelay; public float RightDelay; public EchoPanDelay PanDelay; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("8bd28edf-50db-4e92-a2bd-445488d1ed42")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXEcho { [PreserveSig] int SetAllParameters([In] ref DsFxEcho param); [PreserveSig] int GetAllParameters(out DsFxEcho param); } public class DmoEcho : IDmoEffector, IDisposable { public struct Params { public const float WetDryMixMin = 0f; public const float WetDryMixMax = 100f; public const float WetDeyMixDefault = 50f; public const float FeedBackMin = 0f; public const float FeedBackMax = 100f; public const float FeedBackDefault = 50f; public const float LeftDelayMin = 1f; public const float LeftDelayMax = 2000f; public const float LeftDelayDefault = 500f; public const float RightDelayMin = 1f; public const float RightDelayMax = 2000f; public const float RightDelayDefault = 500f; public const EchoPanDelay PanDelayDefault = EchoPanDelay.Off; private readonly IDirectSoundFXEcho fxEcho; public float WetDryMix { get { return GetAllParameters().WetDryMix; } set { DsFxEcho allParameters = GetAllParameters(); allParameters.WetDryMix = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float FeedBack { get { return GetAllParameters().FeedBack; } set { DsFxEcho allParameters = GetAllParameters(); allParameters.FeedBack = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float LeftDelay { get { return GetAllParameters().LeftDelay; } set { DsFxEcho allParameters = GetAllParameters(); allParameters.LeftDelay = Math.Max(Math.Min(2000f, value), 1f); SetAllParameters(allParameters); } } public float RightDelay { get { return GetAllParameters().RightDelay; } set { DsFxEcho allParameters = GetAllParameters(); allParameters.RightDelay = Math.Max(Math.Min(2000f, value), 1f); SetAllParameters(allParameters); } } public EchoPanDelay PanDelay { get { return GetAllParameters().PanDelay; } set { DsFxEcho allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(EchoPanDelay), value)) { allParameters.PanDelay = value; } SetAllParameters(allParameters); } } internal Params(IDirectSoundFXEcho dsFxObject) { fxEcho = dsFxObject; } private void SetAllParameters(DsFxEcho param) { Marshal.ThrowExceptionForHR(fxEcho.SetAllParameters(ref param)); } private DsFxEcho GetAllParameters() { Marshal.ThrowExceptionForHR(fxEcho.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Echo = new Guid("EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoEcho() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Echo)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXEcho)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxFlanger { public float WetDryMix; public float Depth; public float FeedBack; public float Frequency; public FlangerWaveForm WaveForm; public float Delay; public FlangerPhase Phase; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("903e9878-2c92-4072-9b2c-ea68f5396783")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXFlanger { [PreserveSig] int SetAllParameters([In] ref DsFxFlanger param); [PreserveSig] int GetAllParameters(out DsFxFlanger param); } public class DmoFlanger : IDmoEffector, IDisposable { public struct Params { public const float WetDryMixMin = 0f; public const float WetDryMixMax = 100f; public const float WetDrtMixDefault = 50f; public const float DepthMin = 0f; public const float DepthMax = 100f; public const float DepthDefault = 100f; public const float FeedBackMin = -99f; public const float FeedBackMax = 99f; public const float FeedBaclDefault = -50f; public const float FrequencyMin = 0f; public const float FrequencyMax = 10f; public const float FrequencyDefault = 0.25f; public const FlangerWaveForm WaveFormDefault = FlangerWaveForm.Sin; public const float DelayMin = 0f; public const float DelayMax = 4f; public const float DelayDefault = 2f; public const FlangerPhase PhaseDefault = FlangerPhase.Zero; private readonly IDirectSoundFXFlanger fxFlanger; public float WetDryMix { get { return GetAllParameters().WetDryMix; } set { DsFxFlanger allParameters = GetAllParameters(); allParameters.WetDryMix = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float Depth { get { return GetAllParameters().Depth; } set { DsFxFlanger allParameters = GetAllParameters(); allParameters.Depth = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float FeedBack { get { return GetAllParameters().FeedBack; } set { DsFxFlanger allParameters = GetAllParameters(); allParameters.FeedBack = Math.Max(Math.Min(99f, value), -99f); SetAllParameters(allParameters); } } public float Frequency { get { return GetAllParameters().Frequency; } set { DsFxFlanger allParameters = GetAllParameters(); allParameters.Frequency = Math.Max(Math.Min(10f, value), 0f); SetAllParameters(allParameters); } } public FlangerWaveForm WaveForm { get { return GetAllParameters().WaveForm; } set { DsFxFlanger allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(FlangerWaveForm), value)) { allParameters.WaveForm = value; } SetAllParameters(allParameters); } } public float Delay { get { return GetAllParameters().Delay; } set { DsFxFlanger allParameters = GetAllParameters(); allParameters.Delay = Math.Max(Math.Min(4f, value), 0f); SetAllParameters(allParameters); } } public FlangerPhase Phase { get { return GetAllParameters().Phase; } set { DsFxFlanger allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(FlangerPhase), value)) { allParameters.Phase = value; } SetAllParameters(allParameters); } } internal Params(IDirectSoundFXFlanger dsFxObject) { fxFlanger = dsFxObject; } private void SetAllParameters(DsFxFlanger param) { Marshal.ThrowExceptionForHR(fxFlanger.SetAllParameters(ref param)); } private DsFxFlanger GetAllParameters() { Marshal.ThrowExceptionForHR(fxFlanger.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Flanger = new Guid("EFCA3D92-DFD8-4672-A603-7420894BAD98"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoFlanger() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Flanger)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXFlanger)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxGargle { public uint RateHz; public GargleWaveShape WaveShape; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("d616f352-d622-11ce-aac5-0020af0b99a3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXGargle { [PreserveSig] int SetAllParameters([In] ref DsFxGargle param); [PreserveSig] int GetAllParameters(out DsFxGargle param); } public class DmoGargle : IDmoEffector, IDisposable { public struct Params { public const uint RateHzMin = 1u; public const uint RateHzMax = 1000u; public const uint RateHzDefault = 20u; public const GargleWaveShape WaveShapeDefault = GargleWaveShape.Triangle; private readonly IDirectSoundFXGargle fxGargle; public uint RateHz { get { return GetAllParameters().RateHz; } set { DsFxGargle allParameters = GetAllParameters(); allParameters.RateHz = Math.Max(Math.Min(1000u, value), 1u); SetAllParameters(allParameters); } } public GargleWaveShape WaveShape { get { return GetAllParameters().WaveShape; } set { DsFxGargle allParameters = GetAllParameters(); if (Enum.IsDefined(typeof(GargleWaveShape), value)) { allParameters.WaveShape = value; } SetAllParameters(allParameters); } } internal Params(IDirectSoundFXGargle dsFxObject) { fxGargle = dsFxObject; } private void SetAllParameters(DsFxGargle param) { Marshal.ThrowExceptionForHR(fxGargle.SetAllParameters(ref param)); } private DsFxGargle GetAllParameters() { Marshal.ThrowExceptionForHR(fxGargle.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_Gargle = new Guid("DAFD8210-5711-4B91-9FE3-F75B7AE279BF"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoGargle() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_Gargle)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXGargle)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxI3Dl2Reverb { public int Room; public int RoomHf; public float RoomRollOffFactor; public float DecayTime; public float DecayHfRatio; public int Reflections; public float ReflectionsDelay; public int Reverb; public float ReverbDelay; public float Diffusion; public float Density; public float HfReference; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("4b166a6a-0d66-43f3-80e3-ee6280dee1a4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXI3DL2Reverb { [PreserveSig] int SetAllParameters([In] ref DsFxI3Dl2Reverb param); [PreserveSig] int GetAllParameters(out DsFxI3Dl2Reverb param); [PreserveSig] int SetPreset([In] uint preset); [PreserveSig] int GetPreset(out uint preset); [PreserveSig] int SetQuality([In] int quality); [PreserveSig] int GetQuality(out int quality); } public class DmoI3DL2Reverb : IDmoEffector, IDisposable { public struct Params { public const int RoomMin = -10000; public const int RoomMax = 0; public const int RoomDefault = -1000; public const int RoomHfMin = -10000; public const int RoomHfMax = 0; public const int RoomHfDefault = -100; public const float RoomRollOffFactorMin = 0f; public const float RoomRollOffFactorMax = 10f; public const float RoomRollOffFactorDefault = 0f; public const float DecayTimeMin = 0.1f; public const float DecayTimeMax = 20f; public const float DecayTimeDefault = 1.49f; public const float DecayHfRatioMin = 0.1f; public const float DecayHfRatioMax = 2f; public const float DecayHfRatioDefault = 0.83f; public const int ReflectionsMin = -10000; public const int ReflectionsMax = 1000; public const int ReflectionsDefault = -2602; public const float ReflectionsDelayMin = 0f; public const float ReflectionsDelayMax = 0.3f; public const float ReflectionsDelayDefault = 0.007f; public const int ReverbMin = -10000; public const int ReverbMax = 2000; public const int ReverbDefault = 200; public const float ReverbDelayMin = 0f; public const float ReverbDelayMax = 0.1f; public const float ReverbDelayDefault = 0.011f; public const float DiffusionMin = 0f; public const float DiffusionMax = 100f; public const float DiffusionDefault = 100f; public const float DensityMin = 0f; public const float DensityMax = 100f; public const float DensityDefault = 100f; public const float HfReferenceMin = 20f; public const float HfReferenceMax = 20000f; public const float HfReferenceDefault = 5000f; public const int QualityMin = 0; public const int QualityMax = 3; public const int QualityDefault = 2; private readonly IDirectSoundFXI3DL2Reverb fxI3Dl2Reverb; public int Room { get { return GetAllParameters().Room; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.Room = Math.Max(Math.Min(0, value), -10000); SetAllParameters(allParameters); } } public int RoomHf { get { return GetAllParameters().RoomHf; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.RoomHf = Math.Max(Math.Min(0, value), -10000); SetAllParameters(allParameters); } } public float RoomRollOffFactor { get { return GetAllParameters().RoomRollOffFactor; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.RoomRollOffFactor = Math.Max(Math.Min(10f, value), 0f); SetAllParameters(allParameters); } } public float DecayTime { get { return GetAllParameters().DecayTime; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.DecayTime = Math.Max(Math.Min(20f, value), 0.1f); SetAllParameters(allParameters); } } public float DecayHfRatio { get { return GetAllParameters().DecayHfRatio; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.DecayHfRatio = Math.Max(Math.Min(2f, value), 0.1f); SetAllParameters(allParameters); } } public int Reflections { get { return GetAllParameters().Reflections; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.Reflections = Math.Max(Math.Min(1000, value), -10000); SetAllParameters(allParameters); } } public float ReflectionsDelay { get { return GetAllParameters().ReflectionsDelay; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.ReflectionsDelay = Math.Max(Math.Min(0.3f, value), 0f); SetAllParameters(allParameters); } } public int Reverb { get { return GetAllParameters().Reverb; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.Reverb = Math.Max(Math.Min(2000, value), -10000); SetAllParameters(allParameters); } } public float ReverbDelay { get { return GetAllParameters().ReverbDelay; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.ReverbDelay = Math.Max(Math.Min(0.1f, value), 0f); SetAllParameters(allParameters); } } public float Diffusion { get { return GetAllParameters().Diffusion; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.Diffusion = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float Density { get { return GetAllParameters().Density; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.Density = Math.Max(Math.Min(100f, value), 0f); SetAllParameters(allParameters); } } public float HfReference { get { return GetAllParameters().HfReference; } set { DsFxI3Dl2Reverb allParameters = GetAllParameters(); allParameters.HfReference = Math.Max(Math.Min(20000f, value), 20f); SetAllParameters(allParameters); } } public int Quality { get { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.GetQuality(out var quality)); return quality; } set { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetQuality(value)); } } internal Params(IDirectSoundFXI3DL2Reverb dsFxObject) { fxI3Dl2Reverb = dsFxObject; } public void SetPreset(I3DL2EnvironmentPreset preset) { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetPreset((uint)preset)); } public I3DL2EnvironmentPreset GetPreset() { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.GetPreset(out var preset)); return (I3DL2EnvironmentPreset)preset; } private void SetAllParameters(DsFxI3Dl2Reverb param) { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetAllParameters(ref param)); } private DsFxI3Dl2Reverb GetAllParameters() { Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_I3DL2Reverb = new Guid("EF985E71-D5C7-42D4-BA4D-2D073E2E96F4"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoI3DL2Reverb() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_I3DL2Reverb)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXI3DL2Reverb)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxParamEq { public float Center; public float BandWidth; public float Gain; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("c03ca9fe-fe90-4204-8078-82334cd177da")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFxParamEq { [PreserveSig] int SetAllParameters([In] ref DsFxParamEq param); [PreserveSig] int GetAllParameters(out DsFxParamEq param); } public class DmoParamEq : IDmoEffector, IDisposable { public struct Params { public const float CenterMin = 80f; public const float CenterMax = 16000f; public const float CenterDefault = 8000f; public const float BandWidthMin = 1f; public const float BandWidthMax = 36f; public const float BandWidthDefault = 12f; public const float GainMin = -15f; public const float GainMax = 15f; public const float GainDefault = 0f; private readonly IDirectSoundFxParamEq fxParamEq; public float Center { get { return GetAllParameters().Center; } set { DsFxParamEq allParameters = GetAllParameters(); allParameters.Center = Math.Max(Math.Min(16000f, value), 80f); SetAllParameters(allParameters); } } public float BandWidth { get { return GetAllParameters().BandWidth; } set { DsFxParamEq allParameters = GetAllParameters(); allParameters.BandWidth = Math.Max(Math.Min(36f, value), 1f); SetAllParameters(allParameters); } } public float Gain { get { return GetAllParameters().Gain; } set { DsFxParamEq allParameters = GetAllParameters(); allParameters.Gain = Math.Max(Math.Min(15f, value), -15f); SetAllParameters(allParameters); } } internal Params(IDirectSoundFxParamEq dsFxObject) { fxParamEq = dsFxObject; } private void SetAllParameters(DsFxParamEq param) { Marshal.ThrowExceptionForHR(fxParamEq.SetAllParameters(ref param)); } private DsFxParamEq GetAllParameters() { Marshal.ThrowExceptionForHR(fxParamEq.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_ParamEq = new Guid("120CED89-3BF4-4173-A132-3CB406CF3231"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoParamEq() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_ParamEq)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFxParamEq)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } internal struct DsFxWavesReverb { public float InGain; public float ReverbMix; public float ReverbTime; public float HighFreqRtRatio; } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("46858c3a-0dc6-45e3-b760-d4eef16cb325")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundFXWavesReverb { [PreserveSig] int SetAllParameters([In] ref DsFxWavesReverb param); [PreserveSig] int GetAllParameters(out DsFxWavesReverb param); } public class DmoWavesReverb : IDmoEffector, IDisposable { public struct Params { public const float InGainMin = -96f; public const float InGainMax = 0f; public const float InGainDefault = 0f; public const float ReverbMixMin = -96f; public const float ReverbMixMax = 0f; public const float ReverbMixDefault = 0f; public const float ReverbTimeMin = 0.001f; public const float ReverbTimeMax = 3000f; public const float ReverbTimeDefault = 1000f; public const float HighFreqRtRatioMin = 0.001f; public const float HighFreqRtRatioMax = 0.999f; public const float HighFreqRtRatioDefault = 0.001f; private readonly IDirectSoundFXWavesReverb fxWavesReverb; public float InGain { get { return GetAllParameters().InGain; } set { DsFxWavesReverb allParameters = GetAllParameters(); allParameters.InGain = Math.Max(Math.Min(0f, value), -96f); SetAllParameters(allParameters); } } public float ReverbMix { get { return GetAllParameters().ReverbMix; } set { DsFxWavesReverb allParameters = GetAllParameters(); allParameters.ReverbMix = Math.Max(Math.Min(0f, value), -96f); SetAllParameters(allParameters); } } public float ReverbTime { get { return GetAllParameters().ReverbTime; } set { DsFxWavesReverb allParameters = GetAllParameters(); allParameters.ReverbTime = Math.Max(Math.Min(3000f, value), 0.001f); SetAllParameters(allParameters); } } public float HighFreqRtRatio { get { return GetAllParameters().HighFreqRtRatio; } set { DsFxWavesReverb allParameters = GetAllParameters(); allParameters.HighFreqRtRatio = Math.Max(Math.Min(0.999f, value), 0.001f); SetAllParameters(allParameters); } } internal Params(IDirectSoundFXWavesReverb dsFxObject) { fxWavesReverb = dsFxObject; } private void SetAllParameters(DsFxWavesReverb param) { Marshal.ThrowExceptionForHR(fxWavesReverb.SetAllParameters(ref param)); } private DsFxWavesReverb GetAllParameters() { Marshal.ThrowExceptionForHR(fxWavesReverb.GetAllParameters(out var param)); return param; } } private static readonly Guid Id_WavesReverb = new Guid("87FC0268-9A55-4360-95AA-004A1D9DE26C"); public MediaObject MediaObject { get; } public MediaObjectInPlace MediaObjectInPlace { get; } public Params EffectParams { get; } public DmoWavesReverb() { DmoDescriptor dmoDescriptor = DmoEnumerator.GetAudioEffectNames().First((DmoDescriptor descriptor) => object.Equals(descriptor.Clsid, Id_WavesReverb)); if (dmoDescriptor != null) { object obj = Activator.CreateInstance(Type.GetTypeFromCLSID(dmoDescriptor.Clsid)); MediaObject = new MediaObject((IMediaObject)obj); MediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)obj); EffectParams = new Params((IDirectSoundFXWavesReverb)obj); } } public void Dispose() { MediaObjectInPlace?.Dispose(); MediaObject?.Dispose(); } } public enum EchoPanDelay { Off, On } public enum FlangerPhase { Neg180, Neg90, Zero, Pos90, Pos180 } public enum FlangerWaveForm { Triangle, Sin } public enum GargleWaveShape : uint { Triangle, Square } public enum I3DL2EnvironmentPreset { Default, Generic, PaddedCell, Room, Bathroom, LivingRoom, StoneRoom, Auditorium, ConcertHall, Cave, Arena, Hangar, CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Mountains, Quarry, Plain, ParkingLot, SewerPipe, UnderWater, SmallRoom, MediumRoom, LargeRoom, MediumHall, LargeHall, Plate } public interface IDmoEffector : IDisposable { MediaObject MediaObject { get; } MediaObjectInPlace MediaObjectInPlace { get; } TParameters EffectParams { get; } } } namespace NAudio.FileFormats.Mp3 { public class DmoMp3FrameDecompressor : IMp3FrameDecompressor, IDisposable { private WindowsMediaMp3Decoder mp3Decoder; private WaveFormat pcmFormat; private MediaBuffer inputMediaBuffer; private DmoOutputDataBuffer outputBuffer; private bool reposition; public WaveFormat OutputFormat => pcmFormat; public DmoMp3FrameDecompressor(WaveFormat sourceFormat) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown mp3Decoder = new WindowsMediaMp3Decoder(); if (!mp3Decoder.MediaObject.SupportsInputWaveFormat(0, sourceFormat)) { throw new ArgumentException("Unsupported input format"); } mp3Decoder.MediaObject.SetInputWaveFormat(0, sourceFormat); pcmFormat = new WaveFormat(sourceFormat.SampleRate, sourceFormat.Channels); if (!mp3Decoder.MediaObject.SupportsOutputWaveFormat(0, pcmFormat)) { throw new ArgumentException($"Unsupported output format {pcmFormat}"); } mp3Decoder.MediaObject.SetOutputWaveFormat(0, pcmFormat); inputMediaBuffer = new MediaBuffer(sourceFormat.AverageBytesPerSecond); outputBuffer = new DmoOutputDataBuffer(pcmFormat.AverageBytesPerSecond); } public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset) { inputMediaBuffer.LoadData(frame.RawData, frame.FrameLength); if (reposition) { mp3Decoder.MediaObject.Flush(); reposition = false; } mp3Decoder.MediaObject.ProcessInput(0, inputMediaBuffer, DmoInputDataBufferFlags.None, 0L, 0L); outputBuffer.MediaBuffer.SetLength(0); outputBuffer.StatusFlags = DmoOutputDataBufferFlags.None; mp3Decoder.MediaObject.ProcessOutput(DmoProcessOutputFlags.None, 1, new DmoOutputDataBuffer[1] { outputBuffer }); if (outputBuffer.Length == 0) { return 0; } outputBuffer.RetrieveData(dest, destOffset); return outputBuffer.Length; } public void Reset() { reposition = true; } public void Dispose() { if (inputMediaBuffer != null) { inputMediaBuffer.Dispose(); inputMediaBuffer = null; } outputBuffer.Dispose(); if (mp3Decoder != null) { mp3Decoder.Dispose(); mp3Decoder = null; } } } } namespace NAudio.CoreAudioApi { public class AudioCaptureClient : IDisposable { private IAudioCaptureClient audioCaptureClientInterface; internal AudioCaptureClient(IAudioCaptureClient audioCaptureClientInterface) { this.audioCaptureClientInterface = audioCaptureClientInterface; } public IntPtr GetBuffer(out int numFramesToRead, out AudioClientBufferFlags bufferFlags, out long devicePosition, out long qpcPosition) { Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetBuffer(out var dataBuffer, out numFramesToRead, out bufferFlags, out devicePosition, out qpcPosition)); return dataBuffer; } public IntPtr GetBuffer(out int numFramesToRead, out AudioClientBufferFlags bufferFlags) { Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetBuffer(out var dataBuffer, out numFramesToRead, out bufferFlags, out var _, out var _)); return dataBuffer; } public int GetNextPacketSize() { Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetNextPacketSize(out var numFramesInNextPacket)); return numFramesInNextPacket; } public void ReleaseBuffer(int numFramesWritten) { Marshal.ThrowExceptionForHR(audioCaptureClientInterface.ReleaseBuffer(numFramesWritten)); } public void Dispose() { if (audioCaptureClientInterface != null) { Marshal.ReleaseComObject(audioCaptureClientInterface); audioCaptureClientInterface = null; GC.SuppressFinalize(this); } } } public class AudioClient : IDisposable { private static readonly Guid ID_AudioStreamVolume = new Guid("93014887-242D-4068-8A15-CF5E93B90FE3"); private static readonly Guid ID_AudioClockClient = new Guid("CD63314F-3FBA-4a1b-812C-EF96358728E7"); private static readonly Guid ID_AudioRenderClient = new Guid("F294ACFC-3146-4483-A7BF-ADDCA7C260E2"); private static readonly Guid ID_AudioCaptureClient = new Guid("c8adbd64-e71e-48a0-a4de-185c395cd317"); private static readonly Guid IID_IAudioClient2 = new Guid("726778CD-F60A-4eda-82DE-E47610CD78AA"); private IAudioClient audioClientInterface; private WaveFormat mixFormat; private AudioRenderClient audioRenderClient; private AudioCaptureClient audioCaptureClient; private AudioClockClient audioClockClient; private AudioStreamVolume audioStreamVolume; private AudioClientShareMode shareMode; public WaveFormat MixFormat { get { if (mixFormat == null) { Marshal.ThrowExceptionForHR(audioClientInterface.GetMixFormat(out var deviceFormatPointer)); WaveFormat val = WaveFormat.MarshalFromPtr(deviceFormatPointer); Marshal.FreeCoTaskMem(deviceFormatPointer); mixFormat = val; } return mixFormat; } } public int BufferSize { get { Marshal.ThrowExceptionForHR(audioClientInterface.GetBufferSize(out var bufferSize)); return (int)bufferSize; } } public long StreamLatency => audioClientInterface.GetStreamLatency(); public int CurrentPadding { get { Marshal.ThrowExceptionForHR(audioClientInterface.GetCurrentPadding(out var currentPadding)); return currentPadding; } } public long DefaultDevicePeriod { get { Marshal.ThrowExceptionForHR(audioClientInterface.GetDevicePeriod(out var defaultDevicePeriod, out var _)); return defaultDevicePeriod; } } public long MinimumDevicePeriod { get { Marshal.ThrowExceptionForHR(audioClientInterface.GetDevicePeriod(out var _, out var minimumDevicePeriod)); return minimumDevicePeriod; } } public AudioStreamVolume AudioStreamVolume { get { if (shareMode == AudioClientShareMode.Exclusive) { throw new InvalidOperationException("AudioStreamVolume is ONLY supported for shared audio streams."); } if (audioStreamVolume == null) { Marshal.ThrowExceptionForHR(audioClientInterface.GetService(ID_AudioStreamVolume, out var interfacePointer)); audioStreamVolume = new AudioStreamVolume((IAudioStreamVolume)interfacePointer); } return audioStreamVolume; } } public AudioClockClient AudioClockClient { get { if (audioClockClient == null) { Marshal.ThrowExceptionForHR(audioClientInterface.GetService(ID_AudioClockClient, out var interfacePointer)); audioClockClient = new AudioClockClient((IAudioClock)interfacePointer); } return audioClockClient; } } public AudioRenderClient AudioRenderClient { get { if (audioRenderClient == null) { Marshal.ThrowExceptionForHR(audioClientInterface.GetService(ID_AudioRenderClient, out var interfacePointer)); audioRenderClient = new AudioRenderClient((IAudioRenderClient)interfacePointer); } return audioRenderClient; } } public AudioCaptureClient AudioCaptureClient { get { if (audioCaptureClient == null) { Marshal.ThrowExceptionForHR(audioClientInterface.GetService(ID_AudioCaptureClient, out var interfacePointer)); audioCaptureClient = new AudioCaptureClient((IAudioCaptureClient)interfacePointer); } return audioCaptureClient; } } public static async Task ActivateAsync(string deviceInterfacePath, AudioClientProperties? audioClientProperties) { ActivateAudioInterfaceCompletionHandler activateAudioInterfaceCompletionHandler = new ActivateAudioInterfaceCompletionHandler(delegate(IAudioClient2 ac2) { if (audioClientProperties.HasValue) { IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audioClientProperties.Value)); try { Marshal.StructureToPtr(audioClientProperties.Value, intPtr, fDeleteOld: false); ac2.SetClientProperties(intPtr); } finally { Marshal.FreeHGlobal(intPtr); } } }); NativeMethods.ActivateAudioInterfaceAsync(deviceInterfacePath, IID_IAudioClient2, IntPtr.Zero, activateAudioInterfaceCompletionHandler, out var _); return new AudioClient(await activateAudioInterfaceCompletionHandler); } public AudioClient(IAudioClient audioClientInterface) { this.audioClientInterface = audioClientInterface; } public void Initialize(AudioClientShareMode shareMode, AudioClientStreamFlags streamFlags, long bufferDuration, long periodicity, WaveFormat waveFormat, Guid audioSessionGuid) { this.shareMode = shareMode; Marshal.ThrowExceptionForHR(audioClientInterface.Initialize(shareMode, streamFlags, bufferDuration, periodicity, waveFormat, ref audioSessionGuid)); mixFormat = null; } public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat) { WaveFormatExtensible closestMatchFormat; return IsFormatSupported(shareMode, desiredFormat, out closestMatchFormat); } private IntPtr GetPointerToPointer() { return Marshal.AllocHGlobal(Marshal.SizeOf()); } public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat) { IntPtr pointerToPointer = GetPointerToPointer(); closestMatchFormat = null; int num = audioClientInterface.IsFormatSupported(shareMode, desiredFormat, pointerToPointer); IntPtr intPtr = Marshal.PtrToStructure(pointerToPointer); if (intPtr != IntPtr.Zero) { closestMatchFormat = Marshal.PtrToStructure(intPtr); Marshal.FreeCoTaskMem(intPtr); } Marshal.FreeHGlobal(pointerToPointer); switch (num) { case 0: return true; case 1: return false; case -2004287480: return false; default: Marshal.ThrowExceptionForHR(num); throw new NotSupportedException("Unknown hresult " + num); } } public void Start() { audioClientInterface.Start(); } public void Stop() { audioClientInterface.Stop(); } public void SetEventHandle(IntPtr eventWaitHandle) { audioClientInterface.SetEventHandle(eventWaitHandle); } public void Reset() { audioClientInterface.Reset(); } public void Dispose() { if (audioClientInterface != null) { if (audioClockClient != null) { audioClockClient.Dispose(); audioClockClient = null; } if (audioRenderClient != null) { audioRenderClient.Dispose(); audioRenderClient = null; } if (audioCaptureClient != null) { audioCaptureClient.Dispose(); audioCaptureClient = null; } if (audioStreamVolume != null) { audioStreamVolume.Dispose(); audioStreamVolume = null; } Marshal.ReleaseComObject(audioClientInterface); audioClientInterface = null; GC.SuppressFinalize(this); } } } [Flags] public enum AudioClientBufferFlags { None = 0, DataDiscontinuity = 1, Silent = 2, TimestampError = 4 } public struct AudioClientProperties { public uint cbSize; public int bIsOffload; public AudioStreamCategory eCategory; public AudioClientStreamOptions Options; } public enum AudioClientShareMode { Shared, Exclusive } [Flags] public enum AudioClientStreamFlags : uint { None = 0u, CrossProcess = 0x10000u, Loopback = 0x20000u, EventCallback = 0x40000u, NoPersist = 0x80000u, RateAdjust = 0x100000u, SrcDefaultQuality = 0x8000000u, AutoConvertPcm = 0x80000000u } internal enum ProcessLoopbackMode { IncludeTargetProcessTree, ExcludeTargetProcessTree } internal enum AudioClientActivationType { Default, ProcessLoopback } [Flags] public enum AudioClientStreamOptions { None = 0, Raw = 1, MatchFormat = 2, Ambisonics = 4 } public class AudioClockClient : IDisposable { private IAudioClock audioClockClientInterface; public int Characteristics { get { Marshal.ThrowExceptionForHR(audioClockClientInterface.GetCharacteristics(out var characteristics)); return (int)characteristics; } } public ulong Frequency { get { Marshal.ThrowExceptionForHR(audioClockClientInterface.GetFrequency(out var frequency)); return frequency; } } public ulong AdjustedPosition { get { int num = 0; ulong position; ulong qpcPosition; while (!GetPosition(out position, out qpcPosition) && ++num != 5) { } if (Stopwatch.IsHighResolution) { ulong num2 = ((ulong)((decimal)Stopwatch.GetTimestamp() * 10000000m / (decimal)Stopwatch.Frequency) - qpcPosition) * Frequency / 10000000; return position + num2; } return position; } } public bool CanAdjustPosition => Stopwatch.IsHighResolution; internal AudioClockClient(IAudioClock audioClockClientInterface) { this.audioClockClientInterface = audioClockClientInterface; } public bool GetPosition(out ulong position, out ulong qpcPosition) { int position2 = audioClockClientInterface.GetPosition(out position, out qpcPosition); if (position2 == -1) { return false; } Marshal.ThrowExceptionForHR(position2); return true; } public void Dispose() { if (audioClockClientInterface != null) { Marshal.ReleaseComObject(audioClockClientInterface); audioClockClientInterface = null; GC.SuppressFinalize(this); } } } public class AudioEndpointVolume : IDisposable { private readonly IAudioEndpointVolume audioEndPointVolume; private AudioEndpointVolumeCallback callBack; private Guid notificationGuid = Guid.Empty; public Guid NotificationGuid { get { return notificationGuid; } set { notificationGuid = value; } } public AudioEndpointVolumeVolumeRange VolumeRange { get; } public EEndpointHardwareSupport HardwareSupport { get; } public AudioEndpointVolumeStepInformation StepInformation { get; } public AudioEndpointVolumeChannels Channels { get; } public float MasterVolumeLevel { get { Marshal.ThrowExceptionForHR(audioEndPointVolume.GetMasterVolumeLevel(out var pfLevelDB)); return pfLevelDB; } set { Marshal.ThrowExceptionForHR(audioEndPointVolume.SetMasterVolumeLevel(value, ref notificationGuid)); } } public float MasterVolumeLevelScalar { get { Marshal.ThrowExceptionForHR(audioEndPointVolume.GetMasterVolumeLevelScalar(out var pfLevel)); return pfLevel; } set { Marshal.ThrowExceptionForHR(audioEndPointVolume.SetMasterVolumeLevelScalar(value, ref notificationGuid)); } } public bool Mute { get { Marshal.ThrowExceptionForHR(audioEndPointVolume.GetMute(out var pbMute)); return pbMute; } set { Marshal.ThrowExceptionForHR(audioEndPointVolume.SetMute(value, ref notificationGuid)); } } public event AudioEndpointVolumeNotificationDelegate OnVolumeNotification; public void VolumeStepUp() { Marshal.ThrowExceptionForHR(audioEndPointVolume.VolumeStepUp(ref notificationGuid)); } public void VolumeStepDown() { Marshal.ThrowExceptionForHR(audioEndPointVolume.VolumeStepDown(ref notificationGuid)); } internal AudioEndpointVolume(IAudioEndpointVolume realEndpointVolume) { audioEndPointVolume = realEndpointVolume; Channels = new AudioEndpointVolumeChannels(audioEndPointVolume); StepInformation = new AudioEndpointVolumeStepInformation(audioEndPointVolume); Marshal.ThrowExceptionForHR(audioEndPointVolume.QueryHardwareSupport(out var pdwHardwareSupportMask)); HardwareSupport = (EEndpointHardwareSupport)pdwHardwareSupportMask; VolumeRange = new AudioEndpointVolumeVolumeRange(audioEndPointVolume); callBack = new AudioEndpointVolumeCallback(this); Marshal.ThrowExceptionForHR(audioEndPointVolume.RegisterControlChangeNotify(callBack)); } internal void FireNotification(AudioVolumeNotificationData notificationData) { this.OnVolumeNotification?.Invoke(notificationData); } public void Dispose() { if (callBack != null) { Marshal.ThrowExceptionForHR(audioEndPointVolume.UnregisterControlChangeNotify(callBack)); callBack = null; } Marshal.ReleaseComObject(audioEndPointVolume); GC.SuppressFinalize(this); } ~AudioEndpointVolume() { Dispose(); } } internal class AudioEndpointVolumeCallback : IAudioEndpointVolumeCallback { private readonly AudioEndpointVolume parent; internal AudioEndpointVolumeCallback(AudioEndpointVolume parent) { this.parent = parent; } public void OnNotify(IntPtr notifyData) { AudioVolumeNotificationDataStruct audioVolumeNotificationDataStruct = Marshal.PtrToStructure(notifyData); IntPtr intPtr = Marshal.OffsetOf("ChannelVolume"); IntPtr ptr = (IntPtr)((long)notifyData + (long)intPtr); float[] array = new float[audioVolumeNotificationDataStruct.nChannels]; for (int i = 0; i < audioVolumeNotificationDataStruct.nChannels; i++) { array[i] = Marshal.PtrToStructure(ptr); } AudioVolumeNotificationData notificationData = new AudioVolumeNotificationData(audioVolumeNotificationDataStruct.guidEventContext, audioVolumeNotificationDataStruct.bMuted, audioVolumeNotificationDataStruct.fMasterVolume, array, audioVolumeNotificationDataStruct.guidEventContext); parent.FireNotification(notificationData); } } public class AudioEndpointVolumeChannel { private readonly uint channel; private readonly IAudioEndpointVolume audioEndpointVolume; private Guid notificationGuid = Guid.Empty; public Guid NotificationGuid { get { return notificationGuid; } set { notificationGuid = value; } } public float VolumeLevel { get { Marshal.ThrowExceptionForHR(audioEndpointVolume.GetChannelVolumeLevel(channel, out var pfLevelDB)); return pfLevelDB; } set { Marshal.ThrowExceptionForHR(audioEndpointVolume.SetChannelVolumeLevel(channel, value, ref notificationGuid)); } } public float VolumeLevelScalar { get { Marshal.ThrowExceptionForHR(audioEndpointVolume.GetChannelVolumeLevelScalar(channel, out var pfLevel)); return pfLevel; } set { Marshal.ThrowExceptionForHR(audioEndpointVolume.SetChannelVolumeLevelScalar(channel, value, ref notificationGuid)); } } internal AudioEndpointVolumeChannel(IAudioEndpointVolume parent, int channel) { this.channel = (uint)channel; audioEndpointVolume = parent; } } public class AudioEndpointVolumeChannels { private readonly IAudioEndpointVolume audioEndPointVolume; private readonly AudioEndpointVolumeChannel[] channels; public int Count { get { Marshal.ThrowExceptionForHR(audioEndPointVolume.GetChannelCount(out var pnChannelCount)); return pnChannelCount; } } public AudioEndpointVolumeChannel this[int index] => channels[index]; internal AudioEndpointVolumeChannels(IAudioEndpointVolume parent) { audioEndPointVolume = parent; int count = Count; channels = new AudioEndpointVolumeChannel[count]; for (int i = 0; i < count; i++) { channels[i] = new AudioEndpointVolumeChannel(audioEndPointVolume, i); } } } public delegate void AudioEndpointVolumeNotificationDelegate(AudioVolumeNotificationData data); public class AudioEndpointVolumeStepInformation { private readonly uint step; private readonly uint stepCount; public uint Step => step; public uint StepCount => stepCount; internal AudioEndpointVolumeStepInformation(IAudioEndpointVolume parent) { Marshal.ThrowExceptionForHR(parent.GetVolumeStepInfo(out step, out stepCount)); } } public class AudioEndpointVolumeVolumeRange { private readonly float volumeMinDecibels; private readonly float volumeMaxDecibels; private readonly float volumeIncrementDecibels; public float MinDecibels => volumeMinDecibels; public float MaxDecibels => volumeMaxDecibels; public float IncrementDecibels => volumeIncrementDecibels; internal AudioEndpointVolumeVolumeRange(IAudioEndpointVolume parent) { Marshal.ThrowExceptionForHR(parent.GetVolumeRange(out volumeMinDecibels, out volumeMaxDecibels, out volumeIncrementDecibels)); } } public class AudioMeterInformation { private readonly IAudioMeterInformation audioMeterInformation; public AudioMeterInformationChannels PeakValues { get; } public EEndpointHardwareSupport HardwareSupport { get; } public float MasterPeakValue { get { Marshal.ThrowExceptionForHR(audioMeterInformation.GetPeakValue(out var pfPeak)); return pfPeak; } } internal AudioMeterInformation(IAudioMeterInformation realInterface) { audioMeterInformation = realInterface; Marshal.ThrowExceptionForHR(audioMeterInformation.QueryHardwareSupport(out var pdwHardwareSupportMask)); HardwareSupport = (EEndpointHardwareSupport)pdwHardwareSupportMask; PeakValues = new AudioMeterInformationChannels(audioMeterInformation); } } public class AudioMeterInformationChannels { private readonly IAudioMeterInformation audioMeterInformation; public int Count { get { Marshal.ThrowExceptionForHR(audioMeterInformation.GetMeteringChannelCount(out var pnChannelCount)); return pnChannelCount; } } public float this[int index] { get { int count = Count; if (index >= count) { throw new ArgumentOutOfRangeException("index", $"Peak index cannot be greater than number of channels ({count})"); } float[] array = new float[Count]; GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned); Marshal.ThrowExceptionForHR(audioMeterInformation.GetChannelsPeakValues(array.Length, gCHandle.AddrOfPinnedObject())); gCHandle.Free(); return array[index]; } } internal AudioMeterInformationChannels(IAudioMeterInformation parent) { audioMeterInformation = parent; } } public class AudioMute { private IAudioMute audioMuteInterface; public bool IsMuted { get { audioMuteInterface.GetMute(out var mute); return mute; } set { Guid empty = Guid.Empty; IAudioMute audioMute = audioMuteInterface; Guid eventContext = empty; audioMute.SetMute(value, ref eventContext); } } internal AudioMute(IAudioMute audioMute) { audioMuteInterface = audioMute; } } public class AudioRenderClient : IDisposable { private IAudioRenderClient audioRenderClientInterface; internal AudioRenderClient(IAudioRenderClient audioRenderClientInterface) { this.audioRenderClientInterface = audioRenderClientInterface; } public IntPtr GetBuffer(int numFramesRequested) { Marshal.ThrowExceptionForHR(audioRenderClientInterface.GetBuffer(numFramesRequested, out var dataBufferPointer)); return dataBufferPointer; } public void ReleaseBuffer(int numFramesWritten, AudioClientBufferFlags bufferFlags) { Marshal.ThrowExceptionForHR(audioRenderClientInterface.ReleaseBuffer(numFramesWritten, bufferFlags)); } public void Dispose() { if (audioRenderClientInterface != null) { Marshal.ReleaseComObject(audioRenderClientInterface); audioRenderClientInterface = null; GC.SuppressFinalize(this); } } } public class AudioSessionControl : IDisposable { private readonly IAudioSessionControl audioSessionControlInterface; private readonly IAudioSessionControl2 audioSessionControlInterface2; private AudioSessionEventsCallback audioSessionEventCallback; public AudioMeterInformation AudioMeterInformation { get; } public SimpleAudioVolume SimpleAudioVolume { get; } public AudioSessionState State { get { Marshal.ThrowExceptionForHR(audioSessionControlInterface.GetState(out var state)); return state; } } public string DisplayName { get { Marshal.ThrowExceptionForHR(audioSessionControlInterface.GetDisplayName(out var displayName)); return displayName; } set { if (value != string.Empty) { Marshal.ThrowExceptionForHR(audioSessionControlInterface.SetDisplayName(value, Guid.Empty)); } } } public string IconPath { get { Marshal.ThrowExceptionForHR(audioSessionControlInterface.GetIconPath(out var iconPath)); return iconPath; } set { if (value != string.Empty) { Marshal.ThrowExceptionForHR(audioSessionControlInterface.SetIconPath(value, Guid.Empty)); } } } public string GetSessionIdentifier { get { if (audioSessionControlInterface2 == null) { throw new InvalidOperationException("Not supported on this version of Windows"); } Marshal.ThrowExceptionForHR(audioSessionControlInterface2.GetSessionIdentifier(out var retVal)); return retVal; } } public string GetSessionInstanceIdentifier { get { if (audioSessionControlInterface2 == null) { throw new InvalidOperationException("Not supported on this version of Windows"); } Marshal.ThrowExceptionForHR(audioSessionControlInterface2.GetSessionInstanceIdentifier(out var retVal)); return retVal; } } public uint GetProcessID { get { if (audioSessionControlInterface2 == null) { throw new InvalidOperationException("Not supported on this version of Windows"); } Marshal.ThrowExceptionForHR(audioSessionControlInterface2.GetProcessId(out var retVal)); return retVal; } } public bool IsSystemSoundsSession { get { if (audioSessionControlInterface2 == null) { throw new InvalidOperationException("Not supported on this version of Windows"); } return audioSessionControlInterface2.IsSystemSoundsSession() == 0; } } public AudioSessionControl(IAudioSessionControl audioSessionControl) { audioSessionControlInterface = audioSessionControl; audioSessionControlInterface2 = audioSessionControl as IAudioSessionControl2; if (audioSessionControlInterface is IAudioMeterInformation realInterface) { AudioMeterInformation = new AudioMeterInformation(realInterface); } if (audioSessionControlInterface is ISimpleAudioVolume realSimpleVolume) { SimpleAudioVolume = new SimpleAudioVolume(realSimpleVolume); } } public void Dispose() { if (audioSessionEventCallback != null) { Marshal.ThrowExceptionForHR(audioSessionControlInterface.UnregisterAudioSessionNotification(audioSessionEventCallback)); audioSessionEventCallback = null; } GC.SuppressFinalize(this); } ~AudioSessionControl() { Dispose(); } public Guid GetGroupingParam() { Marshal.ThrowExceptionForHR(audioSessionControlInterface.GetGroupingParam(out var groupingId)); return groupingId; } public void SetGroupingParam(Guid groupingId, Guid context) { Marshal.ThrowExceptionForHR(audioSessionControlInterface.SetGroupingParam(groupingId, context)); } public void RegisterEventClient(IAudioSessionEventsHandler eventClient) { audioSessionEventCallback = new AudioSessionEventsCallback(eventClient); Marshal.ThrowExceptionForHR(audioSessionControlInterface.RegisterAudioSessionNotification(audioSessionEventCallback)); } public void UnRegisterEventClient(IAudioSessionEventsHandler eventClient) { if (audioSessionEventCallback != null) { Marshal.ThrowExceptionForHR(audioSessionControlInterface.UnregisterAudioSessionNotification(audioSessionEventCallback)); audioSessionEventCallback = null; } } } public class AudioSessionEventsCallback : IAudioSessionEvents { private readonly IAudioSessionEventsHandler audioSessionEventsHandler; public AudioSessionEventsCallback(IAudioSessionEventsHandler handler) { audioSessionEventsHandler = handler; } public int OnDisplayNameChanged([In][MarshalAs(UnmanagedType.LPWStr)] string displayName, [In] ref Guid eventContext) { audioSessionEventsHandler.OnDisplayNameChanged(displayName); return 0; } public int OnIconPathChanged([In][MarshalAs(UnmanagedType.LPWStr)] string iconPath, [In] ref Guid eventContext) { audioSessionEventsHandler.OnIconPathChanged(iconPath); return 0; } public int OnSimpleVolumeChanged([In][MarshalAs(UnmanagedType.R4)] float volume, [In][MarshalAs(UnmanagedType.Bool)] bool isMuted, [In] ref Guid eventContext) { audioSessionEventsHandler.OnVolumeChanged(volume, isMuted); return 0; } public int OnChannelVolumeChanged([In][MarshalAs(UnmanagedType.U4)] uint channelCount, [In][MarshalAs(UnmanagedType.SysInt)] IntPtr newVolumes, [In][MarshalAs(UnmanagedType.U4)] uint channelIndex, [In] ref Guid eventContext) { audioSessionEventsHandler.OnChannelVolumeChanged(channelCount, newVolumes, channelIndex); return 0; } public int OnGroupingParamChanged([In] ref Guid groupingId, [In] ref Guid eventContext) { audioSessionEventsHandler.OnGroupingParamChanged(ref groupingId); return 0; } public int OnStateChanged([In] AudioSessionState state) { audioSessionEventsHandler.OnStateChanged(state); return 0; } public int OnSessionDisconnected([In] AudioSessionDisconnectReason disconnectReason) { audioSessionEventsHandler.OnSessionDisconnected(disconnectReason); return 0; } } public class AudioSessionManager { public delegate void SessionCreatedDelegate(object sender, IAudioSessionControl newSession); private readonly IAudioSessionManager audioSessionInterface; private readonly IAudioSessionManager2 audioSessionInterface2; private AudioSessionNotification audioSessionNotification; private SessionCollection sessions; private SimpleAudioVolume simpleAudioVolume; private AudioSessionControl audioSessionControl; public SimpleAudioVolume SimpleAudioVolume { get { if (simpleAudioVolume == null) { audioSessionInterface.GetSimpleAudioVolume(Guid.Empty, 0u, out var audioVolume); simpleAudioVolume = new SimpleAudioVolume(audioVolume); } return simpleAudioVolume; } } public AudioSessionControl AudioSessionControl { get { if (audioSessionControl == null) { audioSessionInterface.GetAudioSessionControl(Guid.Empty, 0u, out var sessionControl); audioSessionControl = new AudioSessionControl(sessionControl); } return audioSessionControl; } } public SessionCollection Sessions => sessions; public event SessionCreatedDelegate OnSessionCreated; internal AudioSessionManager(IAudioSessionManager audioSessionManager) { audioSessionInterface = audioSessionManager; audioSessionInterface2 = audioSessionManager as IAudioSessionManager2; RefreshSessions(); } internal void FireSessionCreated(IAudioSessionControl newSession) { this.OnSessionCreated?.Invoke(this, newSession); } public void RefreshSessions() { UnregisterNotifications(); if (audioSessionInterface2 != null) { Marshal.ThrowExceptionForHR(audioSessionInterface2.GetSessionEnumerator(out var sessionEnum)); sessions = new SessionCollection(sessionEnum); audioSessionNotification = new AudioSessionNotification(this); Marshal.ThrowExceptionForHR(audioSessionInterface2.RegisterSessionNotification(audioSessionNotification)); } } public void Dispose() { UnregisterNotifications(); GC.SuppressFinalize(this); } private void UnregisterNotifications() { sessions = null; if (audioSessionNotification != null && audioSessionInterface2 != null) { Marshal.ThrowExceptionForHR(audioSessionInterface2.UnregisterSessionNotification(audioSessionNotification)); audioSessionNotification = null; } } ~AudioSessionManager() { Dispose(); } } internal class AudioSessionNotification : IAudioSessionNotification { private AudioSessionManager parent; internal AudioSessionNotification(AudioSessionManager parent) { this.parent = parent; } [PreserveSig] public int OnSessionCreated(IAudioSessionControl newSession) { parent.FireSessionCreated(newSession); return 0; } } public enum AudioStreamCategory { Other, ForegroundOnlyMedia, BackgroundCapableMedia, Communications, Alerts, SoundEffects, GameEffects, GameMedia, GameChat, Speech, Movie, Media, FarFieldSpeech, UniformSpeech, VoiceTyping } public class AudioStreamVolume : IDisposable { private IAudioStreamVolume audioStreamVolumeInterface; public int ChannelCount { get { Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.GetChannelCount(out var dwCount)); return (int)dwCount; } } internal AudioStreamVolume(IAudioStreamVolume audioStreamVolumeInterface) { this.audioStreamVolumeInterface = audioStreamVolumeInterface; } private void CheckChannelIndex(int channelIndex, string parameter) { int channelCount = ChannelCount; if (channelIndex >= channelCount) { throw new ArgumentOutOfRangeException(parameter, "You must supply a valid channel index < current count of channels: " + channelCount); } } public float[] GetAllVolumes() { Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.GetChannelCount(out var dwCount)); float[] array = new float[dwCount]; Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.GetAllVolumes(dwCount, array)); return array; } public float GetChannelVolume(int channelIndex) { CheckChannelIndex(channelIndex, "channelIndex"); Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.GetChannelVolume((uint)channelIndex, out var fLevel)); return fLevel; } public void SetAllVolumes(float[] levels) { int channelCount = ChannelCount; if (levels == null) { throw new ArgumentNullException("levels"); } if (levels.Length != channelCount) { throw new ArgumentOutOfRangeException("levels", string.Format(CultureInfo.InvariantCulture, "SetAllVolumes MUST be supplied with a volume level for ALL channels. The AudioStream has {0} channels and you supplied {1} channels.", channelCount, levels.Length)); } for (int i = 0; i < levels.Length; i++) { float num = levels[i]; if (num < 0f) { throw new ArgumentOutOfRangeException("levels", "All volumes must be between 0.0 and 1.0. Invalid volume at index: " + i); } if (num > 1f) { throw new ArgumentOutOfRangeException("levels", "All volumes must be between 0.0 and 1.0. Invalid volume at index: " + i); } } Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.SetAllVoumes((uint)channelCount, levels)); } public void SetChannelVolume(int index, float level) { CheckChannelIndex(index, "index"); if (level < 0f) { throw new ArgumentOutOfRangeException("level", "Volume must be between 0.0 and 1.0"); } if (level > 1f) { throw new ArgumentOutOfRangeException("level", "Volume must be between 0.0 and 1.0"); } Marshal.ThrowExceptionForHR(audioStreamVolumeInterface.SetChannelVolume((uint)index, level)); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing && audioStreamVolumeInterface != null) { Marshal.ReleaseComObject(audioStreamVolumeInterface); audioStreamVolumeInterface = null; } } } public class AudioVolumeNotificationData { public Guid EventContext { get; } public bool Muted { get; } public Guid Guid { get; } public float MasterVolume { get; } public int Channels { get; } public float[] ChannelVolume { get; } public AudioVolumeNotificationData(Guid eventContext, bool muted, float masterVolume, float[] channelVolume, Guid guid) { EventContext = eventContext; Muted = muted; MasterVolume = masterVolume; Channels = channelVolume.Length; ChannelVolume = channelVolume; Guid = guid; } } public class Connector { private readonly IConnector connectorInterface; public ConnectorType Type { get { connectorInterface.GetType(out var type); return type; } } public DataFlow DataFlow { get { connectorInterface.GetDataFlow(out var flow); return flow; } } public bool IsConnected { get { connectorInterface.IsConnected(out var connected); return connected; } } public Connector ConnectedTo { get { connectorInterface.GetConnectedTo(out var conTo); return new Connector(conTo); } } public string ConnectedToConnectorId { get { connectorInterface.GetConnectorIdConnectedTo(out var id); return id; } } public string ConnectedToDeviceId { get { connectorInterface.GetDeviceIdConnectedTo(out var id); return id; } } public Part Part => new Part(connectorInterface as IPart); internal Connector(IConnector connector) { connectorInterface = connector; } public void ConnectTo(Connector other) { connectorInterface.ConnectTo(other.connectorInterface); } public void Disconnect() { connectorInterface.Disconnect(); } } public enum ConnectorType { UnknownConnector, PhysicalInternal, PhysicalExternal, SoftwareIo, SoftwareFixed, Network } public enum DataFlow { Render, Capture, All } [Flags] public enum DeviceState { Active = 1, Disabled = 2, NotPresent = 4, Unplugged = 8, All = 0xF } public class DeviceTopology { private readonly IDeviceTopology deviceTopologyInterface; public uint ConnectorCount { get { deviceTopologyInterface.GetConnectorCount(out var count); return count; } } public string DeviceId { get { deviceTopologyInterface.GetDeviceId(out var id); return id; } } internal DeviceTopology(IDeviceTopology deviceTopology) { deviceTopologyInterface = deviceTopology; } public Connector GetConnector(uint index) { deviceTopologyInterface.GetConnector(index, out var connector); return new Connector(connector); } } [Flags] public enum EEndpointHardwareSupport { Volume = 1, Mute = 2, Meter = 4 } public class KsJackDescription { private readonly IKsJackDescription ksJackDescriptionInterface; public uint Count { get { ksJackDescriptionInterface.GetJackCount(out var jacks); return jacks; } } public string this[uint index] { get { ksJackDescriptionInterface.GetJackDescription(index, out var description); return description; } } internal KsJackDescription(IKsJackDescription ksJackDescription) { ksJackDescriptionInterface = ksJackDescription; } } public class MMDevice : IDisposable { private readonly IMMDevice deviceInterface; private PropertyStore propertyStore; private AudioMeterInformation audioMeterInformation; private AudioEndpointVolume audioEndpointVolume; private AudioSessionManager audioSessionManager; private DeviceTopology deviceTopology; private static readonly Guid IID_IAudioMeterInformation = new Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064"); private static readonly Guid IID_IAudioEndpointVolume = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A"); private static readonly Guid IID_IAudioClient = new Guid("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2"); private static readonly Guid IDD_IAudioSessionManager = new Guid("BFA971F1-4D5E-40BB-935E-967039BFBEE4"); private static readonly Guid IDD_IDeviceTopology = new Guid("2A07407E-6497-4A18-9787-32F79BD0D98F"); public AudioClient AudioClient => GetAudioClient(); public AudioMeterInformation AudioMeterInformation { get { if (audioMeterInformation == null) { GetAudioMeterInformation(); } return audioMeterInformation; } } public AudioEndpointVolume AudioEndpointVolume { get { if (audioEndpointVolume == null) { GetAudioEndpointVolume(); } return audioEndpointVolume; } } public AudioSessionManager AudioSessionManager { get { if (audioSessionManager == null) { GetAudioSessionManager(); } return audioSessionManager; } } public DeviceTopology DeviceTopology { get { if (deviceTopology == null) { GetDeviceTopology(); } return deviceTopology; } } public PropertyStore Properties { get { EnsurePropertyStoreExists(); return propertyStore; } } public string FriendlyName { get { EnsurePropertyStoreExists(); if (!propertyStore.TryGetValue(PropertyKeys.PKEY_Device_FriendlyName, out var obj)) { return "Unknown"; } return obj; } } public string DeviceFriendlyName { get { EnsurePropertyStoreExists(); if (!propertyStore.TryGetValue(PropertyKeys.PKEY_DeviceInterface_FriendlyName, out var obj)) { return "Unknown"; } return obj; } } public string IconPath { get { EnsurePropertyStoreExists(); if (!propertyStore.TryGetValue(PropertyKeys.PKEY_Device_IconPath, out var obj)) { return "Unknown"; } return obj; } } public string InstanceId { get { EnsurePropertyStoreExists(); if (!propertyStore.TryGetValue(PropertyKeys.PKEY_Device_InstanceId, out var obj)) { return "Unknown"; } return obj; } } public string ID { get { Marshal.ThrowExceptionForHR(deviceInterface.GetId(out var id)); return id; } } public DataFlow DataFlow { get { (deviceInterface as IMMEndpoint).GetDataFlow(out var dataFlow); return dataFlow; } } public DeviceState State { get { Marshal.ThrowExceptionForHR(deviceInterface.GetState(out var state)); return state; } } public void GetPropertyInformation(StorageAccessMode stgmAccess = StorageAccessMode.Read) { Marshal.ThrowExceptionForHR(deviceInterface.OpenPropertyStore(stgmAccess, out var properties)); propertyStore = new PropertyStore(properties); } private AudioClient GetAudioClient() { Marshal.ThrowExceptionForHR(deviceInterface.Activate(in IID_IAudioClient, ClsCtx.ALL, IntPtr.Zero, out var interfacePointer)); return new AudioClient(interfacePointer as IAudioClient); } private void GetAudioMeterInformation() { Marshal.ThrowExceptionForHR(deviceInterface.Activate(in IID_IAudioMeterInformation, ClsCtx.ALL, IntPtr.Zero, out var interfacePointer)); audioMeterInformation = new AudioMeterInformation(interfacePointer as IAudioMeterInformation); } private void GetAudioEndpointVolume() { Marshal.ThrowExceptionForHR(deviceInterface.Activate(in IID_IAudioEndpointVolume, ClsCtx.ALL, IntPtr.Zero, out var interfacePointer)); audioEndpointVolume = new AudioEndpointVolume(interfacePointer as IAudioEndpointVolume); } private void GetAudioSessionManager() { Marshal.ThrowExceptionForHR(deviceInterface.Activate(in IDD_IAudioSessionManager, ClsCtx.ALL, IntPtr.Zero, out var interfacePointer)); audioSessionManager = new AudioSessionManager(interfacePointer as IAudioSessionManager); } private void GetDeviceTopology() { Marshal.ThrowExceptionForHR(deviceInterface.Activate(in IDD_IDeviceTopology, ClsCtx.ALL, IntPtr.Zero, out var interfacePointer)); deviceTopology = new DeviceTopology(interfacePointer as IDeviceTopology); } private void EnsurePropertyStoreExists() { if (propertyStore == null) { GetPropertyInformation(); } } internal MMDevice(IMMDevice realDevice) { deviceInterface = realDevice; } public override string ToString() { return FriendlyName; } public void Dispose() { audioEndpointVolume?.Dispose(); audioSessionManager?.Dispose(); GC.SuppressFinalize(this); } ~MMDevice() { Dispose(); } } public class MMDeviceCollection : IEnumerable, IEnumerable { [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MMDevice <>2__current; public MMDeviceCollection <>4__this; private int 5__2; MMDevice IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; MMDeviceCollection mMDeviceCollection = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } if (5__2 < mMDeviceCollection.Count) { <>2__current = mMDeviceCollection[5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly IMMDeviceCollection mmDeviceCollection; public int Count { get { Marshal.ThrowExceptionForHR(mmDeviceCollection.GetCount(out var numDevices)); return numDevices; } } public MMDevice this[int index] { get { mmDeviceCollection.Item(index, out var device); return new MMDevice(device); } } internal MMDeviceCollection(IMMDeviceCollection parent) { mmDeviceCollection = parent; } [IteratorStateMachine(typeof(d__6))] public IEnumerator GetEnumerator() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { <>4__this = this }; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class MMDeviceEnumerator : IDisposable { private IMMDeviceEnumerator realEnumerator; public MMDeviceEnumerator() { if (Environment.OSVersion.Version.Major < 6) { throw new NotSupportedException("This functionality is only supported on Windows Vista or newer."); } realEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; } public MMDeviceCollection EnumerateAudioEndPoints(DataFlow dataFlow, DeviceState dwStateMask) { Marshal.ThrowExceptionForHR(realEnumerator.EnumAudioEndpoints(dataFlow, dwStateMask, out var devices)); return new MMDeviceCollection(devices); } public MMDevice GetDefaultAudioEndpoint(DataFlow dataFlow, Role role) { Marshal.ThrowExceptionForHR(realEnumerator.GetDefaultAudioEndpoint(dataFlow, role, out var endpoint)); return new MMDevice(endpoint); } public bool HasDefaultAudioEndpoint(DataFlow dataFlow, Role role) { IMMDevice endpoint; int defaultAudioEndpoint = realEnumerator.GetDefaultAudioEndpoint(dataFlow, role, out endpoint); switch (defaultAudioEndpoint) { case 0: Marshal.ReleaseComObject(endpoint); return true; case -2147023728: return false; default: Marshal.ThrowExceptionForHR(defaultAudioEndpoint); return false; } } public MMDevice GetDevice(string id) { Marshal.ThrowExceptionForHR(realEnumerator.GetDevice(id, out var deviceName)); return new MMDevice(deviceName); } public int RegisterEndpointNotificationCallback([In][MarshalAs(UnmanagedType.Interface)] IMMNotificationClient client) { return realEnumerator.RegisterEndpointNotificationCallback(client); } public int UnregisterEndpointNotificationCallback([In][MarshalAs(UnmanagedType.Interface)] IMMNotificationClient client) { return realEnumerator.UnregisterEndpointNotificationCallback(client); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing && realEnumerator != null) { Marshal.ReleaseComObject(realEnumerator); realEnumerator = null; } } } public class Part { private const int E_NOTFOUND = -2147023728; private readonly IPart partInterface; private DeviceTopology deviceTopology; private static Guid IID_IAudioVolumeLevel = new Guid("7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC"); private static Guid IID_IAudioMute = new Guid("DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E"); private static Guid IID_IAudioEndpointVolume = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A"); private static Guid IID_IKsJackDescription = new Guid("4509F757-2D46-4637-8E62-CE7DB944F57B"); public string Name { get { partInterface.GetName(out var name); return name; } } public uint LocalId { get { partInterface.GetLocalId(out var id); return id; } } public string GlobalId { get { partInterface.GetGlobalId(out var id); return id; } } public PartTypeEnum PartType { get { partInterface.GetPartType(out var partType); return partType; } } public Guid GetSubType { get { partInterface.GetSubType(out var subType); return subType; } } public uint ControlInterfaceCount { get { partInterface.GetControlInterfaceCount(out var count); return count; } } public PartsList PartsIncoming { get { IPartsList parts; int num = partInterface.EnumPartsIncoming(out parts); return num switch { -2147023728 => new PartsList(null), 0 => new PartsList(parts), _ => throw new COMException("EnumPartsIncoming", num), }; } } public PartsList PartsOutgoing { get { IPartsList parts; int num = partInterface.EnumPartsOutgoing(out parts); return num switch { -2147023728 => new PartsList(null), 0 => new PartsList(parts), _ => throw new COMException("EnumPartsOutgoing", num), }; } } public DeviceTopology DeviceTopology { get { if (deviceTopology == null) { GetDeviceTopology(); } return deviceTopology; } } public AudioVolumeLevel AudioVolumeLevel { get { if (partInterface.Activate(ClsCtx.ALL, ref IID_IAudioVolumeLevel, out var interfacePointer) != 0) { return null; } return new AudioVolumeLevel(interfacePointer as IAudioVolumeLevel); } } public AudioMute AudioMute { get { if (partInterface.Activate(ClsCtx.ALL, ref IID_IAudioMute, out var interfacePointer) != 0) { return null; } return new AudioMute(interfacePointer as IAudioMute); } } public KsJackDescription JackDescription { get { if (partInterface.Activate(ClsCtx.ALL, ref IID_IKsJackDescription, out var interfacePointer) != 0) { return null; } return new KsJackDescription(interfacePointer as IKsJackDescription); } } internal Part(IPart part) { partInterface = part; } public IControlInterface GetControlInterface(uint index) { partInterface.GetControlInterface(index, out var controlInterface); return controlInterface; } private void GetDeviceTopology() { Marshal.ThrowExceptionForHR(partInterface.GetTopologyObject(out var topologyObject)); deviceTopology = new DeviceTopology(topologyObject as IDeviceTopology); } } public class PartsList { private IPartsList partsListInterface; public uint Count { get { uint count = 0u; if (partsListInterface != null) { partsListInterface.GetCount(out count); } return count; } } public Part this[uint index] { get { if (partsListInterface == null) { throw new IndexOutOfRangeException(); } partsListInterface.GetPart(index, out var part); return new Part(part); } } internal PartsList(IPartsList partsList) { partsListInterface = partsList; } } public struct PropertyKey { public Guid formatId; public int propertyId; public PropertyKey(Guid formatId, int propertyId) { this.formatId = formatId; this.propertyId = propertyId; } } public static class PropertyKeys { public static readonly PropertyKey PKEY_DeviceInterface_FriendlyName = new PropertyKey(new Guid(40784238, -18412, 16715, 131, 205, 133, 109, 111, 239, 72, 34), 2); public static readonly PropertyKey PKEY_AudioEndpoint_FormFactor = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 0); public static readonly PropertyKey PKEY_AudioEndpoint_ControlPanelPageProvider = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 1); public static readonly PropertyKey PKEY_AudioEndpoint_Association = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 2); public static readonly PropertyKey PKEY_AudioEndpoint_PhysicalSpeakers = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 3); public static readonly PropertyKey PKEY_AudioEndpoint_GUID = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 4); public static readonly PropertyKey PKEY_AudioEndpoint_Disable_SysFx = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 5); public static readonly PropertyKey PKEY_AudioEndpoint_FullRangeSpeakers = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 6); public static readonly PropertyKey PKEY_AudioEndpoint_Supports_EventDriven_Mode = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 7); public static readonly PropertyKey PKEY_AudioEndpoint_JackSubType = new PropertyKey(new Guid(497408003, -11118, 20189, 140, 35, 224, 192, byte.MaxValue, 238, 127, 14), 8); public static readonly PropertyKey PKEY_AudioEngine_DeviceFormat = new PropertyKey(new Guid(-241236403, 2092, 20007, 188, 115, 104, 130, 161, 187, 142, 76), 0); public static readonly PropertyKey PKEY_AudioEngine_OEMFormat = new PropertyKey(new Guid(-460911066, 15557, 19666, 186, 70, 202, 10, 154, 112, 237, 4), 3); public static readonly PropertyKey PKEY_Device_FriendlyName = new PropertyKey(new Guid(-1537465010, -8420, 20221, 128, 32, 103, 209, 70, 168, 80, 224), 14); public static readonly PropertyKey PKEY_Device_IconPath = new PropertyKey(new Guid(630898684, 20647, 18382, 175, 8, 104, 201, 167, 215, 51, 102), 12); public static readonly PropertyKey PKEY_Device_DeviceDesc = new PropertyKey(new Guid(-1537465010, -8420, 20221, 128, 32, 103, 209, 70, 168, 80, 224), 2); public static readonly PropertyKey PKEY_Device_ControllerDeviceId = new PropertyKey(new Guid(-1275528621, 4, 17294, 144, 3, 81, 164, 110, 19, 155, 252), 2); public static readonly PropertyKey PKEY_Device_InterfaceKey = new PropertyKey(new Guid(590439624, 6956, 19581, 188, 104, 182, 113, 104, 122, 37, 103), 1); public static readonly PropertyKey PKEY_Device_InstanceId = new PropertyKey(new Guid(2026065864, 4170, 19146, 158, 164, 82, 77, 82, 153, 110, 87), 256); } public class PropertyStore { private readonly IPropertyStore storeInterface; public int Count { get { Marshal.ThrowExceptionForHR(storeInterface.GetCount(out var propCount)); return propCount; } } public PropertyStoreProperty this[int index] { get { PropertyKey key = Get(index); Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out var value)); return new PropertyStoreProperty(key, value); } } public PropertyStoreProperty this[PropertyKey key] { get { Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out var value)); return new PropertyStoreProperty(key, value); } } public bool Contains(PropertyKey key) { if (storeInterface.GetValue(ref key, out var value) >= 0) { return value.vt != 0; } return false; } public bool TryGetValue(PropertyKey key, out T obj) { obj = default(T); if (storeInterface.GetValue(ref key, out var value) < 0 || value.vt == 0) { return false; } obj = (T)value.Value; return true; } public PropertyKey Get(int index) { Marshal.ThrowExceptionForHR(storeInterface.GetAt(index, out var key)); return key; } public PropVariant GetValue(int index) { PropertyKey key = Get(index); Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out var value)); return value; } public void SetValue(PropertyKey key, PropVariant value) { Marshal.ThrowExceptionForHR(storeInterface.SetValue(ref key, ref value)); } public void Commit() { Marshal.ThrowExceptionForHR(storeInterface.Commit()); } internal PropertyStore(IPropertyStore store) { storeInterface = store; } } public struct PropertyStoreProperty { private PropVariant propertyValue; public PropertyKey Key { get; } public object Value => propertyValue.Value; internal PropertyStoreProperty(PropertyKey key, PropVariant value) { Key = key; propertyValue = value; } } public enum Role { Console, Multimedia, Communications } public class SessionCollection { private readonly IAudioSessionEnumerator audioSessionEnumerator; public AudioSessionControl this[int index] { get { Marshal.ThrowExceptionForHR(audioSessionEnumerator.GetSession(index, out var session)); return new AudioSessionControl(session); } } public int Count { get { Marshal.ThrowExceptionForHR(audioSessionEnumerator.GetCount(out var sessionCount)); return sessionCount; } } internal SessionCollection(IAudioSessionEnumerator realEnumerator) { audioSessionEnumerator = realEnumerator; } } public class SimpleAudioVolume : IDisposable { private readonly ISimpleAudioVolume simpleAudioVolume; public float Volume { get { Marshal.ThrowExceptionForHR(simpleAudioVolume.GetMasterVolume(out var levelNorm)); return levelNorm; } set { if ((double)value >= 0.0 && (double)value <= 1.0) { Marshal.ThrowExceptionForHR(simpleAudioVolume.SetMasterVolume(value, Guid.Empty)); } } } public bool Mute { get { Marshal.ThrowExceptionForHR(simpleAudioVolume.GetMute(out var isMuted)); return isMuted; } set { Marshal.ThrowExceptionForHR(simpleAudioVolume.SetMute(value, Guid.Empty)); } } internal SimpleAudioVolume(ISimpleAudioVolume realSimpleVolume) { simpleAudioVolume = realSimpleVolume; } public void Dispose() { GC.SuppressFinalize(this); } ~SimpleAudioVolume() { Dispose(); } } public class WasapiCapture : IWaveIn, IDisposable { private const long ReftimesPerSec = 10000000L; private const long ReftimesPerMillisec = 10000L; private volatile CaptureState captureState; private byte[] recordBuffer; private Thread captureThread; private AudioClient audioClient; private int bytesPerFrame; private WaveFormat waveFormat; private bool initialized; private readonly SynchronizationContext syncContext; private readonly bool isUsingEventSync; private EventWaitHandle frameEventWaitHandle; private readonly int audioBufferMillisecondsLength; public AudioClientShareMode ShareMode { get; set; } public CaptureState CaptureState => captureState; public virtual WaveFormat WaveFormat { get { return WaveExtensionMethods.AsStandardWaveFormat(waveFormat); } set { waveFormat = value; } } public event EventHandler DataAvailable; public event EventHandler RecordingStopped; public WasapiCapture() : this(GetDefaultCaptureDevice()) { } public WasapiCapture(MMDevice captureDevice) : this(captureDevice, useEventSync: false) { } public WasapiCapture(MMDevice captureDevice, bool useEventSync) : this(captureDevice, useEventSync, 100) { } public WasapiCapture(MMDevice captureDevice, bool useEventSync, int audioBufferMillisecondsLength) { syncContext = SynchronizationContext.Current; audioClient = captureDevice.AudioClient; ShareMode = AudioClientShareMode.Shared; isUsingEventSync = useEventSync; this.audioBufferMillisecondsLength = audioBufferMillisecondsLength; waveFormat = audioClient.MixFormat; } public static MMDevice GetDefaultCaptureDevice() { return new MMDeviceEnumerator().GetDefaultAudioEndpoint(DataFlow.Capture, Role.Console); } private void InitializeCaptureDevice() { if (initialized) { return; } long num = 10000L * (long)audioBufferMillisecondsLength; if (ShareMode == AudioClientShareMode.Exclusive && !audioClient.IsFormatSupported(ShareMode, waveFormat)) { throw new ArgumentException("Unsupported Wave Format"); } AudioClientStreamFlags audioClientStreamFlags = GetAudioClientStreamFlags(); if (isUsingEventSync) { if (ShareMode == AudioClientShareMode.Shared) { audioClient.Initialize(ShareMode, AudioClientStreamFlags.EventCallback | audioClientStreamFlags, num, 0L, waveFormat, Guid.Empty); } else { audioClient.Initialize(ShareMode, AudioClientStreamFlags.EventCallback | audioClientStreamFlags, num, num, waveFormat, Guid.Empty); } frameEventWaitHandle = new EventWaitHandle(initialState: false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { audioClient.Initialize(ShareMode, audioClientStreamFlags, num, 0L, waveFormat, Guid.Empty); } int bufferSize = audioClient.BufferSize; bytesPerFrame = waveFormat.Channels * waveFormat.BitsPerSample / 8; recordBuffer = new byte[bufferSize * bytesPerFrame]; initialized = true; } protected virtual AudioClientStreamFlags GetAudioClientStreamFlags() { if (ShareMode == AudioClientShareMode.Shared) { return AudioClientStreamFlags.SrcDefaultQuality | AudioClientStreamFlags.AutoConvertPcm; } return AudioClientStreamFlags.None; } public void StartRecording() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((int)captureState != 0) { throw new InvalidOperationException("Previous recording still in progress"); } captureState = (CaptureState)1; InitializeCaptureDevice(); captureThread = new Thread((ThreadStart)delegate { CaptureThread(audioClient); }) { IsBackground = true }; captureThread.Start(); } public void StopRecording() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((int)captureState != 0) { captureState = (CaptureState)3; } } private void CaptureThread(AudioClient client) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Exception e = null; try { DoRecording(client); } catch (Exception ex) { e = ex; } finally { client.Stop(); } captureThread = null; captureState = (CaptureState)0; RaiseRecordingStopped(e); } private void DoRecording(AudioClient client) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 int bufferSize = client.BufferSize; long num = (long)(10000000.0 * (double)bufferSize / (double)waveFormat.SampleRate); int millisecondsTimeout = (int)(num / 10000 / 2); int millisecondsTimeout2 = (int)(3 * num / 10000); AudioCaptureClient audioCaptureClient = client.AudioCaptureClient; client.Start(); if ((int)captureState == 1) { captureState = (CaptureState)2; } while ((int)captureState == 2) { if (isUsingEventSync) { frameEventWaitHandle.WaitOne(millisecondsTimeout2, exitContext: false); } else { Thread.Sleep(millisecondsTimeout); } if ((int)captureState == 2) { ReadNextPacket(audioCaptureClient); continue; } break; } } private void RaiseRecordingStopped(Exception e) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown EventHandler handler = this.RecordingStopped; if (handler == null) { return; } if (syncContext == null) { handler(this, new StoppedEventArgs(e)); return; } syncContext.Post(delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown handler(this, new StoppedEventArgs(e)); }, null); } private void ReadNextPacket(AudioCaptureClient capture) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown int nextPacketSize = capture.GetNextPacketSize(); int num = 0; while (nextPacketSize != 0) { int numFramesToRead; AudioClientBufferFlags bufferFlags; IntPtr buffer = capture.GetBuffer(out numFramesToRead, out bufferFlags); int num2 = numFramesToRead * bytesPerFrame; if (Math.Max(0, recordBuffer.Length - num) < num2 && num > 0) { this.DataAvailable?.Invoke(this, new WaveInEventArgs(recordBuffer, num)); num = 0; } if ((bufferFlags & AudioClientBufferFlags.Silent) != AudioClientBufferFlags.Silent) { Marshal.Copy(buffer, recordBuffer, num, num2); } else { Array.Clear(recordBuffer, num, num2); } num += num2; capture.ReleaseBuffer(numFramesToRead); nextPacketSize = capture.GetNextPacketSize(); } this.DataAvailable?.Invoke(this, new WaveInEventArgs(recordBuffer, num)); } public void Dispose() { StopRecording(); if (captureThread != null) { captureThread.Join(); captureThread = null; } if (audioClient != null) { audioClient.Dispose(); audioClient = null; } } } } namespace NAudio.CoreAudioApi.Interfaces { internal struct AudioVolumeNotificationDataStruct { public Guid guidEventContext; public bool bMuted; public float fMasterVolume; public uint nChannels; public float ChannelVolume; } public struct Blob { public int Length; public IntPtr Data; } [Flags] internal enum ClsCtx { INPROC_SERVER = 1, INPROC_HANDLER = 2, LOCAL_SERVER = 4, INPROC_SERVER16 = 8, REMOTE_SERVER = 0x10, INPROC_HANDLER16 = 0x20, NO_CODE_DOWNLOAD = 0x400, NO_CUSTOM_MARSHAL = 0x1000, ENABLE_CODE_DOWNLOAD = 0x2000, NO_FAILURE_LOG = 0x4000, DISABLE_AAA = 0x8000, ENABLE_AAA = 0x10000, FROM_DEFAULT_CONTEXT = 0x20000, ACTIVATE_32_BIT_SERVER = 0x40000, ACTIVATE_64_BIT_SERVER = 0x80000, ENABLE_CLOAKING = 0x100000, PS_DLL = int.MinValue, INPROC = 3, SERVER = 0x15, ALL = 0x17 } public static class AudioClientErrorCode { public const int NotInitialized = -2004287487; public const int AlreadyInitialized = -2004287486; public const int WrongEndpointType = -2004287485; public const int DeviceInvalidated = -2004287484; public const int NotStopped = -2004287483; public const int BufferTooLarge = -2004287482; public const int OutOfOrder = -2004287481; public const int UnsupportedFormat = -2004287480; public const int InvalidSize = -2004287479; public const int DeviceInUse = -2004287478; public const int BufferOperationPending = -2004287477; public const int ThreadNotRegistered = -2004287476; public const int NoSingleProcess = -2004287475; public const int ExclusiveModeNotAllowed = -2004287474; public const int EndpointCreateFailed = -2004287473; public const int ServiceNotRunning = -2004287472; public const int EventHandleNotExpected = -2004287471; public const int ExclusiveModeOnly = -2004287470; public const int BufferDurationPeriodNotEqual = -2004287469; public const int EventHandleNotSet = -2004287468; public const int IncorrectBufferSize = -2004287467; public const int BufferSizeError = -2004287466; public const int CpuUsageExceeded = -2004287465; public const int BufferError = -2004287464; public const int BufferSizeNotAligned = -2004287463; public const int InvalidDevicePeriod = -2004287456; public const int InvalidStreamFlag = -2004287455; public const int EndpointOffloadNotCapable = -2004287454; public const int OutOfOffloadResources = -2004287453; public const int OffloadModeOnly = -2004287452; public const int NonOffloadModeOnly = -2004287451; public const int ResourcesInvalidated = -2004287450; public const int RawModeUnsupported = -2004287449; public const int EnginePeriodicityLocked = -2004287448; public const int EngineFormatLocked = -2004287447; public const int HeadTrackingEnabled = -2004287440; public const int HeadTrackingUnsupported = -2004287424; } [ComImport] [Guid("85401FD4-6DE4-4b9d-9869-2D6753A82F3C")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioAutoGainControl { [PreserveSig] int GetEnabled([MarshalAs(UnmanagedType.Bool)] out bool enabled); [PreserveSig] int SetEnabled([In][MarshalAs(UnmanagedType.Bool)] bool enabled); } [ComImport] [Guid("C8ADBD64-E71E-48a0-A4DE-185C395CD317")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioCaptureClient { int GetBuffer(out IntPtr dataBuffer, out int numFramesToRead, out AudioClientBufferFlags bufferFlags, out long devicePosition, out long qpcPosition); int ReleaseBuffer(int numFramesRead); int GetNextPacketSize(out int numFramesInNextPacket); } [ComImport] [Guid("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioClient { [PreserveSig] int Initialize(AudioClientShareMode shareMode, AudioClientStreamFlags streamFlags, long hnsBufferDuration, long hnsPeriodicity, [In] WaveFormat pFormat, [In] ref Guid audioSessionGuid); int GetBufferSize(out uint bufferSize); [return: MarshalAs(UnmanagedType.I8)] long GetStreamLatency(); int GetCurrentPadding(out int currentPadding); [PreserveSig] int IsFormatSupported(AudioClientShareMode shareMode, [In] WaveFormat pFormat, IntPtr closestMatchFormat); int GetMixFormat(out IntPtr deviceFormatPointer); int GetDevicePeriod(out long defaultDevicePeriod, out long minimumDevicePeriod); int Start(); int Stop(); int Reset(); int SetEventHandle(IntPtr eventHandle); [PreserveSig] int GetService([In][MarshalAs(UnmanagedType.LPStruct)] Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("726778CD-F60A-4eda-82DE-E47610CD78AA")] public interface IAudioClient2 : IAudioClient { void IsOffloadCapable(AudioStreamCategory category, out bool pbOffloadCapable); void SetClientProperties([In] IntPtr pProperties); void GetBufferSizeLimits(IntPtr pFormat, bool bEventDriven, out long phnsMinBufferDuration, out long phnsMaxBufferDuration); } [ComImport] [Guid("CD63314F-3FBA-4a1b-812C-EF96358728E7")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioClock { [PreserveSig] int GetFrequency(out ulong frequency); [PreserveSig] int GetPosition(out ulong devicePosition, out ulong qpcPosition); [PreserveSig] int GetCharacteristics(out uint characteristics); } [ComImport] [Guid("6f49ff73-6727-49AC-A008-D98CF5E70048")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioClock2 : IAudioClock { [PreserveSig] int GetDevicePosition(out ulong devicePosition, out ulong qpcPosition); } [ComImport] [Guid("5CDF2C82-841E-4546-9722-0CF74078229A")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioEndpointVolume { int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify); int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify); int GetChannelCount(out int pnChannelCount); int SetMasterVolumeLevel(float fLevelDB, ref Guid pguidEventContext); int SetMasterVolumeLevelScalar(float fLevel, ref Guid pguidEventContext); int GetMasterVolumeLevel(out float pfLevelDB); int GetMasterVolumeLevelScalar(out float pfLevel); int SetChannelVolumeLevel(uint nChannel, float fLevelDB, ref Guid pguidEventContext); int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, ref Guid pguidEventContext); int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB); int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel); int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, ref Guid pguidEventContext); int GetMute(out bool pbMute); int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount); int VolumeStepUp(ref Guid pguidEventContext); int VolumeStepDown(ref Guid pguidEventContext); int QueryHardwareSupport(out uint pdwHardwareSupportMask); int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB); } [ComImport] [Guid("657804FA-D6AD-4496-8A60-352752AF4F89")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioEndpointVolumeCallback { void OnNotify(IntPtr notifyData); } [ComImport] [Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioMeterInformation { int GetPeakValue(out float pfPeak); int GetMeteringChannelCount(out int pnChannelCount); int GetChannelsPeakValues(int u32ChannelCount, [In] IntPtr afPeakValues); int QueryHardwareSupport(out int pdwHardwareSupportMask); } [ComImport] [Guid("DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioMute { [PreserveSig] int GetMute([MarshalAs(UnmanagedType.Bool)] out bool mute); [PreserveSig] int SetMute([In][MarshalAs(UnmanagedType.Bool)] bool mute, [In] ref Guid eventContext); } [ComImport] [Guid("F294ACFC-3146-4483-A7BF-ADDCA7C260E2")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioRenderClient { int GetBuffer(int numFramesRequested, out IntPtr dataBufferPointer); int ReleaseBuffer(int numFramesWritten, AudioClientBufferFlags bufferFlags); } [ComImport] [Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionControl { [PreserveSig] int GetState(out AudioSessionState state); [PreserveSig] int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string displayName); [PreserveSig] int SetDisplayName([In][MarshalAs(UnmanagedType.LPWStr)] string displayName, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string iconPath); [PreserveSig] int SetIconPath([In][MarshalAs(UnmanagedType.LPWStr)] string iconPath, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] int GetGroupingParam(out Guid groupingId); [PreserveSig] int SetGroupingParam([In][MarshalAs(UnmanagedType.LPStruct)] Guid groupingId, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] int RegisterAudioSessionNotification([In] IAudioSessionEvents client); [PreserveSig] int UnregisterAudioSessionNotification([In] IAudioSessionEvents client); } [ComImport] [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionControl2 : IAudioSessionControl { [PreserveSig] new int GetState(out AudioSessionState state); [PreserveSig] new int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string displayName); [PreserveSig] new int SetDisplayName([In][MarshalAs(UnmanagedType.LPWStr)] string displayName, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] new int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string iconPath); [PreserveSig] new int SetIconPath([In][MarshalAs(UnmanagedType.LPWStr)] string iconPath, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] new int GetGroupingParam(out Guid groupingId); [PreserveSig] new int SetGroupingParam([In][MarshalAs(UnmanagedType.LPStruct)] Guid groupingId, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] new int RegisterAudioSessionNotification([In] IAudioSessionEvents client); [PreserveSig] new int UnregisterAudioSessionNotification([In] IAudioSessionEvents client); [PreserveSig] int GetSessionIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string retVal); [PreserveSig] int GetSessionInstanceIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string retVal); [PreserveSig] int GetProcessId(out uint retVal); [PreserveSig] int IsSystemSoundsSession(); [PreserveSig] int SetDuckingPreference(bool optOut); } [ComImport] [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioSessionEnumerator { int GetCount(out int sessionCount); int GetSession(int sessionCount, out IAudioSessionControl session); } public enum AudioSessionState { AudioSessionStateInactive, AudioSessionStateActive, AudioSessionStateExpired } public enum AudioSessionDisconnectReason { DisconnectReasonDeviceRemoval, DisconnectReasonServerShutdown, DisconnectReasonFormatChanged, DisconnectReasonSessionLogoff, DisconnectReasonSessionDisconnected, DisconnectReasonExclusiveModeOverride } [ComImport] [Guid("24918ACC-64B3-37C1-8CA9-74A66E9957A8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionEvents { [PreserveSig] int OnDisplayNameChanged([In][MarshalAs(UnmanagedType.LPWStr)] string displayName, [In] ref Guid eventContext); [PreserveSig] int OnIconPathChanged([In][MarshalAs(UnmanagedType.LPWStr)] string iconPath, [In] ref Guid eventContext); [PreserveSig] int OnSimpleVolumeChanged([In][MarshalAs(UnmanagedType.R4)] float volume, [In][MarshalAs(UnmanagedType.Bool)] bool isMuted, [In] ref Guid eventContext); [PreserveSig] int OnChannelVolumeChanged([In][MarshalAs(UnmanagedType.U4)] uint channelCount, [In][MarshalAs(UnmanagedType.SysInt)] IntPtr newVolumes, [In][MarshalAs(UnmanagedType.U4)] uint channelIndex, [In] ref Guid eventContext); [PreserveSig] int OnGroupingParamChanged([In] ref Guid groupingId, [In] ref Guid eventContext); [PreserveSig] int OnStateChanged([In] AudioSessionState state); [PreserveSig] int OnSessionDisconnected([In] AudioSessionDisconnectReason disconnectReason); } public interface IAudioSessionEventsHandler { void OnVolumeChanged(float volume, bool isMuted); void OnDisplayNameChanged(string displayName); void OnIconPathChanged(string iconPath); void OnChannelVolumeChanged(uint channelCount, IntPtr newVolumes, uint channelIndex); void OnGroupingParamChanged(ref Guid groupingId); void OnStateChanged(AudioSessionState state); void OnSessionDisconnected(AudioSessionDisconnectReason disconnectReason); } [ComImport] [Guid("BFA971F1-4D5E-40BB-935E-967039BFBEE4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioSessionManager { [PreserveSig] int GetAudioSessionControl([Optional][In][MarshalAs(UnmanagedType.LPStruct)] Guid sessionId, [In][MarshalAs(UnmanagedType.U4)] uint streamFlags, [MarshalAs(UnmanagedType.Interface)] out IAudioSessionControl sessionControl); [PreserveSig] int GetSimpleAudioVolume([Optional][In][MarshalAs(UnmanagedType.LPStruct)] Guid sessionId, [In][MarshalAs(UnmanagedType.U4)] uint streamFlags, [MarshalAs(UnmanagedType.Interface)] out ISimpleAudioVolume audioVolume); } [ComImport] [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioSessionManager2 : IAudioSessionManager { [PreserveSig] new int GetAudioSessionControl([Optional][In][MarshalAs(UnmanagedType.LPStruct)] Guid sessionId, [In][MarshalAs(UnmanagedType.U4)] uint streamFlags, [MarshalAs(UnmanagedType.Interface)] out IAudioSessionControl sessionControl); [PreserveSig] new int GetSimpleAudioVolume([Optional][In][MarshalAs(UnmanagedType.LPStruct)] Guid sessionId, [In][MarshalAs(UnmanagedType.U4)] uint streamFlags, [MarshalAs(UnmanagedType.Interface)] out ISimpleAudioVolume audioVolume); [PreserveSig] int GetSessionEnumerator(out IAudioSessionEnumerator sessionEnum); [PreserveSig] int RegisterSessionNotification(IAudioSessionNotification sessionNotification); [PreserveSig] int UnregisterSessionNotification(IAudioSessionNotification sessionNotification); [PreserveSig] int RegisterDuckNotification(string sessionId, IAudioSessionNotification audioVolumeDuckNotification); [PreserveSig] int UnregisterDuckNotification(IntPtr audioVolumeDuckNotification); } [ComImport] [Guid("641DD20B-4D41-49CC-ABA3-174B9477BB08")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionNotification { [PreserveSig] int OnSessionCreated(IAudioSessionControl newSession); } [ComImport] [Guid("93014887-242D-4068-8A15-CF5E93B90FE3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioStreamVolume { [PreserveSig] int GetChannelCount(out uint dwCount); [PreserveSig] int SetChannelVolume([In] uint dwIndex, [In] float fLevel); [PreserveSig] int GetChannelVolume([In] uint dwIndex, out float fLevel); [PreserveSig] int SetAllVoumes([In] uint dwCount, [In][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 0)] float[] fVolumes); [PreserveSig] int GetAllVolumes([In] uint dwCount, [MarshalAs(UnmanagedType.LPArray)] float[] pfVolumes); } [ComImport] [Guid("7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IAudioVolumeLevel : IPerChannelDbLevel { } [ComImport] [Guid("9C2C4058-23F5-41DE-877A-DF3AF236A09E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IConnector { int GetType(out ConnectorType type); int GetDataFlow(out DataFlow flow); int ConnectTo([In] IConnector connectTo); int Disconnect(); int IsConnected(out bool connected); int GetConnectedTo(out IConnector conTo); int GetConnectorIdConnectedTo([MarshalAs(UnmanagedType.LPWStr)] out string id); int GetDeviceIdConnectedTo([MarshalAs(UnmanagedType.LPWStr)] out string id); } [ComImport] [Guid("45d37c3f-5140-444a-ae24-400789f3cbf3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IControlInterface { } [ComImport] [Guid("2A07407E-6497-4A18-9787-32F79BD0D98F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDeviceTopology { int GetConnectorCount(out uint count); int GetConnector(uint index, out IConnector connector); int GetSubunitCount(out uint count); int GetSubunit(uint index, out ISubunit subunit); int GetPartById(uint id, out IPart part); int GetDeviceId([MarshalAs(UnmanagedType.LPWStr)] out string id); int GetSignalPath(IPart from, IPart to, bool rejectMixedPaths, out IPartsList parts); } [ComImport] [Guid("4509F757-2D46-4637-8E62-CE7DB944F57B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IKsJackDescription { int GetJackCount(out uint jacks); int GetJackDescription([In] uint jack, [MarshalAs(UnmanagedType.LPWStr)] out string description); } [ComImport] [Guid("D666063F-1587-4E43-81F1-B948E807363F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDevice { int Activate(in Guid id, ClsCtx clsCtx, IntPtr activationParams, [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer); int OpenPropertyStore(StorageAccessMode stgmAccess, out IPropertyStore properties); int GetId([MarshalAs(UnmanagedType.LPWStr)] out string id); int GetState(out DeviceState state); } [ComImport] [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDeviceCollection { int GetCount(out int numDevices); int Item(int deviceNumber, out IMMDevice device); } [ComImport] [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDeviceEnumerator { int EnumAudioEndpoints(DataFlow dataFlow, DeviceState stateMask, out IMMDeviceCollection devices); [PreserveSig] int GetDefaultAudioEndpoint(DataFlow dataFlow, Role role, out IMMDevice endpoint); int GetDevice(string id, out IMMDevice deviceName); int RegisterEndpointNotificationCallback(IMMNotificationClient client); int UnregisterEndpointNotificationCallback(IMMNotificationClient client); } [ComImport] [Guid("1BE09788-6894-4089-8586-9A2A6C265AC5")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMEndpoint { int GetDataFlow(out DataFlow dataFlow); } [ComImport] [Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMNotificationClient { void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] string deviceId, [MarshalAs(UnmanagedType.I4)] DeviceState newState); void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId); void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] string deviceId); void OnDefaultDeviceChanged(DataFlow flow, Role role, [MarshalAs(UnmanagedType.LPWStr)] string defaultDeviceId); void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId, PropertyKey key); } [ComImport] [Guid("AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPart { int GetName([MarshalAs(UnmanagedType.LPWStr)] out string name); int GetLocalId(out uint id); int GetGlobalId([MarshalAs(UnmanagedType.LPWStr)] out string id); int GetPartType(out PartTypeEnum partType); int GetSubType(out Guid subType); int GetControlInterfaceCount(out uint count); int GetControlInterface([In] uint index, [MarshalAs(UnmanagedType.IUnknown)] out IControlInterface controlInterface); [PreserveSig] int EnumPartsIncoming(out IPartsList parts); [PreserveSig] int EnumPartsOutgoing(out IPartsList parts); int GetTopologyObject(out object topologyObject); [PreserveSig] int Activate([In] ClsCtx dwClsContext, [In] ref Guid refiid, [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer); int RegisterControlChangeCallback([In] ref Guid refiid, [In] IControlChangeNotify notify); int UnregisterControlChangeCallback([In] IControlChangeNotify notify); } [ComImport] [Guid("6DAA848C-5EB0-45CC-AEA5-998A2CDA1FFB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPartsList { int GetCount(out uint count); int GetPart(uint index, out IPart part); } [ComImport] [Guid("7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPerChannelDbLevel { int GetChannelCount(out uint channels); int GetLevelRange(uint channel, out float minLevelDb, out float maxLevelDb, out float stepping); int GetLevel(uint channel, out float levelDb); int SetLevel(uint channel, float levelDb, ref Guid eventGuidContext); int SetLevelUniform(float levelDb, ref Guid eventGuidContext); int SetLevelAllChannel(float[] levelsDb, uint channels, ref Guid eventGuidContext); } [ComImport] [Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPropertyStore { int GetCount(out int propCount); int GetAt(int property, out PropertyKey key); int GetValue(ref PropertyKey key, out PropVariant value); int SetValue(ref PropertyKey key, ref PropVariant value); int Commit(); } [ComImport] [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISimpleAudioVolume { [PreserveSig] int SetMasterVolume([In][MarshalAs(UnmanagedType.R4)] float levelNorm, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] int GetMasterVolume([MarshalAs(UnmanagedType.R4)] out float levelNorm); [PreserveSig] int SetMute([In][MarshalAs(UnmanagedType.Bool)] bool isMuted, [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext); [PreserveSig] int GetMute([MarshalAs(UnmanagedType.Bool)] out bool isMuted); } [ComImport] [Guid("82149A85-DBA6-4487-86BB-EA8F7FEFCC71")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISubunit { } [ComImport] [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] internal class MMDeviceEnumeratorComObject { } public enum PartTypeEnum { Connector, Subunit, HardwarePeriphery, SoftwareDriver, Splitter, Category, Other } public enum StorageAccessMode { Read, Write, ReadWrite } [StructLayout(LayoutKind.Explicit)] public struct PropVariant { [FieldOffset(0)] public short vt; [FieldOffset(2)] public short wReserved1; [FieldOffset(4)] public short wReserved2; [FieldOffset(6)] public short wReserved3; [FieldOffset(8)] public sbyte cVal; [FieldOffset(8)] public byte bVal; [FieldOffset(8)] public short iVal; [FieldOffset(8)] public ushort uiVal; [FieldOffset(8)] public int lVal; [FieldOffset(8)] public uint ulVal; [FieldOffset(8)] public int intVal; [FieldOffset(8)] public uint uintVal; [FieldOffset(8)] public long hVal; [FieldOffset(8)] public long uhVal; [FieldOffset(8)] public float fltVal; [FieldOffset(8)] public double dblVal; [FieldOffset(8)] public short boolVal; [FieldOffset(8)] public int scode; [FieldOffset(8)] public FILETIME filetime; [FieldOffset(8)] public Blob blobVal; [FieldOffset(8)] public IntPtr pointerValue; public VarEnum DataType => (VarEnum)vt; public object Value { get { VarEnum dataType = DataType; switch (dataType) { case VarEnum.VT_I1: return bVal; case VarEnum.VT_I2: return iVal; case VarEnum.VT_I4: return lVal; case VarEnum.VT_I8: return hVal; case VarEnum.VT_INT: return iVal; case VarEnum.VT_UI4: return ulVal; case VarEnum.VT_UI8: return uhVal; case VarEnum.VT_LPWSTR: return Marshal.PtrToStringUni(pointerValue); case VarEnum.VT_BLOB: case (VarEnum)4113: return GetBlob(); case VarEnum.VT_CLSID: return Marshal.PtrToStructure(pointerValue); case VarEnum.VT_BOOL: return boolVal switch { -1 => true, 0 => false, _ => throw new NotSupportedException("PropVariant VT_BOOL must be either -1 or 0"), }; case VarEnum.VT_FILETIME: return DateTime.FromFileTime(((long)filetime.dwHighDateTime << 32) + filetime.dwLowDateTime); case VarEnum.VT_EMPTY: return null; default: throw new NotImplementedException("PropVariant " + dataType); } } } public static PropVariant FromLong(long value) { PropVariant result = default(PropVariant); result.vt = 20; result.hVal = value; return result; } private byte[] GetBlob() { byte[] array = new byte[blobVal.Length]; Marshal.Copy(blobVal.Data, array, 0, array.Length); return array; } public T[] GetBlobAsArrayOf() { int length = blobVal.Length; int num = Marshal.SizeOf((T)Activator.CreateInstance(typeof(T))); if (length % num != 0) { throw new InvalidDataException($"Blob size {length} not a multiple of struct size {num}"); } int num2 = length / num; T[] array = new T[num2]; for (int i = 0; i < num2; i++) { array[i] = (T)Activator.CreateInstance(typeof(T)); Marshal.PtrToStructure(new IntPtr((long)blobVal.Data + i * num), array[i]); } return array; } public static void Clear(IntPtr ptr) { PropVariantNative.PropVariantClear(ptr); } } internal class PropVariantNative { [DllImport("ole32.dll")] internal static extern int PropVariantClear(ref PropVariant pvar); [DllImport("ole32.dll")] internal static extern int PropVariantClear(IntPtr pvar); } } namespace NAudio.Wasapi.CoreAudioApi { internal class ActivateAudioInterfaceCompletionHandler : IActivateAudioInterfaceCompletionHandler, IAgileObject { private Action initializeAction; private TaskCompletionSource tcs = new TaskCompletionSource(); public ActivateAudioInterfaceCompletionHandler(Action initializeAction) { this.initializeAction = initializeAction; } public void ActivateCompleted(IActivateAudioInterfaceAsyncOperation activateOperation) { activateOperation.GetActivateResult(out var activateResult, out var activateInterface); if (activateResult != 0) { tcs.TrySetException(Marshal.GetExceptionForHR(activateResult, new IntPtr(-1))); return; } IAudioClient2 audioClient = (IAudioClient2)activateInterface; try { initializeAction(audioClient); tcs.SetResult(audioClient); } catch (Exception exception) { tcs.TrySetException(exception); } } public TaskAwaiter GetAwaiter() { return tcs.Task.GetAwaiter(); } } public class AudioVolumeLevel { private readonly IAudioVolumeLevel audioVolumeLevelInterface; public uint ChannelCount { get { audioVolumeLevelInterface.GetChannelCount(out var channels); return channels; } } internal AudioVolumeLevel(IAudioVolumeLevel audioVolumeLevel) { audioVolumeLevelInterface = audioVolumeLevel; } public void GetLevelRange(uint channel, out float minLevelDb, out float maxLevelDb, out float stepping) { audioVolumeLevelInterface.GetLevelRange(channel, out minLevelDb, out maxLevelDb, out stepping); } public float GetLevel(uint channel) { audioVolumeLevelInterface.GetLevel(channel, out var levelDb); return levelDb; } public void SetLevel(uint channel, float value) { Guid eventGuidContext = Guid.Empty; audioVolumeLevelInterface.SetLevel(channel, value, ref eventGuidContext); } public void SetLevelUniform(float value) { Guid eventGuidContext = Guid.Empty; audioVolumeLevelInterface.SetLevelUniform(value, ref eventGuidContext); } public void SetLevelAllChannel(float[] values, uint channels) { Guid eventGuidContext = Guid.Empty; audioVolumeLevelInterface.SetLevelAllChannel(values, channels, ref eventGuidContext); } } internal static class NativeMethods { [DllImport("Mmdevapi.dll", ExactSpelling = true, PreserveSig = false)] public static extern void ActivateAudioInterfaceAsync([In][MarshalAs(UnmanagedType.LPWStr)] string deviceInterfacePath, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [In] IntPtr activationParams, [In] IActivateAudioInterfaceCompletionHandler completionHandler, out IActivateAudioInterfaceAsyncOperation activationOperation); } } namespace NAudio.Wasapi.CoreAudioApi.Interfaces { [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("72A22D78-CDE4-431D-B8CC-843A71199B6D")] public interface IActivateAudioInterfaceAsyncOperation { void GetActivateResult(out int activateResult, [MarshalAs(UnmanagedType.IUnknown)] out object activateInterface); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("41D949AB-9862-444A-80F6-C261334DA5EB")] public interface IActivateAudioInterfaceCompletionHandler { void ActivateCompleted(IActivateAudioInterfaceAsyncOperation activateOperation); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] internal interface IAgileObject { } [ComImport] [Guid("9c2c4058-23f5-41de-877a-df3af236a09e")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IControlChangeNotify { [PreserveSig] int OnNotify([In] uint controlId, [In] IntPtr context); } } namespace NAudio.Wave { internal class ComStream : Stream, IStream { private Stream stream; public override bool CanRead => stream.CanRead; public override bool CanSeek => stream.CanSeek; public override bool CanWrite => stream.CanWrite; public override long Length => stream.Length; public override long Position { get { return stream.Position; } set { stream.Position = value; } } public ComStream(Stream stream) : this(stream, synchronizeStream: true) { } internal ComStream(Stream stream, bool synchronizeStream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (synchronizeStream) { stream = Stream.Synchronized(stream); } this.stream = stream; } void IStream.Clone(out IStream ppstm) { ppstm = null; } void IStream.Commit(int grfCommitFlags) { stream.Flush(); } void IStream.CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { } void IStream.LockRegion(long libOffset, long cb, int dwLockType) { } void IStream.Read(byte[] pv, int cb, IntPtr pcbRead) { if (!CanRead) { throw new InvalidOperationException("Stream is not readable."); } int val = Read(pv, 0, cb); if (pcbRead != IntPtr.Zero) { Marshal.WriteInt32(pcbRead, val); } } void IStream.Revert() { } void IStream.Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { long val = Seek(dlibMove, (SeekOrigin)dwOrigin); if (plibNewPosition != IntPtr.Zero) { Marshal.WriteInt64(plibNewPosition, val); } } void IStream.SetSize(long libNewSize) { SetLength(libNewSize); } void IStream.Stat(out STATSTG pstatstg, int grfStatFlag) { STATSTG sTATSTG = default(STATSTG); sTATSTG.type = 2; sTATSTG.cbSize = Length; sTATSTG.grfMode = 0; STATSTG sTATSTG2 = sTATSTG; if (CanWrite && CanRead) { sTATSTG2.grfMode |= 2; } else if (CanRead) { sTATSTG2.grfMode |= 0; } else { if (!CanWrite) { throw new ObjectDisposedException("Stream"); } sTATSTG2.grfMode |= 1; } pstatstg = sTATSTG2; } void IStream.UnlockRegion(long libOffset, long cb, int dwLockType) { } void IStream.Write(byte[] pv, int cb, IntPtr pcbWritten) { if (!CanWrite) { throw new InvalidOperationException("Stream is not writeable."); } Write(pv, 0, cb); if (pcbWritten != IntPtr.Zero) { Marshal.WriteInt32(pcbWritten, cb); } } public override void Flush() { stream.Flush(); } public override int Read(byte[] buffer, int offset, int count) { return stream.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { return stream.Seek(offset, origin); } public override void SetLength(long value) { stream.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { stream.Write(buffer, offset, count); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (stream != null) { stream.Dispose(); stream = null; } } public override void Close() { base.Close(); if (stream != null) { stream.Close(); stream = null; } } } public class DmoEffectWaveProvider : IWaveProvider, IDisposable where TDmoEffector : IDmoEffector, new() { private readonly IWaveProvider inputProvider; private readonly IDmoEffector effector; public WaveFormat WaveFormat => inputProvider.WaveFormat; public TEffectorParam EffectParams => effector.EffectParams; public DmoEffectWaveProvider(IWaveProvider inputProvider) { this.inputProvider = inputProvider; effector = new TDmoEffector(); MediaObject obj = effector.MediaObject ?? throw new NotSupportedException("Dmo Effector Not Supported: TDmoEffector"); if (!obj.SupportsInputWaveFormat(0, inputProvider.WaveFormat)) { throw new ArgumentException("Unsupported Input Stream format", "inputProvider"); } obj.AllocateStreamingResources(); obj.SetInputWaveFormat(0, this.inputProvider.WaveFormat); obj.SetOutputWaveFormat(0, this.inputProvider.WaveFormat); } public int Read(byte[] buffer, int offset, int count) { int num = inputProvider.Read(buffer, offset, count); if (effector == null) { return num; } if (effector.MediaObjectInPlace.Process(num, offset, buffer, 0L, DmoInPlaceProcessFlags.Normal) == DmoInPlaceProcessReturn.HasEffectTail) { byte[] data = new byte[num]; while (effector.MediaObjectInPlace.Process(num, 0, data, 0L, DmoInPlaceProcessFlags.Zero) == DmoInPlaceProcessReturn.HasEffectTail) { } } return num; } public void Dispose() { if (effector != null) { effector.MediaObject.FreeStreamingResources(); effector.Dispose(); } } } public class MediaFoundationEncoder : IDisposable { private readonly MediaType outputMediaType; private bool disposed; public int DefaultReadBufferSize { get; set; } public static int[] GetEncodeBitrates(Guid audioSubtype, int sampleRate, int channels) { return (from br in (from mt in GetOutputMediaTypes(audioSubtype) where mt.SampleRate == sampleRate && mt.ChannelCount == channels select mt.AverageBytesPerSecond * 8).Distinct() orderby br select br).ToArray(); } public static MediaType[] GetOutputMediaTypes(Guid audioSubtype) { MediaFoundationApi.Startup(); IMFCollection ppAvailableTypes; try { MediaFoundationInterop.MFTranscodeGetAudioOutputAvailableTypes(audioSubtype, _MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, null, out ppAvailableTypes); } catch (COMException ex) { if (HResult.GetHResult(ex) == -1072875819) { return new MediaType[0]; } throw; } ppAvailableTypes.GetElementCount(out var pcElements); List list = new List(pcElements); for (int i = 0; i < pcElements; i++) { ppAvailableTypes.GetElement(i, out var ppUnkElement); IMFMediaType mediaType = (IMFMediaType)ppUnkElement; list.Add(new MediaType(mediaType)); } Marshal.ReleaseComObject(ppAvailableTypes); return list.ToArray(); } public static void EncodeToWma(IWaveProvider inputProvider, string outputFile, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_WMAudioV8, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable WMA encoders available")); mediaFoundationEncoder.Encode(outputFile, inputProvider); } public static void EncodeToWma(IWaveProvider inputProvider, Stream outputStream, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_WMAudioV8, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable WMA encoders available")); mediaFoundationEncoder.Encode(outputStream, inputProvider, TranscodeContainerTypes.MFTranscodeContainerType_ASF); } public static void EncodeToMp3(IWaveProvider inputProvider, string outputFile, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_MP3, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable MP3 encoders available")); mediaFoundationEncoder.Encode(outputFile, inputProvider); } public static void EncodeToMp3(IWaveProvider inputProvider, Stream outputStream, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_MP3, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable MP3 encoders available")); mediaFoundationEncoder.Encode(outputStream, inputProvider, TranscodeContainerTypes.MFTranscodeContainerType_MP3); } public static void EncodeToAac(IWaveProvider inputProvider, string outputFile, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_AAC, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable AAC encoders available")); mediaFoundationEncoder.Encode(outputFile, inputProvider); } public static void EncodeToAac(IWaveProvider inputProvider, Stream outputStream, int desiredBitRate = 192000) { using MediaFoundationEncoder mediaFoundationEncoder = new MediaFoundationEncoder(SelectMediaType(AudioSubtypes.MFAudioFormat_AAC, inputProvider.WaveFormat, desiredBitRate) ?? throw new InvalidOperationException("No suitable AAC encoders available")); mediaFoundationEncoder.Encode(outputStream, inputProvider, TranscodeContainerTypes.MFTranscodeContainerType_MPEG4); } public static MediaType SelectMediaType(Guid audioSubtype, WaveFormat inputFormat, int desiredBitRate) { MediaFoundationApi.Startup(); return (from mt in GetOutputMediaTypes(audioSubtype) where mt.SampleRate == inputFormat.SampleRate && mt.ChannelCount == inputFormat.Channels select new { MediaType = mt, Delta = Math.Abs(desiredBitRate - mt.AverageBytesPerSecond * 8) } into mt orderby mt.Delta select mt.MediaType).FirstOrDefault(); } public MediaFoundationEncoder(MediaType outputMediaType) { if (outputMediaType == null) { throw new ArgumentNullException("outputMediaType"); } this.outputMediaType = outputMediaType; } public void Encode(string outputFile, IWaveProvider inputProvider) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((int)inputProvider.WaveFormat.Encoding != 1 && (int)inputProvider.WaveFormat.Encoding != 3) { throw new ArgumentException("Encode input format must be PCM or IEEE float"); } MediaType mediaType = new MediaType(inputProvider.WaveFormat); IMFSinkWriter iMFSinkWriter = CreateSinkWriter(outputFile); try { iMFSinkWriter.AddStream(outputMediaType.MediaFoundationObject, out var pdwStreamIndex); iMFSinkWriter.SetInputMediaType(pdwStreamIndex, mediaType.MediaFoundationObject, null); PerformEncode(iMFSinkWriter, pdwStreamIndex, inputProvider); } finally { if (iMFSinkWriter != null) { Marshal.ReleaseComObject(iMFSinkWriter); } if (mediaType.MediaFoundationObject != null) { Marshal.ReleaseComObject(mediaType.MediaFoundationObject); } } } public void Encode(Stream outputStream, IWaveProvider inputProvider, Guid transcodeContainerType) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((int)inputProvider.WaveFormat.Encoding != 1 && (int)inputProvider.WaveFormat.Encoding != 3) { throw new ArgumentException("Encode input format must be PCM or IEEE float"); } MediaType mediaType = new MediaType(inputProvider.WaveFormat); IMFSinkWriter iMFSinkWriter = CreateSinkWriter(new ComStream(outputStream), transcodeContainerType); try { iMFSinkWriter.AddStream(outputMediaType.MediaFoundationObject, out var pdwStreamIndex); iMFSinkWriter.SetInputMediaType(pdwStreamIndex, mediaType.MediaFoundationObject, null); PerformEncode(iMFSinkWriter, pdwStreamIndex, inputProvider); } finally { if (iMFSinkWriter != null) { Marshal.ReleaseComObject(iMFSinkWriter); } if (mediaType.MediaFoundationObject != null) { Marshal.ReleaseComObject(mediaType.MediaFoundationObject); } } } private static IMFSinkWriter CreateSinkWriter(string outputFile) { IMFAttributes iMFAttributes = MediaFoundationApi.CreateAttributes(1); iMFAttributes.SetUINT32(MediaFoundationAttributes.MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 1); try { MediaFoundationInterop.MFCreateSinkWriterFromURL(outputFile, null, iMFAttributes, out var ppSinkWriter); return ppSinkWriter; } catch (COMException ex) { if (HResult.GetHResult(ex) == -1072875819) { throw new ArgumentException("Was not able to create a sink writer for this file extension"); } throw; } finally { Marshal.ReleaseComObject(iMFAttributes); } } private static IMFSinkWriter CreateSinkWriter(IStream outputStream, Guid TranscodeContainerType) { IMFAttributes iMFAttributes = MediaFoundationApi.CreateAttributes(1); iMFAttributes.SetGUID(MediaFoundationAttributes.MF_TRANSCODE_CONTAINERTYPE, TranscodeContainerType); try { MediaFoundationInterop.MFCreateMFByteStreamOnStream(outputStream, out var ppByteStream); MediaFoundationInterop.MFCreateSinkWriterFromURL(null, ppByteStream, iMFAttributes, out var ppSinkWriter); return ppSinkWriter; } finally { Marshal.ReleaseComObject(iMFAttributes); } } private void PerformEncode(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider) { if (DefaultReadBufferSize == 0) { DefaultReadBufferSize = inputProvider.WaveFormat.AverageBytesPerSecond * 4; } byte[] managedBuffer = new byte[DefaultReadBufferSize]; writer.BeginWriting(); long num = 0L; long num2; do { num2 = ConvertOneBuffer(writer, streamIndex, inputProvider, num, managedBuffer); num += num2; } while (num2 > 0); writer.DoFinalize(); } private static long BytesToNsPosition(int bytes, WaveFormat waveFormat) { return 10000000L * (long)bytes / waveFormat.AverageBytesPerSecond; } private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer) { long num = 0L; IMFMediaBuffer iMFMediaBuffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length); iMFMediaBuffer.GetMaxLength(out var pcbMaxLength); IMFSample iMFSample = MediaFoundationApi.CreateSample(); iMFSample.AddBuffer(iMFMediaBuffer); int num2 = inputProvider.Read(managedBuffer, 0, pcbMaxLength); if (num2 > 0) { iMFMediaBuffer.Lock(out var ppbBuffer, out pcbMaxLength, out var _); num = BytesToNsPosition(num2, inputProvider.WaveFormat); Marshal.Copy(managedBuffer, 0, ppbBuffer, num2); iMFMediaBuffer.SetCurrentLength(num2); iMFMediaBuffer.Unlock(); iMFSample.SetSampleTime(position); iMFSample.SetSampleDuration(num); writer.WriteSample(streamIndex, iMFSample); } Marshal.ReleaseComObject(iMFSample); Marshal.ReleaseComObject(iMFMediaBuffer); return num; } protected void Dispose(bool disposing) { Marshal.ReleaseComObject(outputMediaType.MediaFoundationObject); } public void Dispose() { if (!disposed) { disposed = true; Dispose(disposing: true); } GC.SuppressFinalize(this); } ~MediaFoundationEncoder() { Dispose(disposing: false); } } public class MediaFoundationReader : WaveStream { public class MediaFoundationReaderSettings { public bool RequestFloatOutput { get; set; } public bool SingleReaderObject { get; set; } public bool RepositionInRead { get; set; } public MediaFoundationReaderSettings() { RepositionInRead = true; } } private WaveFormat waveFormat; private long length; private MediaFoundationReaderSettings settings; private readonly string file; private IMFSourceReader pReader; private long position; private byte[] decoderOutputBuffer; private int decoderOutputOffset; private int decoderOutputCount; private long repositionTo = -1L; public override WaveFormat WaveFormat => waveFormat; public override long Length => length; public override long Position { get { return position; } set { if (value < 0) { throw new ArgumentOutOfRangeException("value", "Position cannot be less than 0"); } if (settings.RepositionInRead) { repositionTo = value; position = value; } else { Reposition(value); } } } public event EventHandler WaveFormatChanged; protected MediaFoundationReader() { } public MediaFoundationReader(string file) : this(file, null) { } public MediaFoundationReader(string file, MediaFoundationReaderSettings settings) { this.file = file; Init(settings); } protected void Init(MediaFoundationReaderSettings initialSettings) { MediaFoundationApi.Startup(); settings = initialSettings ?? new MediaFoundationReaderSettings(); IMFSourceReader iMFSourceReader = CreateReader(settings); waveFormat = GetCurrentWaveFormat(iMFSourceReader); iMFSourceReader.SetStreamSelection(-3, pSelected: true); length = GetLength(iMFSourceReader); if (settings.SingleReaderObject) { pReader = iMFSourceReader; } else { Marshal.ReleaseComObject(iMFSourceReader); } } private WaveFormat GetCurrentWaveFormat(IMFSourceReader reader) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown reader.GetCurrentMediaType(-3, out var ppMediaType); MediaType mediaType = new MediaType(ppMediaType); _ = mediaType.MajorType; Guid subType = mediaType.SubType; int channelCount = mediaType.ChannelCount; int bitsPerSample = mediaType.BitsPerSample; int sampleRate = mediaType.SampleRate; if (subType == AudioSubtypes.MFAudioFormat_PCM) { return new WaveFormat(sampleRate, bitsPerSample, channelCount); } if (subType == AudioSubtypes.MFAudioFormat_Float) { return WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channelCount); } string text = FieldDescriptionHelper.Describe(typeof(AudioSubtypes), subType); throw new InvalidDataException("Unsupported audio sub Type " + text); } private static MediaType GetCurrentMediaType(IMFSourceReader reader) { reader.GetCurrentMediaType(-3, out var ppMediaType); return new MediaType(ppMediaType); } protected virtual IMFSourceReader CreateReader(MediaFoundationReaderSettings settings) { MediaFoundationInterop.MFCreateSourceReaderFromURL(file, null, out var ppSourceReader); ppSourceReader.SetStreamSelection(-2, pSelected: false); ppSourceReader.SetStreamSelection(-3, pSelected: true); MediaType mediaType = new MediaType(); mediaType.MajorType = NAudio.MediaFoundation.MediaTypes.MFMediaType_Audio; mediaType.SubType = (settings.RequestFloatOutput ? AudioSubtypes.MFAudioFormat_Float : AudioSubtypes.MFAudioFormat_PCM); MediaType currentMediaType = GetCurrentMediaType(ppSourceReader); mediaType.ChannelCount = currentMediaType.ChannelCount; mediaType.SampleRate = currentMediaType.SampleRate; try { ppSourceReader.SetCurrentMediaType(-3, IntPtr.Zero, mediaType.MediaFoundationObject); } catch (COMException ex) when (HResult.GetHResult(ex) == -1072875852) { if (!(currentMediaType.SubType == AudioSubtypes.MFAudioFormat_AAC) || currentMediaType.ChannelCount != 1) { throw; } mediaType.SampleRate = (currentMediaType.SampleRate *= 2); mediaType.ChannelCount = (currentMediaType.ChannelCount *= 2); ppSourceReader.SetCurrentMediaType(-3, IntPtr.Zero, mediaType.MediaFoundationObject); } Marshal.ReleaseComObject(currentMediaType.MediaFoundationObject); return ppSourceReader; } private long GetLength(IMFSourceReader reader) { IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf()); try { int presentationAttribute = reader.GetPresentationAttribute(-1, MediaFoundationAttributes.MF_PD_DURATION, intPtr); switch (presentationAttribute) { case -1072875802: return 0L; default: Marshal.ThrowExceptionForHR(presentationAttribute); break; case 0: break; } return (long)Marshal.PtrToStructure(intPtr).Value * waveFormat.AverageBytesPerSecond / 10000000; } finally { PropVariant.Clear(intPtr); Marshal.FreeHGlobal(intPtr); } } private void EnsureBuffer(int bytesRequired) { if (decoderOutputBuffer == null || decoderOutputBuffer.Length < bytesRequired) { decoderOutputBuffer = new byte[bytesRequired]; } } public override int Read(byte[] buffer, int offset, int count) { if (pReader == null) { pReader = CreateReader(settings); } if (repositionTo != -1) { Reposition(repositionTo); } int num = 0; if (decoderOutputCount > 0) { num += ReadFromDecoderBuffer(buffer, offset, count - num); } while (num < count) { pReader.ReadSample(-3, 0, out var _, out var pdwStreamFlags, out var _, out var ppSample); if ((pdwStreamFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_ENDOFSTREAM) != 0) { break; } if ((pdwStreamFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) != 0) { waveFormat = GetCurrentWaveFormat(pReader); OnWaveFormatChanged(); } else if (pdwStreamFlags != 0) { throw new InvalidOperationException($"MediaFoundationReadError {pdwStreamFlags}"); } ppSample.ConvertToContiguousBuffer(out var ppBuffer); ppBuffer.Lock(out var ppbBuffer, out var _, out var pcbCurrentLength); EnsureBuffer(pcbCurrentLength); Marshal.Copy(ppbBuffer, decoderOutputBuffer, 0, pcbCurrentLength); decoderOutputOffset = 0; decoderOutputCount = pcbCurrentLength; num += ReadFromDecoderBuffer(buffer, offset + num, count - num); ppBuffer.Unlock(); Marshal.ReleaseComObject(ppBuffer); Marshal.ReleaseComObject(ppSample); } position += num; return num; } private int ReadFromDecoderBuffer(byte[] buffer, int offset, int needed) { int num = Math.Min(needed, decoderOutputCount); Array.Copy(decoderOutputBuffer, decoderOutputOffset, buffer, offset, num); decoderOutputOffset += num; decoderOutputCount -= num; if (decoderOutputCount == 0) { decoderOutputOffset = 0; } return num; } private void Reposition(long desiredPosition) { PropVariant structure = PropVariant.FromLong(10000000 * repositionTo / waveFormat.AverageBytesPerSecond); IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(structure)); try { Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false); pReader.SetCurrentPosition(Guid.Empty, intPtr); } finally { Marshal.FreeHGlobal(intPtr); } decoderOutputCount = 0; decoderOutputOffset = 0; position = desiredPosition; repositionTo = -1L; } protected override void Dispose(bool disposing) { if (pReader != null) { Marshal.ReleaseComObject(pReader); pReader = null; } ((Stream)this).Dispose(disposing); } private void OnWaveFormatChanged() { this.WaveFormatChanged?.Invoke(this, EventArgs.Empty); } } public class MediaFoundationResampler : MediaFoundationTransform { private int resamplerQuality; public int ResamplerQuality { get { return resamplerQuality; } set { if (value < 1 || value > 60) { throw new ArgumentOutOfRangeException("Resampler Quality must be between 1 and 60"); } resamplerQuality = value; } } private static bool IsPcmOrIeeeFloat(WaveFormat waveFormat) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 WaveFormatExtensible val = (WaveFormatExtensible)(object)((waveFormat is WaveFormatExtensible) ? waveFormat : null); if ((int)waveFormat.Encoding != 1 && (int)waveFormat.Encoding != 3) { if (val != null) { if (!(val.SubFormat == AudioSubtypes.MFAudioFormat_PCM)) { return val.SubFormat == AudioSubtypes.MFAudioFormat_Float; } return true; } return false; } return true; } public MediaFoundationResampler(IWaveProvider sourceProvider, WaveFormat outputFormat) : base(sourceProvider, outputFormat) { if (!IsPcmOrIeeeFloat(sourceProvider.WaveFormat)) { throw new ArgumentException("Input must be PCM or IEEE float", "sourceProvider"); } if (!IsPcmOrIeeeFloat(outputFormat)) { throw new ArgumentException("Output must be PCM or IEEE float", "outputFormat"); } MediaFoundationApi.Startup(); ResamplerQuality = 60; object comObject = CreateResamplerComObject(); FreeComObject(comObject); } private void FreeComObject(object comObject) { Marshal.ReleaseComObject(comObject); } private object CreateResamplerComObject() { return new ResamplerMediaComObject(); } public MediaFoundationResampler(IWaveProvider sourceProvider, int outputSampleRate) : this(sourceProvider, CreateOutputFormat(sourceProvider.WaveFormat, outputSampleRate)) { } protected override IMFTransform CreateTransform() { object obj = CreateResamplerComObject(); IMFTransform obj2 = (IMFTransform)obj; IMFMediaType iMFMediaType = MediaFoundationApi.CreateMediaTypeFromWaveFormat(sourceProvider.WaveFormat); obj2.SetInputType(0, iMFMediaType, _MFT_SET_TYPE_FLAGS.None); Marshal.ReleaseComObject(iMFMediaType); IMFMediaType iMFMediaType2 = MediaFoundationApi.CreateMediaTypeFromWaveFormat(outputWaveFormat); obj2.SetOutputType(0, iMFMediaType2, _MFT_SET_TYPE_FLAGS.None); Marshal.ReleaseComObject(iMFMediaType2); ((IWMResamplerProps)obj).SetHalfFilterLength(ResamplerQuality); return obj2; } private static WaveFormat CreateOutputFormat(WaveFormat inputFormat, int outputSampleRate) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((int)inputFormat.Encoding == 1) { return new WaveFormat(outputSampleRate, inputFormat.BitsPerSample, inputFormat.Channels); } if ((int)inputFormat.Encoding == 3) { return WaveFormat.CreateIeeeFloatWaveFormat(outputSampleRate, inputFormat.Channels); } throw new ArgumentException("Can only resample PCM or IEEE float"); } } public class ResamplerDmoStream : WaveStream { private readonly IWaveProvider inputProvider; private readonly WaveStream inputStream; private readonly WaveFormat outputFormat; private DmoOutputDataBuffer outputBuffer; private DmoResampler dmoResampler; private MediaBuffer inputMediaBuffer; private long position; public override WaveFormat WaveFormat => outputFormat; public override long Length { get { if (inputStream == null) { throw new InvalidOperationException("Cannot report length if the input was an IWaveProvider"); } return InputToOutputPosition(((Stream)(object)inputStream).Length); } } public override long Position { get { return position; } set { if (inputStream == null) { throw new InvalidOperationException("Cannot set position if the input was not a WaveStream"); } ((Stream)(object)inputStream).Position = OutputToInputPosition(value); position = InputToOutputPosition(((Stream)(object)inputStream).Position); dmoResampler.MediaObject.Discontinuity(0); } } public ResamplerDmoStream(IWaveProvider inputProvider, WaveFormat outputFormat) { this.inputProvider = inputProvider; inputStream = (WaveStream)(object)((inputProvider is WaveStream) ? inputProvider : null); this.outputFormat = outputFormat; dmoResampler = new DmoResampler(); if (!dmoResampler.MediaObject.SupportsInputWaveFormat(0, inputProvider.WaveFormat)) { throw new ArgumentException("Unsupported Input Stream format", "inputProvider"); } dmoResampler.MediaObject.SetInputWaveFormat(0, inputProvider.WaveFormat); if (!dmoResampler.MediaObject.SupportsOutputWaveFormat(0, outputFormat)) { throw new ArgumentException("Unsupported Output Stream format", "outputFormat"); } dmoResampler.MediaObject.SetOutputWaveFormat(0, outputFormat); if (inputStream != null) { position = InputToOutputPosition(((Stream)(object)inputStream).Position); } inputMediaBuffer = new MediaBuffer(inputProvider.WaveFormat.AverageBytesPerSecond); outputBuffer = new DmoOutputDataBuffer(outputFormat.AverageBytesPerSecond); } private long InputToOutputPosition(long inputPosition) { double num = (double)outputFormat.AverageBytesPerSecond / (double)inputProvider.WaveFormat.AverageBytesPerSecond; long num2 = (long)((double)inputPosition * num); if (num2 % outputFormat.BlockAlign != 0L) { num2 -= num2 % outputFormat.BlockAlign; } return num2; } private long OutputToInputPosition(long outputPosition) { double num = (double)outputFormat.AverageBytesPerSecond / (double)inputProvider.WaveFormat.AverageBytesPerSecond; long num2 = (long)((double)outputPosition / num); if (num2 % inputProvider.WaveFormat.BlockAlign != 0L) { num2 -= num2 % inputProvider.WaveFormat.BlockAlign; } return num2; } public override int Read(byte[] buffer, int offset, int count) { int num = 0; while (num < count) { if (dmoResampler.MediaObject.IsAcceptingData(0)) { int num2 = (int)OutputToInputPosition(count - num); byte[] array = new byte[num2]; int num3 = inputProvider.Read(array, 0, num2); if (num3 == 0) { break; } inputMediaBuffer.LoadData(array, num3); dmoResampler.MediaObject.ProcessInput(0, inputMediaBuffer, DmoInputDataBufferFlags.None, 0L, 0L); outputBuffer.MediaBuffer.SetLength(0); outputBuffer.StatusFlags = DmoOutputDataBufferFlags.None; dmoResampler.MediaObject.ProcessOutput(DmoProcessOutputFlags.None, 1, new DmoOutputDataBuffer[1] { outputBuffer }); if (outputBuffer.Length == 0) { break; } outputBuffer.RetrieveData(buffer, offset + num); num += outputBuffer.Length; } } position += num; return num; } protected override void Dispose(bool disposing) { if (inputMediaBuffer != null) { inputMediaBuffer.Dispose(); inputMediaBuffer = null; } outputBuffer.Dispose(); if (dmoResampler != null) { dmoResampler = null; } ((Stream)this).Dispose(disposing); } } public class StreamMediaFoundationReader : MediaFoundationReader { private readonly Stream stream; public StreamMediaFoundationReader(Stream stream, MediaFoundationReaderSettings settings = null) { this.stream = stream; Init(settings); } protected override IMFSourceReader CreateReader(MediaFoundationReaderSettings settings) { IMFSourceReader iMFSourceReader = MediaFoundationApi.CreateSourceReaderFromByteStream(MediaFoundationApi.CreateByteStream(new ComStream(stream))); iMFSourceReader.SetStreamSelection(-2, pSelected: false); iMFSourceReader.SetStreamSelection(-3, pSelected: true); iMFSourceReader.SetCurrentMediaType(-3, IntPtr.Zero, new MediaType { MajorType = NAudio.MediaFoundation.MediaTypes.MFMediaType_Audio, SubType = (settings.RequestFloatOutput ? AudioSubtypes.MFAudioFormat_Float : AudioSubtypes.MFAudioFormat_PCM) }.MediaFoundationObject); return iMFSourceReader; } } public class WasapiLoopbackCapture : WasapiCapture { public WasapiLoopbackCapture() : this(GetDefaultLoopbackCaptureDevice()) { } public WasapiLoopbackCapture(MMDevice captureDevice) : base(captureDevice) { } public static MMDevice GetDefaultLoopbackCaptureDevice() { return new MMDeviceEnumerator().GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); } protected override AudioClientStreamFlags GetAudioClientStreamFlags() { return AudioClientStreamFlags.Loopback | base.GetAudioClientStreamFlags(); } } public class WasapiOut : IWavePlayer, IDisposable, IWavePosition { private AudioClient audioClient; private readonly MMDevice mmDevice; private readonly AudioClientShareMode shareMode; private AudioRenderClient renderClient; private IWaveProvider sourceProvider; private int latencyMilliseconds; private int bufferFrameCount; private int bytesPerFrame; private readonly bool isUsingEventSync; private EventWaitHandle frameEventWaitHandle; private byte[] readBuffer; private volatile PlaybackState playbackState; private Thread playThread; private readonly SynchronizationContext syncContext; private bool dmoResamplerNeeded; public WaveFormat OutputWaveFormat { get; private set; } public PlaybackState PlaybackState => playbackState; public float Volume { get { return mmDevice.AudioEndpointVolume.MasterVolumeLevelScalar; } set { if (value < 0f) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } if (value > 1f) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } mmDevice.AudioEndpointVolume.MasterVolumeLevelScalar = value; } } public AudioStreamVolume AudioStreamVolume { get { if (shareMode == AudioClientShareMode.Exclusive) { throw new InvalidOperationException("AudioStreamVolume is ONLY supported for shared audio streams."); } return audioClient.AudioStreamVolume; } } public event EventHandler PlaybackStopped; public WasapiOut() : this(GetDefaultAudioEndpoint(), AudioClientShareMode.Shared, useEventSync: true, 200) { } public WasapiOut(AudioClientShareMode shareMode, int latency) : this(GetDefaultAudioEndpoint(), shareMode, useEventSync: true, latency) { } public WasapiOut(AudioClientShareMode shareMode, bool useEventSync, int latency) : this(GetDefaultAudioEndpoint(), shareMode, useEventSync, latency) { } public WasapiOut(MMDevice device, AudioClientShareMode shareMode, bool useEventSync, int latency) { audioClient = device.AudioClient; mmDevice = device; this.shareMode = shareMode; isUsingEventSync = useEventSync; latencyMilliseconds = latency; syncContext = SynchronizationContext.Current; OutputWaveFormat = audioClient.MixFormat; } private static MMDevice GetDefaultAudioEndpoint() { if (Environment.OSVersion.Version.Major < 6) { throw new NotSupportedException("WASAPI supported only on Windows Vista and above"); } return new MMDeviceEnumerator().GetDefaultAudioEndpoint(DataFlow.Render, Role.Console); } private void PlayThread() { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Invalid comparison between Unknown and I4 //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Invalid comparison between Unknown and I4 ResamplerDmoStream resamplerDmoStream = null; IWaveProvider playbackProvider = sourceProvider; Exception e = null; try { if (dmoResamplerNeeded) { resamplerDmoStream = new ResamplerDmoStream(sourceProvider, OutputWaveFormat); playbackProvider = (IWaveProvider)(object)resamplerDmoStream; } bufferFrameCount = audioClient.BufferSize; bytesPerFrame = OutputWaveFormat.Channels * OutputWaveFormat.BitsPerSample / 8; readBuffer = BufferHelpers.Ensure(readBuffer, bufferFrameCount * bytesPerFrame); if (FillBuffer(playbackProvider, bufferFrameCount)) { return; } WaitHandle[] waitHandles = new WaitHandle[1] { frameEventWaitHandle }; audioClient.Start(); while ((int)playbackState != 0) { if (isUsingEventSync) { WaitHandle.WaitAny(waitHandles, 3 * latencyMilliseconds, exitContext: false); } else { Thread.Sleep(latencyMilliseconds / 2); } if ((int)playbackState == 1) { int num = ((!isUsingEventSync) ? audioClient.CurrentPadding : ((shareMode == AudioClientShareMode.Shared) ? audioClient.CurrentPadding : 0)); int num2 = bufferFrameCount - num; if (num2 > 10 && FillBuffer(playbackProvider, num2)) { break; } } } if ((int)playbackState == 1) { Thread.Sleep(isUsingEventSync ? latencyMilliseconds : (latencyMilliseconds / 2)); } audioClient.Stop(); playbackState = (PlaybackState)0; audioClient.Reset(); } catch (Exception ex) { e = ex; } finally { ((Stream)(object)resamplerDmoStream)?.Dispose(); RaisePlaybackStopped(e); } } private void RaisePlaybackStopped(Exception e) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown EventHandler handler = this.PlaybackStopped; if (handler == null) { return; } if (syncContext == null) { handler(this, new StoppedEventArgs(e)); return; } syncContext.Post(delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown handler(this, new StoppedEventArgs(e)); }, null); } private unsafe bool FillBuffer(IWaveProvider playbackProvider, int frameCount) { int num = frameCount * bytesPerFrame; int num2 = playbackProvider.Read(readBuffer, 0, num); if (num2 == 0) { return true; } IntPtr buffer = renderClient.GetBuffer(frameCount); Marshal.Copy(readBuffer, 0, buffer, num2); if (isUsingEventSync && shareMode == AudioClientShareMode.Exclusive) { if (num2 < num) { byte* ptr = (byte*)(void*)buffer; while (num2 < num) { ptr[num2++] = 0; } } renderClient.ReleaseBuffer(frameCount, AudioClientBufferFlags.None); } else { int numFramesWritten = num2 / bytesPerFrame; renderClient.ReleaseBuffer(numFramesWritten, AudioClientBufferFlags.None); } return false; } private WaveFormat GetFallbackFormat() { //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown int sampleRate = audioClient.MixFormat.SampleRate; int channels = audioClient.MixFormat.Channels; List list = new List { OutputWaveFormat.SampleRate }; if (!list.Contains(sampleRate)) { list.Add(sampleRate); } if (!list.Contains(44100)) { list.Add(44100); } if (!list.Contains(48000)) { list.Add(48000); } List list2 = new List { OutputWaveFormat.Channels }; if (!list2.Contains(channels)) { list2.Add(channels); } if (!list2.Contains(2)) { list2.Add(2); } List list3 = new List { OutputWaveFormat.BitsPerSample }; if (!list3.Contains(32)) { list3.Add(32); } if (!list3.Contains(24)) { list3.Add(24); } if (!list3.Contains(16)) { list3.Add(16); } List list4 = new List { 0 }; if (list2.Contains(1)) { list4.Add(4); } if (list2.Contains(2)) { list4.Add(12); } if (list2.Contains(3)) { list4.Add(11); } if (list2.Contains(4)) { list4.Add(51); list4.Add(263); } if (list2.Contains(5)) { list4.Add(1543); } if (list2.Contains(6)) { list4.Add(1551); } if (list2.Contains(7)) { list4.Add(1591); } if (list2.Contains(8)) { list4.Add(1599); } foreach (int item in list) { foreach (int item2 in list2) { foreach (int item3 in list3) { foreach (int item4 in list4) { WaveFormatExtensible val = new WaveFormatExtensible(item, item3, item2, item4); if (audioClient.IsFormatSupported(shareMode, (WaveFormat)(object)val)) { return (WaveFormat)(object)val; } } } } } throw new NotSupportedException("Can't find a supported format to use"); } public long GetPosition() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 PlaybackState val = playbackState; if ((int)val != 0) { ulong position; if ((int)val == 1) { position = audioClient.AudioClockClient.AdjustedPosition; } else { audioClient.AudioClockClient.GetPosition(out position, out var _); } return (long)position * (long)OutputWaveFormat.AverageBytesPerSecond / (long)audioClient.AudioClockClient.Frequency; } return 0L; } public void Play() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((int)playbackState != 1) { if ((int)playbackState == 0) { playThread = new Thread(PlayThread) { IsBackground = true }; playbackState = (PlaybackState)1; playThread.Start(); } else { playbackState = (PlaybackState)1; } } } public void Stop() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((int)playbackState != 0) { playbackState = (PlaybackState)0; playThread.Join(); playThread = null; } } public void Pause() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((int)playbackState == 1) { playbackState = (PlaybackState)2; } } public void Init(IWaveProvider waveProvider) { long num = (long)latencyMilliseconds * 10000L; OutputWaveFormat = waveProvider.WaveFormat; AudioClientStreamFlags audioClientStreamFlags = AudioClientStreamFlags.SrcDefaultQuality | AudioClientStreamFlags.AutoConvertPcm; sourceProvider = waveProvider; if (shareMode == AudioClientShareMode.Exclusive) { audioClientStreamFlags = AudioClientStreamFlags.None; if (!audioClient.IsFormatSupported(shareMode, OutputWaveFormat, out var closestMatchFormat)) { if (closestMatchFormat == null) { OutputWaveFormat = GetFallbackFormat(); } else { OutputWaveFormat = (WaveFormat)(object)closestMatchFormat; } try { ResamplerDmoStream resamplerDmoStream = new ResamplerDmoStream(waveProvider, OutputWaveFormat); try { } finally { ((IDisposable)resamplerDmoStream)?.Dispose(); } } catch (Exception) { OutputWaveFormat = GetFallbackFormat(); ResamplerDmoStream resamplerDmoStream = new ResamplerDmoStream(waveProvider, OutputWaveFormat); try { } finally { ((IDisposable)resamplerDmoStream)?.Dispose(); } } dmoResamplerNeeded = true; } else { dmoResamplerNeeded = false; } } if (isUsingEventSync) { if (shareMode == AudioClientShareMode.Shared) { audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback | audioClientStreamFlags, num, 0L, OutputWaveFormat, Guid.Empty); long streamLatency = audioClient.StreamLatency; if (streamLatency != 0L) { latencyMilliseconds = (int)(streamLatency / 10000); } } else { try { audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback | audioClientStreamFlags, num, num, OutputWaveFormat, Guid.Empty); } catch (COMException ex2) { if (ex2.ErrorCode != -2004287463) { throw; } long num2 = (long)(10000000.0 / (double)OutputWaveFormat.SampleRate * (double)audioClient.BufferSize + 0.5); audioClient.Dispose(); audioClient = mmDevice.AudioClient; audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback | audioClientStreamFlags, num2, num2, OutputWaveFormat, Guid.Empty); } } frameEventWaitHandle = new EventWaitHandle(initialState: false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { audioClient.Initialize(shareMode, audioClientStreamFlags, num, 0L, OutputWaveFormat, Guid.Empty); } renderClient = audioClient.AudioRenderClient; } public void Dispose() { if (audioClient != null) { Stop(); audioClient.Dispose(); audioClient = null; renderClient = null; } } } }