Как получить аудио форматы, поддерживаемые физическим устройством (WinAPI, Windows) - PullRequest
0 голосов
/ 17 мая 2018

У меня есть аудиоустройство (микрофон USB), и я хочу выяснить, какие аудиоформаты оно поддерживает изначально (битовая глубина и частота дискретизации), в OS X есть хорошее свойство Core Audio kAudioStreamPropertyAvailablePhysicalFormats, но мне не удается найти нечто похожее на Windows.

Я знаю, что есть этот вопрос Windows Core Audio Api получает все поддерживаемые форматы на устройстве захвата , но

  • Ответ плохой ... и я не ограничен Windows Core Audio API, мне нужен любой способ.

  • Сама Windows как-то это знает, поэтому, скорее всего, должен быть способ, например, через IOCTL, DirectShow или WMI или что-то еще.

  • Возможно, в Windows есть способ узнать, что он использует для перечисления форматов, но я не знаю, как это сделать.

1 Ответ

0 голосов
/ 18 мая 2018

Hokay, вот пример кода для вас. Информация там, разбросана по сети, но вы должны искать ее. Гугл функции, которые я вызываю ниже и некоторые из странных констант манифеста, чтобы узнать больше Код, написанный в блокноте, может не скомпилироваться.

Приведенный ниже код запрашивает устройство ввода / вывода по умолчанию. Чтобы получить идентификаторы device_id для всех устройств, установленных в любой конкретной системе, позвоните по номеру waveInGetNumDevs или waveOutGetNumDevs и начните отсчет от 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);
}
...