如何获取物理设备(WinAPI,Windows)支持的音频格式 [英] How to get Audio Formats supported by physical device (WinAPI, Windows)
问题描述
我有一个音频设备(一个USB麦克风),我想找出它本身支持的音频格式(位深度和采样率),在OS X上有一个不错的kAudioStreamPropertyAvailablePhysicalFormats Core Audio属性,但是我无法在Windows上找到类似的内容.
I have an audio device (a USB microphone) and I want to find out what audio formats it supports natively (bit depth & sample rate), on OS X there is a nice kAudioStreamPropertyAvailablePhysicalFormats Core Audio property, but I fail to find something similar on Windows.
我知道有一个问题 Windows Core Audio Api在捕获设备上获取所有受支持的格式,但是
I know there is this question Windows Core Audio Api get all supported formats on capture device but
-
答案是错误的……而且我不受Windows Core Audio API的限制,我需要任何方式.
The answer is bad... and I'm not limited with windows Core Audio APIs, I need any way.
Windows本身以某种方式知道它,因此很可能应该有一种方法,例如通过IOCTL,DirectShow或WMI或其他方式.
Windows itself somehow knows it, so most likely there should be a way, via IOCTL for example, DirectShow or WMI or something else.
可能有一种方法可以让Windows上的间谍发现它用来枚举格式的内容,但我不知道该怎么做.
Probably there is a way to Spy on Windows to find out what it uses to enumerate the formats, but I don't know how to do this.
推荐答案
好的,这是一些示例代码.信息在那里,散布在网络上,但是您必须进行搜索. Google我在下面调用的函数以及一些怪异函数会显示常量以了解更多信息.用记事本编写的代码可能无法编译.
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.
下面的代码查询默认的输入/输出设备.要获取安装在任何特定系统上的所有设备的device_id,请调用waveInGetNumDevs
或waveOutGetNumDevs
并从0开始计数.
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);
}
这篇关于如何获取物理设备(WinAPI,Windows)支持的音频格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!