Partilhar via


Exposição de Nós Multicanais

Em versões do Microsoft Windows anteriores ao Windows XP, os drivers de áudio WDM não têm uma maneira simplificada de expor nós multicanal dos seguintes tipos:

KSNODETYPE_VOLUME

KSNODETYPE_MUTE

KSNODETYPE_TONE

Em específico, não existe nenhum mecanismo para consultar explicitamente um nó sobre o número de canais que ele suporta. Embora existam soluções alternativas para esse problema, elas têm desvantagens. Por exemplo, um cliente pode usar a propriedade KSPROPERTY_AUDIO_VOLUMELEVEL para consultar iterativamente um nó de volume (KSNODETYPE_VOLUME) para o nível de volume de cada canal--0, 1 e assim por diante--até que a solicitação retorne um erro indicando que não existem mais canais. No entanto, essa técnica requer várias consultas e é muito ineficiente para lidar com dispositivos de áudio multicanal mais recentes. No Windows XP e em sistemas operacionais posteriores, essa limitação é resolvida definindo dois bits de sinalizador adicionais no membro Flags da estrutura KSPROPERTY_MEMBERSHEADER , que o manipulador de propriedades gera em resposta a uma consulta de suporte básico:

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL

    Durante uma solicitação de propriedade de suporte básico em um nó, o manipulador define esse bit de sinalizador para indicar que o membro MembersCount de KSPROPERTY_MEMBERSHEADER contém o número de canais suportados pelo nó. Para o Windows Vista e sistemas operacionais Windows posteriores, esse sinalizador deve ser definido para cada propriedade de canal.

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM

    O manipulador executa uma operação OR bit a bit entre este bit de bandeira e o bit de bandeira KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL para indicar que um único valor de propriedade é aplicado uniformemente a todos os canais em um nó. Por exemplo, se o hardware fornecer apenas um único controle de nível de volume para todos os canais, o gestor de suporte básico do nó de volume definirá o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM para indicar essa restrição. Se este sinalizador não estiver definido, o nível de volume para cada canal pode ser controlado independentemente dos níveis de volume para os outros canais.

    Observação O sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM não é usado pelo sistema operacional Windows Vista.

Em drivers de miniporta para Windows XP e posterior, o manipulador de propriedades para um nó de volume multicanal deve definir o bit de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL em resposta a uma consulta de suporte básico KSPROPERTY_AUDIO_VOLUMELEVEL. O manipulador retorna uma matriz de KSPROPERTY_STEPPING_LONG estruturas - uma para cada canal exposto pelo nó - e define MembersSize para sizeof(KSPROPERTY_STEPPING_LONG). Cada elemento de matriz descreve os níveis de volume mínimo e máximo de um canal e o delta entre valores sucessivos no intervalo. Um intervalo diferente pode ser especificado para cada canal individual para que os canais com intervalos não-uniformes podem ser expostos corretamente. Por exemplo, um canal de subwoofer pode ter um alcance diferente do dos outros canais.

O exemplo de código a seguir mostra como manipular uma consulta de suporte básico para uma propriedade audio com valores de propriedade não uniformes. A variável pDescription na primeira linha de código abaixo aponta para a estrutura KSPROPERTY_DESCRIPTION no início do buffer de dados no qual o manipulador grava as informações de suporte básico:

  //
  // 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);

A figura a seguir mostra o layout do buffer de dados para este exemplo. Os ponteiros pDescription, pMembers e pRange estão mostrados apontando para os seus respetivos deslocamentos dentro do buffer.

Diagrama ilustrando o layout de um buffer de dados para uma consulta de suporte básico com ponteiros pDescription, pMembers e pRange.

Neste exemplo, o manipulador define MembersCount como ulNumChannels, o número de canais. O tamanho em bytes da matriz de intervalo é

Tamanho dos Membros * Contagem de Membros

Observe que, se o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM fosse definido neste exemplo, o manipulador definiria todas as estruturas de KSPROPERTY_STEPPING_LONG na matriz para o mesmo intervalo.

O manipulador de suporte básico para as propriedades KSPROPERTY_AUDIO_BASS, KSPROPERTY_AUDIO_TREBLE ou KSPROPERTY_AUDIO_MID de um nó de tom opera de maneira semelhante.

Se um nó multicanal tiver uma propriedade com um valor de propriedade por canal do tipo BOOL, o manipulador de suporte básico deverá preencher valores para uma matriz de intervalos incrementais. Nesse caso, o manipulador define os membros para os valores mostrados no exemplo de código a seguir. Dois exemplos desse tipo de propriedade são a propriedade KSPROPERTY_AUDIO_MUTE de um nó de silêncio e a propriedade KSPROPERTY_AUDIO_BASS_BOOST de um nó de tonalidade.

