Поделиться через


Предоставление многоканальных узлов

В версиях Microsoft Windows до Windows XP звуковые драйверы WDM не имеют упрощенного способа предоставления многоканальных узлов следующих типов:

KSNODETYPE_VOLUME

KSNODETYPE_MUTE

KSNODETYPE_TONE

В частности, не существует механизма явного запроса к узлу количества поддерживаемых им каналов. Хотя существуют обходные пути для этой проблемы, они имеют недостатки. Например, клиент может использовать свойство KSPROPERTY_AUDIO_VOLUMELEVEL для итеративного запроса к узлу тома (KSNODETYPE_VOLUME) уровня тома для каждого канала —0, 1 и т. д., пока запрос не вернет ошибку, указывающую на отсутствие каналов. Однако этот метод требует нескольких запросов и слишком неэффективен для обработки новых многоканальных звуковых устройств. В Операционных системах Windows XP и более поздних версий это ограничение устраняется путем определения двух дополнительных битов флагов в элементе Flags структуры KSPROPERTY_MEMBERSHEADER , которые обработчик свойств выводит в ответ на запрос базовой поддержки:

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL

    Во время запроса свойства базовой поддержки на узле обработчик задает этот бит флага, чтобы указать, что член MembersCount KSPROPERTY_MEMBERSHEADER содержит количество каналов, поддерживаемых узлом. Для операционных систем Windows Vista и более поздних версий этот флаг должен быть установлен для каждого свойства канала.

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM

    Обработчик выполняет побитовое или между этим битом флага и битом флага KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL, чтобы указать, что одно значение свойства применяется равномерно по всем каналам в узле. Например, если оборудование предоставляет только один элемент управления на уровне тома для всех каналов, обработчик базовой поддержки для узла тома устанавливает флаг KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, указывающий на это ограничение. Если этот флаг не установлен, уровень громкости для каждого канала можно контролировать независимо от уровней громкости для других каналов.

    Примечание Флаг KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM не используется операционной системой Windows Vista.

В драйверах miniport для Windows XP и более поздних версий обработчик свойств для узла тома с несколькими каналами должен задать бит KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL в ответ на запрос KSPROPERTY_AUDIO_VOLUMELEVEL базовой поддержки. Обработчик возвращает массив KSPROPERTY_STEPPING_LONG структур — по одной для каждого канала, предоставляемого узлом, и задает для MembersSize значение sizeof(KSPROPERTY_STEPPING_LONG). Каждый элемент массива описывает минимальный и максимальный уровни громкости канала, а также разницу между последовательными значениями в диапазоне. Для каждого отдельного канала можно указать отдельный диапазон, чтобы каналы с неоднородными диапазонами можно было правильно предоставлять. Например, канал сабвуфера может иметь диапазон, который отличается от диапазона других каналов.

В следующем примере кода показано, как обрабатывать запрос базовой поддержки для свойства audio с неоднородными значениями свойств. Переменная pDescription в первой строке кода ниже указывает на структуру KSPROPERTY_DESCRIPTION в начале буфера данных, в который обработчик записывает основные сведения о поддержке:

  //
  // Fill in the members header.
  //
  PKSPROPERTY_MEMBERSHEADER pMembers = PKSPROPERTY_MEMBERSHEADER(pDescription + 1);

  pMembers->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
  pMembers->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
  pMembers->MembersCount = ulNumChannels;
  pMembers->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;

  //
  // Fill in the stepped range with the driver default.
  //
  PKSPROPERTY_STEPPING_LONG pRange = PKSPROPERTY_STEPPING_LONG(pMembers + 1);
  pRange->Reserved = 0;

  for (ULONG i=0; i<ulNumChannels; i++)
  {
      pRange[i].Bounds.SignedMinimum = ulChannelMin[i];
      pRange[i].Bounds.SignedMaximum = ulChannelMax[i];
      pRange[i].SteppingDelta = ChannelStepping[i];
  }

  pPropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
                                sizeof(KSPROPERTY_MEMBERSHEADER) + 
                                ulNumChannels * sizeof(KSPROPERTY_STEPPING_LONG);

На следующем рисунке показан макет буфера данных для этого примера. Отображаются указатели pDescription, pMembers и pRange, указывающие на соответствующие смещения в буфере.

Схема, иллюстрирующая макет буфера данных для запроса с базовой поддержкой с указателями pDescription, pMembers и pRange.

В этом примере обработчик задает membersCount в значение ulNumChannels, количество каналов. Размер массива диапазонов в байтах :

MembersSize * MembersCount

Обратите внимание, что если в этом примере был задан флаг KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, обработчик задал бы все структуры KSPROPERTY_STEPPING_LONG массива в одном диапазоне.

Обработчик базовой поддержки для свойства KSPROPERTY_AUDIO_BASS, KSPROPERTY_AUDIO_TREBLE или KSPROPERTY_AUDIO_MID узла тона работает аналогичным образом.

Если узел с несколькими каналами имеет свойство со значением свойства для каждого канала типа BOOL, обработчик базовой поддержки должен заполнять значения для массива диапазонов шагов. В этом случае обработчик задает для членов значения, показанные в следующем примере кода. Двумя примерами этого типа свойства являются свойство KSPROPERTY_AUDIO_MUTE узла отключения звука и свойство KSPROPERTY_AUDIO_BASS_BOOST узла тона.

