Partager via


Exposition de nœuds multicanaux

Dans les versions de Microsoft Windows antérieures à Windows XP, les pilotes audio WDM ne disposent pas d’un moyen simplifié d’exposer les nœuds multicanal des types suivants :

KSNODETYPE_VOLUME

KSNODETYPE_MUTE

KSNODETYPE_TONE

En particulier, aucun mécanisme n’existe pour interroger explicitement un nœud pour connaître le nombre de canaux qu’il prend en charge. Bien qu’il existe des solutions de contournement pour ce problème, elles présentent des inconvénients. Par exemple, un client peut utiliser la propriété KSPROPERTY_AUDIO_VOLUMELEVEL pour interroger de manière itérative un nœud de volume (KSNODETYPE_VOLUME) pour le niveau de volume de chaque canal (0, 1, etc.) jusqu’à ce que la demande retourne une erreur indiquant qu’il n’existe plus de canaux. Toutefois, cette technique nécessite plusieurs requêtes et est trop inefficace pour gérer les appareils audio multicanal plus récents. Dans Windows XP et les systèmes d’exploitation ultérieurs, cette limitation est résolue en définissant deux bits d’indicateur supplémentaires dans le membre Flags de la structure KSPROPERTY_MEMBERSHEADER , que le gestionnaire de propriétés génère en réponse à une requête de prise en charge de base :

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL

    Lors d’une demande de propriété de support de base sur un nœud, le gestionnaire définit ce bit d’indicateur pour indiquer que le membre MembersCount de KSPROPERTY_MEMBERSHEADER contient le nombre de canaux pris en charge par le nœud. Pour les systèmes d’exploitation Windows Vista et ultérieurs, cet indicateur doit être défini pour chaque propriété de canal.

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM

    Le gestionnaire effectue une opération OR au niveau du bit entre ce bit d’indicateur et le bit d’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL pour indiquer qu’une valeur de propriété unique est appliquée uniformément sur tous les canaux d’un nœud. Par exemple, si le matériel ne fournit qu’un seul contrôle au niveau du volume pour tous les canaux, le gestionnaire de prise en charge de base du nœud de volume définit l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM pour indiquer cette restriction. Si cet indicateur n’est pas défini, le niveau de volume de chaque canal peut être contrôlé indépendamment des niveaux de volume des autres canaux.

    Note L’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM n’est pas utilisé par le système d’exploitation Windows Vista.

Dans les pilotes miniport pour Windows XP et versions ultérieures, le gestionnaire de propriétés d’un nœud de volume multicanal doit définir le KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL bit en réponse à une KSPROPERTY_AUDIO_VOLUMELEVEL requête de support de base. Le gestionnaire retourne un tableau de structures KSPROPERTY_STEPPING_LONG (une pour chaque canal exposé par le nœud) et définit MembersSize sur sizeof(KSPROPERTY_STEPPING_LONG). Chaque élément de tableau décrit les niveaux de volume minimal et maximal d’un canal, ainsi que le delta entre les valeurs successives dans la plage. Une plage différente peut être spécifiée pour chaque canal individuel afin que les canaux avec des plages non uniformes puissent être exposés correctement. Par exemple, un canal subwoofer peut avoir une plage différente de celle des autres canaux.

L’exemple de code suivant montre comment gérer une requête de prise en charge de base pour une propriété audio avec des valeurs de propriété non uniformes. La variable pDescription de la première ligne de code ci-dessous pointe vers la structure KSPROPERTY_DESCRIPTION au début de la mémoire tampon de données dans laquelle le gestionnaire écrit les informations de prise en charge de base :

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

La figure suivante montre la disposition de la mémoire tampon de données pour cet exemple. Les pointeurs pDescription, pMembers et pRange pointent vers leurs décalages respectifs dans la mémoire tampon.

Diagramme illustrant la disposition d’une mémoire tampon de données pour une requête de prise en charge de base avec des pointeurs pDescription, pMembers et pRange.

Pour cet exemple, le gestionnaire définit MembersCount sur ulNumChannels, le nombre de canaux. La taille en octets du tableau de plages est

MembersSize * MembersCount

Notez que si l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM était défini dans cet exemple, le gestionnaire définirait toutes les structures KSPROPERTY_STEPPING_LONG du tableau sur la même plage.

Le gestionnaire de prise en charge de base pour la propriété KSPROPERTY_AUDIO_BASS, KSPROPERTY_AUDIO_TREBLE ou KSPROPERTY_AUDIO_MID d’un nœud de ton fonctionne de la même manière.

Si un nœud multicanal a une propriété avec une valeur de propriété par canal de type BOOL, le gestionnaire de prise en charge de base doit renseigner les valeurs d’un tableau de plages pas à pas. Dans ce cas, le gestionnaire définit les membres sur les valeurs indiquées dans l’exemple de code qui suit. Deux exemples de ce type de propriété sont la propriété KSPROPERTY_AUDIO_MUTE d’un nœud muet la propriété KSPROPERTY_AUDIO_BASS_BOOST d’un nœud tonalité.