O exemplo de código a seguir mostra como lidar com a solicitação de suporte básico para um nó multicanal, no caso de uma propriedade com um valor de propriedade por canal do tipo 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;
  }

Observe que no exemplo de código anterior, o loop FOR usa um zero (0) e um (1) para definir os valores mínimo e máximo para os intervalos por canal. Isso ocorre porque estamos configurando um nó multicanal com um valor de propriedade por canal do tipo BOOL.

Se a propriedade de canal for uniforme, uma operação OR bit a bit pode ser executada entre o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM e o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL, e o resultado atribuído ao membro pMembers->Flags. Esse valor é usado para indicar que o hardware aplica o mesmo valor de propriedade uniformemente em todos os canais em um nó.

Usar os sinalizadores KSPROPERTY_MEMBER_FLAG_UNIFORM e KSPROPERTY_MEMBER_FLAG_MULTICHANNEL elimina a necessidade de agrupar os canais em pares e expor um nó de volume estéreo separado para cada par de canais, como é feito no driver de exemplo Ac97 no Kit de Driver do Windows (WDK). Como as versões do Windows anteriores ao Windows XP não oferecem suporte a esses sinalizadores, o manipulador de suporte básico para seu driver deve usar a interface IPortClsVersion para consultar a versão Portcls.sys a fim de determinar se esses sinalizadores devem ser usados.

O analisador de topologia (no driver de sistema WDMAud no modo kernel, Wdmaud.sys) obtém a topologia de um dispositivo de áudio do seu driver de áudio WDM. O analisador expõe esse dispositivo como um dispositivo misturador tradicional por meio da API de mixer multimídia herdada do Windows. No Windows XP e versões posteriores, o WDMAud usa o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL para determinar o número de canais que devem ser relatados no membro cChannels da estrutura MIXERLINE. Além disso, se o manipulador do suporte básico do nó especificar o sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, o WDMAud definirá o sinalizador MIXERCONTROL_CONTROLF_UNIFORM na estrutura MIXERCONTROL correspondente. Através deste sinalizador, os aplicativos podem determinar se eles podem ajustar cada canal individualmente ou todos os canais uniformemente através de um controle mestre. Para obter mais informações sobre MIXERCONTROL, MIXERLINE e a API do mixer , consulte a documentação do SDK do Microsoft Windows.

No Windows XP e versões posteriores, o programa de controle de volume SndVol32 (consulte SysTray e SndVol32) exibe controles para dispositivos multicanal, conforme mostrado na figura a seguir.

Captura de tela da caixa de diálogo de controle de volume SndVol32 exibindo controles para dispositivos multicanal.

Se o SndVol32 detetar uma linha que tenha mais de dois canais, ele substituirá o controle de panorâmica normal por um botão chamado Volume do alto-falante, que aparece acima do controle deslizante de volume principal na figura anterior. Clicar no botão Volume do alto-falante abrirá uma caixa de diálogo exibindo controles para todos os canais de uma linha específica, conforme mostrado na figura a seguir.

Captura de tela da caixa de diálogo de volume do alto-falante exibindo controles para todos os canais e propriedades avançadas de áudio.

Como a API do mixer expõe canais por número, ela infere os nomes dos canais da configuração do alto-falante que está atualmente selecionada na caixa de diálogo Propriedades avançadas de áudio no painel de controle multimídia do Windows (Mmsys.cpl).

Por exemplo, se um dispositivo expõe quatro canais em uma linha e o usuário selecionou "alto-falantes quadrafônicos", os nomes dos canais serão "Esquerda" (canal 0), "Direita" (canal 1), "Volta à esquerda" (canal 2) e "Volta à direita" (canal 3), como mostrado na figura anterior. Alterar a configuração do alto-falante para "alto-falantes de som surround" resultará em um mapeamento de canal de "Esquerda" (canal 0), "Direita" (canal 1), "Front Center" (canal 2) e "Back Center" (canal 3).

No nível do driver, a propriedade KSPROPERTY_AUDIO_CHANNEL_CONFIG usa um valor de máscara de KSAUDIO_SPEAKER_QUAD ou KSAUDIO_SPEAKER_SURROUND para representar uma configuração de alto-falante quadrafônico ou surround, respectivamente. O arquivo de cabeçalho Ksmedia.h define esses valores da seguinte maneira:

  #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)

Qualquer máscara contém quatro bits que especificam as posições do alto-falante dos quatro canais. Em ambos os casos, a propriedade KSPROPERTY_AUDIO_VOLUMELEVEL identifica esses mesmos quatro canais como canais 0, 1, 2 e 3, respectivamente.

Se o manipulador de suporte básico do nó definir o bit de sinalizador KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, os controles deslizantes mostrados na caixa de diálogo Volume do alto-falante serão movidos em uníssono com as alterações feitas em qualquer controle deslizante único.