В следующем примере кода показано, как обрабатывать запрос базовой поддержки для многоканального узла в случае свойства со значением свойства для каждого канала типа BOOL:

  //
  // Fill in the members header.
  //
  PKSPROPERTY_MEMBERSHEADER pMembers = PKSPROPERTY_MEMBERSHEADER(pDescription + 1);

  pMembers->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
  pMembers->MembersSize = sizeof (KSPROPERTY_STEPPING_LONG);
  pMembers->MembersCount = ulNumChannels;
  pMembers->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;

  pPropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
                                sizeof(KSPROPERTY_MEMBERSHEADER) + 
                                ulNumChannels * sizeof(KSPROPERTY_STEPPING_LONG);

  //
  // Fill in the stepped range with values in FOR loop.
  //
  PKSPROPERTY_STEPPING_LONG pRange = PKSPROPERTY_STEPPING_LONG(pMembers + 1);
  pRange->Reserved = 0;

  for (ULONG i=0; i<ulNumChannels; i++)
  {
      pRange[i].Bounds.SignedMinimum = 0;
      pRange[i].Bounds.SignedMaximum = 1;
      pRange[i].SteppingDelta = 1;
  }

Обратите внимание, что в предыдущем примере кода цикл FOR использует ноль (0) и один (1) для задания минимальных и максимальных значений для диапазонов для каждого канала. Это связано с тем, что мы настраиваем многоканальный узел со значением свойства для каждого канала типа BOOL.

Если свойство канала является однородным, можно выполнить побитовую операцию OR между флагом KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM и флагом KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL и результатом, назначенным члену pMembers-Flags>. Это значение используется, чтобы указать, что оборудование равномерно применяет одно и то же значение свойства по всем каналам в узле.

Использование флагов KSPROPERTY_MEMBER_FLAG_UNIFORM и KSPROPERTY_MEMBER_FLAG_MULTICHANNEL избавляет от необходимости группировать каналы по парам и предоставлять отдельный узел стерео тома для каждой пары каналов, как это делается в примере драйвера Ac97 в комплекте драйверов Windows (WDK). Так как версии Windows, предшествующие Windows XP, не поддерживают эти флаги, обработчик базовой поддержки для драйвера должен использовать интерфейс IPortClsVersion для запроса версии Portcls.sys, чтобы определить, следует ли использовать эти флаги.

Средство синтаксического анализа топологии (в системном драйвере WDMAud в режиме ядра Wdmaud.sys) получает топологию звукового устройства из звукового драйвера WDM. Средство синтаксического анализа предоставляет это устройство в качестве традиционного микшера с помощью устаревшего API микшера Windows Multimedia. В Windows XP и более поздних версиях WDMAud использует флаг KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL для определения количества каналов для передачи данных в элементе cChannels структуры MIXERLINE. Кроме того, если обработчик базовой поддержки узла задает флаг KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, WDMAud задает флаг MIXERCONTROL_CONTROLF_UNIFORM в соответствующей структуре MIXERCONTROL. С помощью этого флага приложения могут определить, можно ли настроить каждый канал по отдельности или все каналы равномерно с помощью элемента управления master. Дополнительные сведения о MIXERCONTROL, MIXERLINE и API микшера см. в документации по Microsoft Windows SDK.

В Windows XP и более поздних версиях программа управления громкостью SndVol32 (см . SysTray и SndVol32) отображает элементы управления для многоканальных устройств, как показано на следующем рисунке.

Снимок экрана: диалоговое окно управления громкостью SndVol32 с элементами управления для многоканальных устройств.

Если SndVol32 обнаруживает линию с более чем двумя каналами, она заменяет обычный элемент управления сдвигом кнопкой с меткой Громкость говорящего, которая отображается над ползунком громкости main на предыдущем рисунке. При нажатии кнопки Громкость динамиков откроется диалоговое окно с элементами управления для всех каналов для определенной строки, как показано на следующем рисунке.

Снимок экрана: диалоговое окно громкости динамиков с элементами управления для всех каналов и расширенными свойствами звука.

Так как API микшера предоставляет каналы по номеру, он выводит имена каналов из конфигурации динамиков, выбранной в диалоговом окне Дополнительные свойства звука на панели управления мультимедиа Windows (Mmsys.cpl).

Например, если устройство предоставляет четыре канала в строке и пользователь выбрал "Квадрофонические динамики", названия каналов будут "Left" (канал 0), "Right" (канал 1), "Back Left" (канал 2) и "Back Right" (канал 3), как показано на предыдущем рисунке. Изменение конфигурации динамиков на "Динамики объемного звука" приведет к сопоставлению каналов "Left" (канал 0), "Right" (канал 1), "Front Center" (канал 2) и "Back Center" (канал 3).

На уровне драйвера свойство KSPROPERTY_AUDIO_CHANNEL_CONFIG использует значение маски KSAUDIO_SPEAKER_QUAD или KSAUDIO_SPEAKER_SURROUND для представления конфигурации квадрофонического или объемного динамика соответственно. Файл заголовка Ksmedia.h определяет эти значения следующим образом:

  #define KSAUDIO_SPEAKER_QUAD      (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
                                     SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)

  #define KSAUDIO_SPEAKER_SURROUND  (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
                                     SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)

Любая маска содержит четыре бита, определяющие положение динамиков четырех каналов. В любом случае свойство KSPROPERTY_AUDIO_VOLUMELEVEL определяет эти же четыре канала как каналы 0, 1, 2 и 3 соответственно.

Если обработчик базовой поддержки узла задает бит флага KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, ползунки, показанные в диалоговом окне Громкость динамиков , двигаются в едином режиме с изменениями, внесенными в любой один ползунок.