C# 使用 Core Audio APIs 获取音频设备信息

本文介绍了如何在C#中利用Core Audio APIs获取音频设备信息,包括实例化接口的奇妙操作,以及实现音量控制和设备选择的代码示例。附录中提供了Com接口的P/Invoke封装。
摘要由CSDN通过智能技术生成

1. 开头

最一开始写这个的目的是为了控制播放和输出设备的音量,开启静音等。但是,在使用C#调用Com的时候发现了一个神奇的事情。

// IMMDeviceEnumerator 为接口
IMMDeviceEnumerator mMDeviceEnumerator = new IMMDeviceEnumerator();

没错,可以实例化一个接口?神奇的操作😃。

所以,这篇的主要目的是写为什么可以实例化一个接口这么神奇的操作。接下来会写怎么操作音量,还有怎么选择默认设备😋

想看实现获取音频设备列表 代码的直接看 下面, 想看为什么能实例化一个接口的可以直接看最后。

2. 功能代码实现

Com接口的相关P/Invoke 封装看附录

 		static PROPERTYKEY PKEY_DeviceInterface_FriendlyName = new PROPERTYKEY() {
    fmtid = new Guid(0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22), pid = 2 };  //PKEY_DeviceInterface_FriendlyName
        static PROPERTYKEY PKEY_Device_FriendlyName = new PROPERTYKEY() {
    fmtid = new Guid(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 14 }; //PKEY_Device_FriendlyName
		static void Main(string[] args)
        {
   

            IMMDeviceEnumerator mMDeviceEnumerator = new IMMDeviceEnumerator();
            IMMDeviceCollection deviceCollection;
            mMDeviceEnumerator.EnumAudioEndpoints(EDataFlow.eRender, DeviceState.All, out deviceCollection);

            uint count = 0;
            deviceCollection.GetCount(out count);
            Console.WriteLine(count);
            for (uint i = 0; i < count; i++)
            {
   
                deviceCollection.Item(i, out IMMDevice device);
                device.GetId(out string id);
                Console.WriteLine(id);

                device.GetState(out uint state);
                Console.WriteLine(state);

                device.OpenPropertyStore(StorageAccessMode.Read, out IPropertyStore property);


                PROPVARIANT pROPVARIANT = new PROPVARIANT();
                property.GetValue(ref PKEY_Device_FriendlyName, out pROPVARIANT);
                Console.WriteLine(pROPVARIANT.Value);

            }

        }

3 关于神奇操作的分析

最简单的一句话 就是 CoClass 这个attribute 使用这个之后 编译器会将

IMMDeviceEnumerator mMDeviceEnumerator = new IMMDeviceEnumerator();

理解为

IMMDeviceEnumerator mMDeviceEnumerator = (IMMDeviceEnumerator) Activator.CreateInstance(Type.GetTypeFromCLSID
        (new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")));

在这里插入图片描述

如果,这篇文章的理解有错误,欢迎指正。

相关解析可以参考:

How does the C# compiler detect COM types?
FAKING COM TO FOOL THE C# COMPILER

附录

相关P/Invoke封装

       #region Struct
        public struct WAVEFORMATEX
        {
   
            ushort wFormatTag;         /* format type */
            ushort nChannels;          /* number of channels (i.e. mono, stereo...) */
            uint nSamplesPerSec;     /* sample rate */
            uint nAvgBytesPerSec;    /* for buffer estimation */
            ushort nBlockAlign;        /* block size of data */
            ushort wBitsPerSample;     /* number of bits per sample of mono data */
            ushort cbSize;             /* the count in bytes of the size of */
            /* extra information (after cbSize) */
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct PROPERTYKEY
        {
   
            public Guid fmtid;
            public uint pid;
        }
        public struct BLOB
        {
   
            public uint cbSize;
            /* [size_is] */
            public IntPtr/* BYTE* */ pBlobData;
        }


        [StructLayout(LayoutKind.Explicit)]
        public struct PROPVARIANT
        {
   
            /// <summary>
            /// Value type tag.
            /// </summary>
            [FieldOffset(0)] public short vt;
            /// <summary>
            /// Reserved1.
            /// </summary>
            [FieldOffset(2)] public short wReserved1;
         
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值