Propriedade Audio Position

O cliente de um driver de áudio usa a propriedade KSPROPERTY_AUDIO_POSITION para obter e definir a posição atual em um fluxo de áudio. A propriedade usa uma estrutura KSAUDIO_POSITION para descrever a posição atual. A estrutura contém dois membros: PlayOffset e WriteOffset.

Os membros PlayOffset e WriteOffset definem os limites da região do buffer do cliente que está atualmente reservado para o uso exclusivo do dispositivo de áudio. O cliente deve assumir que o dispositivo pode estar acessando qualquer um dos dados contidos nessa região. Portanto, o cliente deve acessar apenas as partes do buffer que estão fora dessa região. Os limites da região se movem à medida que o fluxo avança.

Se o buffer do cliente estiver em loop (ou seja, o tipo de fluxo será KSINTERFACE_STANDARD_LOOPED_STREAMING), PlayOffset e WriteOffset serão deslocamentos relativos ao buffer. Ou seja, eles são especificados como deslocamentos de bytes desde o início do buffer do cliente em loop. Quando um dos incrementos de deslocamento para o final do buffer, ele é encapsulado até o início do buffer. (O deslocamento no início do buffer é zero.) Portanto, nenhum deslocamento excede o tamanho do buffer.

Se o buffer do cliente não for colocado (ou seja, o tipo de fluxo será KSINTERFACE_STANDARD_STREAMING), PlayOffset e WriteOffset serão deslocamentos relativos ao fluxo. Ou seja, eles são especificados como deslocamentos de bytes desde o início do fluxo. Esses deslocamentos podem ser considerados como deslocamentos para um buffer idealizado que contém todo o fluxo e é contíguo do início ao fim.

No caso de um fluxo de renderização, o membro PlayOffset especifica a posição de reprodução do fluxo e o membro WriteOffset especifica a posição de gravação do fluxo. A figura a seguir mostra as posições de reprodução e gravação em um buffer de cliente.

Diagrama ilustrando as posições de reprodução e gravação em um fluxo de renderização.

A posição de reprodução é o deslocamento de bytes do exemplo que está sendo reproduzido no momento (ou seja, o exemplo que está travado na entrada do conversor digital para analógico, ou DAC). A posição de gravação é a posição além da qual o cliente pode gravar com segurança no buffer. À medida que o fluxo é reproduzido, as posições de reprodução e gravação se movem da esquerda para a direita na figura anterior. As gravações do cliente devem ficar à frente da posição de gravação. Além disso, se o buffer estiver em loop, as gravações do cliente nunca deverão ultrapassar a posição de reprodução.

Embora o driver de porta WaveCyclic ou WavePci dependa do driver de miniporto para manter o controle da posição de jogo, o driver de porta mantém o controle da posição de gravação. Os drivers de porta WaveCyclic e WavePci atualizam a posição de gravação da seguinte maneira:

  • WaveCyclic

    Sempre que o driver de porta WaveCyclic chama IDmaChannel::CopyTo para copiar um novo bloco de dados para o buffer cíclico (do buffer do cliente), a posição de gravação avança para o local (no buffer do cliente) do último byte no bloco de dados.

  • WavePci

    Por padrão, sempre que o driver de miniporto WavePci chama IPortWavePciStream::GetMapping para adquirir um novo mapeamento (de uma parte do buffer do cliente) e a chamada é bem-sucedida, a posição de gravação avança para o local (no buffer do cliente) do último byte no novo mapeamento.

    Se o driver de miniporto WavePci substituir o comportamento padrão especificando um deslocamento de pré-busca para o driver de porta, a posição de gravação atual será sempre igual à soma da posição de reprodução atual e ao deslocamento de pré-busca. Para obter mais informações, consulte Deslocamentos de pré-busca.

No caso de um fluxo de captura, o membro PlayOffset especifica a posição do registro do fluxo e o membro WriteOffset especifica a posição de leitura do fluxo. A figura a seguir mostra as posições de registro e leitura em um buffer de cliente.

Diagrama ilustrando as posições de registro e leitura em um fluxo de captura.

A posição do registro é o deslocamento de bytes do exemplo mais recente a ser travado na saída do conversor analógico para digital ou do ADC. (Essa posição especifica o local do buffer no qual o mecanismo de DMA do dispositivo de áudio eventualmente gravará o exemplo.) A posição de leitura é a posição além da qual o cliente não pode ler com segurança do buffer. À medida que a gravação do fluxo progride, as posições de leitura e registro avançam da esquerda para a direita na figura anterior. As leituras do cliente devem seguir a posição de leitura. Além disso, se o buffer estiver em loop, as leituras do cliente deverão ficar à frente da posição do registro.