L’exemple de code suivant montre comment gérer la demande de prise en charge de base pour un nœud multicanal, dans le cas d’une propriété avec une valeur de propriété par canal de type 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;
  }

Notez que dans l’exemple de code précédent, la boucle FOR utilise un zéro (0) et un (1) pour définir les valeurs minimales et maximales pour les plages par canal. Cela est dû au fait que nous configurons un nœud multicanal avec une valeur de propriété par canal de type BOOL.

Si la propriété canal est uniforme, une opération OR au niveau du bit peut être effectuée entre l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM et l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL et le résultat attribué au membre pMembers-Flags>. Cette valeur est utilisée pour indiquer que le matériel applique uniformément la même valeur de propriété sur tous les canaux d’un nœud.

L’utilisation des indicateurs KSPROPERTY_MEMBER_FLAG_UNIFORM et KSPROPERTY_MEMBER_FLAG_MULTICHANNEL élimine la nécessité de regrouper les canaux en paires et d’exposer un nœud de volume stéréo distinct pour chaque paire de canaux, comme cela est fait dans l’exemple de pilote Ac97 dans le Kit de pilotes Windows (WDK). Étant donné que les versions de Windows antérieures à Windows XP ne prennent pas en charge ces indicateurs, le gestionnaire de prise en charge de base de votre pilote doit utiliser l’interface IPortClsVersion pour interroger la version Portcls.sys afin de déterminer s’il faut utiliser ces indicateurs.

L’analyseur de topologie (dans le pilote système WDMAud en mode noyau, Wdmaud.sys) obtient la topologie d’un périphérique audio à partir de son pilote audio WDM. L’analyseur expose cet appareil en tant qu’appareil de mixage traditionnel via l’API de mélangeur Multimédia Windows héritée. Dans Windows XP et versions ultérieures, WDMAud utilise l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL pour déterminer le nombre de canaux à signaler dans le membre cChannels de la structure MIXERLINE. En outre, si le gestionnaire de prise en charge de base du nœud spécifie l’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, WDMAud définit l’indicateur MIXERCONTROL_CONTROLF_UNIFORM dans la structure MIXERCONTROL correspondante. Grâce à cet indicateur, les applications peuvent déterminer si elles peuvent ajuster chaque canal individuellement ou tous les canaux uniformément via un contrôle master. Pour plus d’informations sur MIXERCONTROL, MIXERLINE et l’API mixer, consultez la documentation Microsoft Windows SDK.

Dans Windows XP et versions ultérieures, le programme de contrôle de volume SndVol32 (voir SysTray et SndVol32) affiche les contrôles pour les appareils multicanaux, comme illustré dans la figure suivante.

Capture d’écran de la boîte de dialogue de contrôle de volume SndVol32 affichant des contrôles pour les appareils multicanal.

Si SndVol32 détecte une ligne qui a plus de deux canaux, il remplace le contrôle panoramique normal par un bouton intitulé Volume de l’orateur, qui apparaît au-dessus du curseur de volume main dans la figure précédente. En cliquant sur le bouton Volume de l’orateur , une boîte de dialogue affichant des contrôles pour tous les canaux d’une ligne particulière s’affiche, comme illustré dans la figure suivante.

Capture d’écran de la boîte de dialogue haut-parleur-volume affichant des contrôles pour tous les canaux et propriétés audio avancées.

Étant donné que l’API mixer expose les canaux par nombre, elle déduit les noms de canal de la configuration de l’orateur actuellement sélectionnée dans la boîte de dialogue Propriétés audio avancées du panneau de configuration multimédia Windows (Mmsys.cpl).

Par exemple, si un appareil expose quatre canaux sur une ligne et que l’utilisateur a sélectionné « Haut-parleurs quadraphoniques », les noms de canal seront « Left » (canal 0), « Right » (canal 1), « Back Left » (canal 2) et « Back Right » (canal 3), comme illustré dans la figure précédente. La modification de la configuration de l’orateur par « Haut-parleurs surround » entraîne un mappage des canaux « Left » (canal 0), « Right » (canal 1), « Front Center » (canal 2) et « Back Center » (canal 3).

Au niveau du pilote, la propriété KSPROPERTY_AUDIO_CHANNEL_CONFIG utilise une valeur de masque de KSAUDIO_SPEAKER_QUAD ou KSAUDIO_SPEAKER_SURROUND pour représenter une configuration d’orateur quadraphonique ou surround, respectivement. Le fichier d’en-tête Ksmedia.h définit ces valeurs comme suit :

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

L’un ou l’autre masque contient quatre bits qui spécifient les positions de l’orateur des quatre canaux. Dans les deux cas, la propriété KSPROPERTY_AUDIO_VOLUMELEVEL identifie ces quatre mêmes canaux en tant que canaux 0, 1, 2 et 3, respectivement.

Si le gestionnaire de prise en charge de base du nœud définit le bit d’indicateur KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, les curseurs affichés dans la boîte de dialogue Volume de l’orateur se déplacent à l’unisson avec les modifications apportées à n’importe quel curseur unique.