Condividi tramite


Esposizione di nodi multicanale

Nelle versioni di Microsoft Windows precedenti a Windows XP, i driver audio WDM non hanno un modo semplificato di esporre nodi multicanale dei tipi seguenti:

KSNODETYPE_VOLUME

KSNODETYPE_MUTE

KSNODETYPE_TONE

In particolare, non esiste alcun meccanismo per eseguire query in modo esplicito su un nodo per il numero di canali supportati. Anche se esistono soluzioni alternative per questo problema, hanno svantaggi. Ad esempio, un client può usare la proprietà KSPROPERTY_AUDIO_VOLUMELEVEL per eseguire un'iterativa query su un nodo del volume (KSNODETYPE_VOLUME) per il livello di volume di ogni canale-0, 1 e così via finché la richiesta non restituisce un errore che indica che non esistono più canali. Tuttavia, questa tecnica richiede più query ed è troppo inefficiente per gestire i dispositivi audio multicanale più recenti. In Windows XP e nei sistemi operativi successivi questa limitazione viene risolta definendo due bit di flag aggiuntivi nel membro Flag della struttura KSPROPERTY_MEMBERSHEADER , che il gestore delle proprietà restituisce in risposta a una query di supporto di base:

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL

    Durante una richiesta di proprietà di base di supporto in un nodo, il gestore imposta questo bit di flag per indicare che il membro MembersCount di KSPROPERTY_MEMBERSHEADER contiene il numero di canali supportati dal nodo. Per Windows Vista e i sistemi operativi Windows successivi, questo flag deve essere impostato per ogni proprietà del canale.

  • KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM

    Il gestore esegue un or bit bit per bit bit tra questo flag e il bit di flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL per indicare che un singolo valore della proprietà viene applicato uniformemente in tutti i canali in un nodo. Ad esempio, se l'hardware fornisce solo un singolo controllo a livello di volume per tutti i canali, il gestore di supporto di base per il nodo del volume imposta il flag di KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM per indicare questa restrizione. Se questo flag non è impostato, il livello del volume per ogni canale può essere controllato indipendentemente dai livelli di volume per gli altri canali.

    Nota Il flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM non viene usato dal sistema operativo Windows Vista.

Nei driver miniport per Windows XP e versioni successive, il gestore delle proprietà per un nodo del volume multicanale deve impostare il bit di KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL in risposta a una query di supporto di base KSPROPERTY_AUDIO_VOLUMELEVEL. Il gestore restituisce una matrice di strutture KSPROPERTY_STEPPING_LONG-uno per ogni canale esposto dal nodo-e imposta MembersSize su sizeof(KSPROPERTY_STEPPING_LONG). Ogni elemento matrice descrive i livelli di volume minimo e massimo di un canale e il delta tra i valori successivi nell'intervallo. È possibile specificare un intervallo diverso per ogni singolo canale in modo che i canali con intervalli non uniformi possano essere esposti correttamente. Ad esempio, un canale di mdf potrebbe avere un intervallo diverso da quello degli altri canali.

Nell'esempio di codice seguente viene illustrato come gestire una query di base per una proprietà audio con valori di proprietà non uniformi. La variabile pDescription nella prima riga di codice seguente punta alla struttura KSPROPERTY_DESCRIPTION all'inizio del buffer dati in cui il gestore scrive le informazioni di 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);

Nella figura seguente viene illustrato il layout del buffer dei dati per questo esempio. I puntatori pDescription, pMember e pRange vengono visualizzati puntando ai rispettivi offset all'interno del buffer.

Diagramma che illustra il layout di un buffer di dati per una query di base con pDescription, pMembers e puntatori pRange.

Per questo esempio, il gestore imposta MembersCount su ulNumChannels, il numero di canali. Le dimensioni in byte della matrice di intervallo sono

MembersSize * MembersCount

Si noti che se il flag di KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM è stato impostato in questo esempio, il gestore imposta tutte le strutture KSPROPERTY_STEPPING_LONG nella matrice nello stesso intervallo.

Il gestore di supporto di base per la KSPROPERTY_AUDIO_BASS di un nodo tono, KSPROPERTY_AUDIO_TREBLE o KSPROPERTY_AUDIO_MID proprietà opera in modo analogo.

Se un nodo multicanale ha una proprietà con un valore di proprietà per canale di tipo BOOL, il gestore del supporto di base deve compilare i valori per una matrice di intervalli di esecuzione. In questo caso, il gestore imposta i membri sui valori visualizzati nell'esempio di codice seguente. Due esempi di questo tipo di proprietà sono la proprietà KSPROPERTY_AUDIO_MUTE di un nodo mute e la proprietà KSPROPERTY_AUDIO_BASS_BOOST di un nodo tono .

Nell'esempio di codice seguente viene illustrato come gestire la richiesta di supporto di base per un nodo multicanale, nel caso di una proprietà con un valore della proprietà per canale di 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;
  }