Embora o driver de porta WaveCyclic ou WavePci dependa do driver de miniporto para manter o controle da posição do registro, o driver da porta mantém o controle da posição de leitura. Os drivers de porta WaveCyclic e WavePci atualizam a posição de leitura da seguinte maneira:

  • WaveCyclic

    Sempre que o driver de porta WaveCyclic chama IDmaChannel::CopyFrom para copiar um novo bloco de dados do buffer cíclico (para o buffer do cliente), a posição de leitura avança para o local (no buffer do cliente) do último byte no bloco de dados.

  • WavePci

    Sempre que o driver de miniporto WavePci chama IPortWavePciStream::ReleaseMapping para liberar um mapeamento adquirido anteriormente (de uma parte do buffer do cliente), a posição de leitura avança para o local (no buffer do cliente) do último byte no mapeamento liberado.

Os drivers de miniporte não precisam implementar rotinas de manipulador para KSPROPERTY_AUDIO_POSITION solicitações de propriedade. Em vez disso, os drivers de porta WaveCyclic e WavePci lidam com essas solicitações em nome de drivers de miniport. Ao lidar com uma solicitação get-property, um driver de porta WaveCyclic ou WavePci já tem todas as informações necessárias para calcular o valor WriteOffset , mas ainda precisa de informações do driver de miniporto para calcular o valor do PlayOffset . Para obter essas informações, o driver de porta chama o método IMiniportWaveCyclicStream::GetPosition ou IMiniportWavePciStream::GetPosition do driver de miniport.

Para um fluxo de renderização, o método GetPosition recupera a posição de reprodução – o deslocamento de bytes do exemplo que está sendo reproduzido no momento por meio do DAC. Para um fluxo de captura, o método GetPosition recupera a posição do registro – o deslocamento de bytes do exemplo mais recente a ser capturado pelo ADC.

Observe que o valor de deslocamento recuperado por uma chamada GetPosition é uma posição de reprodução correspondente ao sinal que está sendo transmitido no momento por meio da tomada do alto-falante ou uma posição de registro correspondente ao sinal que está sendo recebido no momento por meio da tomada do microfone. Não é a posição de DMA. (A posição de DMA é o deslocamento de bytes do exemplo que o mecanismo de DMA no dispositivo de áudio está transferindo atualmente para ou do buffer de DMA.)

Alguns hardwares de áudio contêm um registro de posição para acompanhar o deslocamento de bytes do exemplo atualmente em cada DAC ou ADC, nesse caso, o método GetPosition simplesmente recupera o conteúdo do registro de posição para o fluxo apropriado. Outro hardware de áudio só pode fornecer ao driver a posição de DMA, nesse caso, o método GetPosition deve fornecer uma melhor estimativa do deslocamento de bytes do exemplo no DAC ou no ADC levando em conta a posição atual do DMA e os atrasos de buffer internos no dispositivo.

Embora o manipulador de propriedades no driver de porta WaveCyclic ou WavePci precise distinguir entre buffers looped e não-looped para determinar se deseja fornecer um deslocamento de bytes relativo a um fluxo ou um buffer relativo, esse detalhe (ou seja, se um buffer está em loop ou não conectado) é transparente para o driver de miniporto.

O método IMiniportWaveCyclicStream::GetPosition sempre relata uma posição de reprodução ou registro relativa ao buffer, independentemente de o buffer do cliente ser em loop ou não ser colocado em loop. Se o buffer do cliente estiver em loop, o manipulador de propriedades converterá a posição relativa do buffer relatada pelo driver de miniporto, que é expresso como um deslocamento para o buffer cíclico, em um deslocamento para o buffer do cliente, que o manipulador grava no membro PlayOffset . Se o buffer do cliente não for colocado, o manipulador de propriedades converterá a posição de reprodução relativa ao buffer em uma posição de reprodução relativa ao fluxo antes de gravá-la no membro PlayOffset .

O método IMiniportWavePciStream::GetPosition sempre relata uma posição de reprodução ou registro relativa ao fluxo, independentemente de o buffer do cliente ser em loop ou não ser colocado em loop. Se o buffer do cliente estiver em loop, o manipulador de propriedades converterá a posição de reprodução relativa ao fluxo em uma posição de reprodução relativa ao buffer (expressa como um deslocamento para o buffer do cliente) antes de gravá-la no membro PlayOffset na estrutura KSAUDIO_POSITION na solicitação de propriedade. Se o buffer do cliente não estiver sendo colocado, o manipulador de propriedades gravará a posição relativa ao fluxo no membro PlayOffset .

A posição de reprodução ou registro é zero imediatamente após a inicialização do fluxo. Uma transição para o estado KSSTATE_STOP (consulte KSSTATE) redefine a posição como zero. Quando o fluxo é interrompido por uma transição de KSSTATE_RUN para KSSTATE_PAUSE ou KSSTATE_ACQUIRE, a posição congela. Ele descongela quando o fluxo faz a transição de KSSTATE_PAUSE ou KSSTATE_ACQUIRE de volta para KSSTATE_RUN.

Por exemplo, implementações de métodos GetPosition para drivers de miniporto WaveCyclic e WavePci, consulte os drivers de áudio de exemplo no WDK (Kit de Driver do Windows).