Exposición de nodos multicanal

En versiones de Microsoft Windows anteriores a Windows XP, los controladores de audio WDM no tienen una manera simplificada de exponer nodos multicanal de los siguientes tipos:

KSNODETYPE_VOLUME

KSNODETYPE_MUTE

KSNODETYPE_TONE

En concreto, no existe ningún mecanismo para consultar explícitamente un nodo para el número de canales que admite. Aunque existen soluciones alternativas para este problema, tienen inconvenientes. Por ejemplo, un cliente puede usar la propiedad KSPROPERTY_AUDIO_VOLUMELEVEL para consultar de forma iterativa un nodo de volumen (KSNODETYPE_VOLUME) para el nivel de volumen de cada canal--0, 1, etc. hasta que la solicitud devuelva un error que indica que no existen más canales. Sin embargo, esta técnica requiere varias consultas y es demasiado ineficaz para controlar los dispositivos de audio multicanal más recientes. En Windows XP y sistemas operativos posteriores, esta limitación se resuelve definiendo dos bits de marca adicionales en el miembro Flags de la estructura KSPROPERTY_MEMBERSHEADER , que el controlador de propiedades genera en respuesta a una consulta de soporte técnico básico:

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL

    Durante una solicitud de propiedad de soporte básico en un nodo, el controlador establece este bit de marca para indicar que el miembro MembersCount de KSPROPERTY_MEMBERSHEADER contiene el número de canales que admite el nodo. Para los sistemas operativos Windows Vista y versiones posteriores, esta marca debe establecerse para cada propiedad de canal.

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM

    El controlador realiza un or bit a bit entre este bit de marca y el bit de marca KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL para indicar que un valor de propiedad único se aplica uniformemente en todos los canales de un nodo. Por ejemplo, si el hardware proporciona solo un control de nivel de volumen único para todos los canales, el controlador de soporte básico para el nodo de volumen establece la marca KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM para indicar esta restricción. Si no se establece esta marca, el nivel de volumen de cada canal se puede controlar independientemente de los niveles de volumen de los otros canales.

    Nota El sistema operativo Windows Vista no usa la marca KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM.

En los controladores de minipuerto para Windows XP y versiones posteriores, el controlador de propiedades de un nodo de volumen multicanal debe establecer el bit de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL en respuesta a una consulta de soporte técnico básico de KSPROPERTY_AUDIO_VOLUMELEVEL. El controlador devuelve una matriz de KSPROPERTY_STEPPING_LONG estructuras--uno para cada canal expuesto por el nodo- y establece MembersSize en sizeof(KSPROPERTY_STEPPING_LONG). Cada elemento de matriz describe los niveles de volumen mínimo y máximo de un canal y la diferencia entre los valores sucesivos del intervalo. Se puede especificar un intervalo diferente para cada canal individual para que los canales con intervalos no uniformes se puedan exponer correctamente. Por ejemplo, un canal de subwoofer puede tener un intervalo que difiere del de los otros canales.

En el ejemplo de código siguiente se muestra cómo controlar una consulta de compatibilidad básica para una propiedad de audio con valores de propiedad no uniformes. La variable pDescription en la primera línea de código siguiente apunta a la estructura KSPROPERTY_DESCRIPTION al principio del búfer de datos en el que el controlador escribe la información de soporte técnico básica:

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

En la ilustración siguiente se muestra el diseño del búfer de datos para este ejemplo. Los punteros pDescription, pMembers y pRange se muestran apuntando a sus respectivos desplazamientos dentro del búfer.

Diagrama que ilustra el diseño de un búfer de datos para una consulta de compatibilidad básica con punteros pDescription, pMembers y pRange.

En este ejemplo, el controlador establece MembersCount en ulNumChannels, el número de canales. El tamaño en bytes de la matriz de intervalos es

MembersSize * MembersCount

Tenga en cuenta que si la marca KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM se estableció en este ejemplo, el controlador establecería todas las estructuras de KSPROPERTY_STEPPING_LONG de la matriz en el mismo intervalo.

El controlador de compatibilidad básica para la propiedad KSPROPERTY_AUDIO_BASS, KSPROPERTY_AUDIO_TREBLE o KSPROPERTY_AUDIO_MID de un nodo de tono funciona de forma similar.

Si un nodo multicanal tiene una propiedad con un valor de propiedad por canal de tipo BOOL, el controlador de compatibilidad básica debe rellenar los valores de una matriz de intervalos paso a paso. En este caso, el controlador establece los miembros en los valores que se muestran en el ejemplo de código siguiente. Dos ejemplos de este tipo de propiedad son la propiedad KSPROPERTY_AUDIO_MUTE de un nodo silenciado y la propiedad KSPROPERTY_AUDIO_BASS_BOOST de un nodo de tono.