Si noti che nell'esempio di codice precedente, il ciclo FOR usa zero (0) e uno (1) per impostare i valori minimi e massimi per gli intervalli di canali. Ciò avviee perché si configura un nodo multicanale con un valore di proprietà per canale di tipo BOOL.

Se la proprietà del canale è uniforme, è possibile eseguire un'operazione OR bit per bit tra il flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM e il flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL e il risultato assegnato al membro pMembers-Flags>. Questo valore viene usato per indicare che l'hardware applica lo stesso valore della proprietà in modo uniforme in tutti i canali in un nodo.

L'uso delle KSPROPERTY_MEMBER_FLAG_UNIFORM e dei flag di KSPROPERTY_MEMBER_FLAG_MULTICHANNEL elimina la necessità di raggruppare i canali in coppie ed esporre un nodo di volume stereo separato per ogni coppia di canali, come avviene nel driver di esempio Ac97 nel Driver Kit di Windows (WDK). Poiché le versioni di Windows precedenti a Windows XP non supportano questi flag, il gestore di supporto di base per il driver deve usare l'interfaccia IPortClsVersion per eseguire query per la versione Portcls.sys per determinare se usare questi flag.

Il parser della topologia (nel driver di sistema WDMAud in modalità kernel, Wdmaud.sys) ottiene la topologia di un dispositivo audio dal driver audio WDM. Il parser espone tale dispositivo come dispositivo mixer tradizionale tramite l'API mixer multimediale Windows legacy. In Windows XP e versioni successive WDMAud usa il flag di KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL per determinare il numero di canali da segnalare nel membro cChannels della struttura MIXERLINE. Inoltre, se il gestore di supporto di base del nodo specifica il flag di KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, WDMAud imposta il flag di MIXERCONTROL_CONTROLF_UNIFORM nella struttura MIXERCONTROL corrispondente. Tramite questo flag, le applicazioni possono determinare se possono regolare ogni canale singolarmente o tutti i canali in modo uniforme tramite un controllo master. Per altre informazioni su MIXERCONTROL, MIXERLINE e l'API mixer, vedere la documentazione di Microsoft Windows SDK.

In Windows XP e versioni successive, il programma di controllo del volume SndVol32 (vedere SysTray e SndVol32) visualizza i controlli per i dispositivi multicanale, come illustrato nella figura seguente.

Screenshot della finestra di dialogo Controllo volume SndVol32 che visualizza i controlli per i dispositivi multicanale.

Se SndVol32 rileva una riga con più di due canali, sostituisce il normale controllo panoramica con un pulsante etichettato Volume altoparlante, che viene visualizzato sopra il dispositivo di scorrimento del volume principale nella figura precedente. Facendo clic sul pulsante Volume altoparlante verrà visualizzata una finestra di dialogo che visualizza i controlli per tutti i canali per una determinata riga, come illustrato nella figura seguente.

Screenshot della finestra di dialogo del volume dell'altoparlante che visualizza i controlli per tutti i canali e le proprietà audio avanzate.

Poiché l'API mixer espone i canali in base al numero, inferisce i nomi dei canali dalla configurazione dell'altoparlante attualmente selezionata nella finestra di dialogo Proprietà audio avanzate nel pannello di controllo multimediale di Windows (Mmsys.cpl).

Ad esempio, se un dispositivo espone quattro canali su una riga e l'utente ha selezionato "Altoparlanti quadrafonici", i nomi dei canali saranno "Left" (canale 0), "Right" (channel 1), "Back Left" (canale 2) e "Back Right" (canale 3), come illustrato nella figura precedente. La modifica della configurazione dell'altoparlante in "Altoparlanti audio circondati" comporta un mapping dei canali di "Left" (canale 0), "Right" (canale 1), "Front Center" (canale 2) e "Back Center" (canale 3).

A livello di driver, la proprietà KSPROPERTY_AUDIO_CHANNEL_CONFIG usa rispettivamente un valore di maschera di KSAUDIO_SPEAKER_QUAD o KSAUDIO_SPEAKER_SURROUND per rappresentare una configurazione quadrafonica o circondata dell'altoparlante. Il file di intestazione Ksmedia.h definisce questi valori come indicato di seguito:

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

La maschera contiene quattro bit che specificano le posizioni dell'altoparlante dei quattro canali. In entrambi i casi, la proprietà KSPROPERTY_AUDIO_VOLUMELEVEL identifica rispettivamente gli stessi quattro canali dei canali 0, 1, 2 e 3.

Se il gestore di supporto di base del nodo imposta il bit del flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM, i dispositivi di scorrimento visualizzati nella finestra di dialogo Volume altoparlante si spostano in unisono con le modifiche apportate a qualsiasi dispositivo di scorrimento singolo.