winapi - 如何获取物理设备支持的音频格式(WinAPI、Windows)
问题描述
我有一个音频设备(USB 麦克风),我想找出它本机支持的音频格式(位深度和采样率),在 OS X 上有一个不错的 kAudioStreamPropertyAvailablePhysicalFormats Core Audio 属性,但我找不到类似的东西视窗。
我知道有这个问题Windows Core Audio Api get all supported formats on capture device但是
答案很糟糕......而且我不受 Windows Core Audio API 的限制,我需要任何方法。
Windows 本身不知何故知道它,所以很可能应该有一种方法,例如通过 IOCTL,DirectShow 或 WMI 或其他东西。
可能有一种方法可以在 Windows 上进行 Spy 以找出它用于枚举格式的方法,但我不知道该怎么做。
解决方案
Hokay, here is some sample code for you. The information is out there, scattered around the web, but you have to search for it. Google the functions I call below and some of the weirdo manifest constants to learn more. Code written in Notepad, might not compile.
The code below queries the default input / output device. To get device_id's for all the devices installed on any particular system, call waveInGetNumDevs
or waveOutGetNumDevs
and count up from 0.
#define INITGUID
#include "Ks.h"
#include "KsMedia.h"
#include "mmdeviceapi.h"
// Open a query handle for the default input or output device
// Call Closehandle when done.
static HANDLE QueryOpen (bool input)
{
DWORD device_id, device_status;
DWORD err = (input) ?
waveInMessage ((HWAVEIN) (INT_PTR) WAVE_MAPPER,
DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &device_id, (DWORD_PTR) &device_status) :
waveOutMessage ((HWAVEOUT) (INT_PTR) WAVE_MAPPER,
DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &device_id, (DWORD_PTR) &device_status);
if (err)
return INVALID_HANDLE_VALUE;
DWORD devicePathSize;
DWORD mm_result = (input) ?
waveInMessage ((HWAVEIN) (INT_PTR) device_id, DRV_QUERYDEVICEINTERFACESIZE,
(DWORD_PTR) &devicePathSize, 0) :
waveOutMessage ((HWAVEOUT) (INT_PTR) device_id, DRV_QUERYDEVICEINTERFACESIZE,
(DWORD_PTR) &devicePathSize, 0);
if (mm_result != 0)
return INVALID_HANDLE_VALUE;
/* apparently DRV_QUERYDEVICEINTERFACE returns a unicode interface path, although this is undocumented */
WCHAR *devicePath = (WCHAR *) malloc (devicePathSize);
mm_result = (input) ?
waveInMessage ((HWAVEIN) (INT_PTR) device_id, DRV_QUERYDEVICEINTERFACE,
(DWORD_PTR) devicePath, devicePathSize) :
waveOutMessage ((HWAVEOUT) (INT_PTR) device_id, DRV_QUERYDEVICEINTERFACE,
(DWORD_PTR) devicePath, devicePathSize);
HANDLE result = (mm_result == 0) ? CreateFileW (devicePath, FILE_SHARE_READ | FILE_SHARE_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL) : INVALID_HANDLE_VALUE;
free (devicePath);
return result;
}
// Interrogate the default input / output device (demo code)
void InterrogateDefaultDevice (bool input)
{
HANDLE hQuery = QueryOpen (input);
if (hQuery == INVALID_HANDLE_VALUE)
return;
int pin_count = GetKSFilterPinCount (hQuery);
for (int pinId = 0; pinId < pin_count; ++pinId)
{
KSPIN_COMMUNICATION communication = GetKSFilterPinPropertyCommunication (hQuery, pinId);
KSPIN_DATAFLOW dataflow = GetKSFilterPinPropertyDataflow (h, pinId);
if ((communication == KSPIN_COMMUNICATION_SINK || communication == KSPIN_COMMUNICATION_BOTH) &&
(KSFilterPinPropertyIdentifiersInclude (hQuery, pinId, KSPROPERTY_PIN_INTERFACES,
&KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_STREAMING) ||
KSFilterPinPropertyIdentifiersInclude (hQuery, pinId, KSPROPERTY_PIN_INTERFACES,
&KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_LOOPED_STREAMING)) &&
KSFilterPinPropertyIdentifiersInclude (hQuery, pinId, KSPROPERTY_PIN_MEDIUMS,
&KSMEDIUMSETID_Standard, KSMEDIUM_STANDARD_DEVIO))
{
KSMULTIPLE_ITEM *item = NULL;
if (WdmGetPinPropertyMulti (hQuery, pinId, KSPROPERTY_PIN_DATARANGES, &item))
{
KSDATARANGE_AUDIO *dr = (KSDATARANGE_AUDIO *) (item + 1);
for (ULONG i = 0; i < item->Count; ++i )
{
printf ("%ul - %ul Hz (%ul - %ul bits per sample, upto %ul channels)\n",
dr->MinimumSampleFrequency, dr->MaximumSampleFrequency,
dr->MinimumBitsPerSample, dr->MaximumBitsPerSample, dr->MaximumChannels);
dr = (KSDATARANGE_AUDIO *) ((BYTE *) dr + dr->DataRange.FormatSize);
}
free (item);
}
}
}
CloseHandle (hQuery);
}
推荐阅读
- c# - 我们需要在控制器中使用 async/await 关键字吗?
- python - 如何在不重复代码的情况下覆盖多个类(Python)
- java - 任务“:amplify_core:compileDebugJavaWithJavac”执行失败
- java - 如何在安装应用程序时将应用程序的快捷方式添加到主屏幕?(不使用谷歌游戏商店)
- node.js - 如何让我的函数在地图中返回一个值而不是一个待处理的 Promise?
- reactjs - 如何在 chakra UI 中为 css 变量添加自定义颜色
- caching - Varnish 默认宽限行为
- selenium - Selenium Web 驱动程序在调试 UI 测试时将文本写入其他应用程序,而不是写入所需的 Web 表单
- node.js - 如何使用新的 URL API 获取请求详细信息?
- c - Passing by Struct pointer is returning wrong value