En el ejemplo de código siguiente se muestra cómo controlar la solicitud de soporte técnico básico para un nodo multicanal, en el caso de una propiedad con un valor de propiedad por canal de 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 en el ejemplo de código anterior, el bucle FOR usa un cero (0) y uno (1) para establecer los valores mínimo y máximo de los intervalos por canal. Esto se debe a que estamos configurando un nodo multicanal con un valor de propiedad por canal de tipo BOOL.

Si la propiedad del canal es uniforme, se puede realizar una operación OR bit a bit entre la marca de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM y la marca de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL y el resultado asignado al miembro pMembers-Flags>. Este valor se usa para indicar que el hardware aplica el mismo valor de propiedad uniformemente en todos los canales de un nodo.

El uso de las marcas KSPROPERTY_MEMBER_FLAG_UNIFORM y KSPROPERTY_MEMBER_FLAG_MULTICHANNEL elimina la necesidad de agrupar los canales en pares y exponer un nodo de volumen estéreo independiente para cada par de canales, como se hace en el controlador de ejemplo Ac97 en el Kit de controladores de Windows (WDK). Dado que las versiones de Windows anteriores a Windows XP no admiten estas marcas, el controlador de soporte técnico básico para el controlador debe usar la interfaz IPortClsVersion para consultar la versión de Portcls.sys con el fin de determinar si se deben usar estas marcas.

El analizador de topología (en el controlador del sistema WDMAud en modo kernel, Wdmaud.sys) obtiene la topología de un dispositivo de audio de su controlador de audio WDM. El analizador expone ese dispositivo como dispositivo mezclador tradicional a través de la API heredada de mezclador multimedia de Windows. En Windows XP y versiones posteriores, WDMAud usa la marca de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL para determinar el número de canales que se van a notificar en el miembro cChannels de la estructura MIXERLINE. Además, si el controlador de compatibilidad básica del nodo especifica la marca de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, WDMAud establece la marca de MIXERCONTROL_CONTROLF_UNIFORM en la estructura MIXERCONTROL correspondiente. A través de esta marca, las aplicaciones pueden determinar si pueden ajustar cada canal individualmente o todos los canales uniformemente a través de un control maestro. Para obtener más información sobre MIXERCONTROL, MIXERLINE y la API de mezclador, consulte la documentación de Microsoft Windows SDK.

En Windows XP y versiones posteriores, el programa de control de volumen SndVol32 (consulte SysTray y SndVol32) muestra controles para dispositivos multicanal, como se muestra en la ilustración siguiente.

Captura de pantalla del cuadro de diálogo control de volumen SndVol32 que muestra controles para dispositivos multicanal.

Si SndVol32 detecta una línea que tiene más de dos canales, reemplaza el control panorámico normal por un botón denominado Volumen del altavoz, que aparece encima del control deslizante del volumen principal de la ilustración anterior. Al hacer clic en el botón Volumen del altavoz , aparecerá un cuadro de diálogo que muestra controles para todos los canales de una línea determinada, como se muestra en la ilustración siguiente.

Captura de pantalla del cuadro de diálogo speaker-volume que muestra controles para todos los canales y propiedades avanzadas de audio.

Dado que la API de mezclador expone canales por número, deduce los nombres de canal de la configuración del altavoz que está seleccionado actualmente en el cuadro de diálogo Propiedades avanzadas de audio en el panel de control multimedia de Windows (Mmsys.cpl).

Por ejemplo, si un dispositivo expone cuatro canales en una línea y el usuario ha seleccionado "Altavoces cuadránfónicos", los nombres de canal serán "Left" (canal 0), "Right" (canal 1), "Back Left" (canal 2) y "Back Right" (canal 3), como se muestra en la ilustración anterior. Al cambiar la configuración del altavoz a "Altavoces envolventes de sonido", se producirá una asignación de canal de "Izquierda" (canal 0), "Derecha" (canal 1), "Front Center" (canal 2) y "Back Center" (canal 3).

En el nivel de controlador, la propiedad KSPROPERTY_AUDIO_CHANNEL_CONFIG usa un valor de máscara de KSAUDIO_SPEAKER_QUAD o KSAUDIO_SPEAKER_SURROUND para representar una configuración de altavoz cuadrática o envolvente, respectivamente. El archivo de encabezado Ksmedia.h define estos valores de la siguiente manera:

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

Cualquiera de las máscaras contiene cuatro bits que especifican las posiciones del altavoz de los cuatro canales. En cualquier caso, la propiedad KSPROPERTY_AUDIO_VOLUMELEVEL identifica estos mismos cuatro canales que los canales 0, 1, 2 y 3, respectivamente.

Si el controlador de compatibilidad básica del nodo establece el bit de marca de KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, los controles deslizantes que se muestran en el cuadro de diálogo Volumen del altavoz se mueven al unísono con los cambios realizados en cualquier control deslizante único.