Свойство положения звука

Клиент звукового драйвера использует свойство KSPROPERTY_AUDIO_POSITION для получения и задания текущей позиции в звуковом потоке. Свойство использует структуру KSAUDIO_POSITION для описания текущей позиции. Структура содержит два члена: PlayOffset и WriteOffset.

Элементы PlayOffset и WriteOffset определяют границы области буфера клиента, которая в настоящее время зарезервирована для монопольного использования звукового устройства. Клиент должен предположить, что устройство в настоящее время может обращаться к любым данным, содержащимся в этом регионе. Таким образом, клиент должен обращаться только к тем частям буфера, которые находятся за пределами этой области. Границы области перемещаются по мере продвижения потока.

Если буфер клиента зациклен (то есть тип потока — KSINTERFACE_STANDARD_LOOPED_STREAMING), PlayOffset и WriteOffset являются относительными смещениями буфера. То есть они указываются как смещения байтов от начала зациклованного клиентского буфера. Когда любое из смещений увеличивается до конца буфера, оно переносится в начало буфера. (Смещение в начале буфера равно нулю.) Таким образом, ни один из смещений никогда не превышает размер буфера.

Если буфер клиента не отлочен (т. е. тип потока — KSINTERFACE_STANDARD_STREAMING), playOffset и WriteOffset являются смещениями относительно потока. То есть они указываются как смещения в байтах от начала потока. Эти смещения можно рассматривать как смещения в идеализированном буфере, который содержит весь поток и является непрерывным от начала до конца.

В случае потока отрисовки элемент PlayOffset задает позицию воспроизведения потока, а элемент WriteOffset — позицию записи потока. На следующем рисунке показаны позиции воспроизведения и записи в буфере клиента.

Схема, иллюстрирующая воспроизведение и запись позиций в потоке отрисовки.

Позиция воспроизведения — это смещение в байтах воспроизводимой в данный момент выборки (т. е. выборка, которая заперта на входе цифрового преобразователя или DAC). Позиция записи — это позиция, за которой клиент может безопасно записывать данные в буфер. По мере воспроизведения потока позиции воспроизведения и записи перемещаются слева направо на предыдущем рисунке. Операции записи клиента должны опережать позицию записи. Кроме того, если буфер зациклен, операции записи клиента никогда не должны обгонять позицию воспроизведения.

Хотя драйвер порта WaveCyclic или WavePci использует драйвер miniport для отслеживания позиции воспроизведения, драйвер порта отслеживает позицию записи. Драйверы портов WaveCyclic и WavePci обновляют позицию записи следующим образом:

  • Волновая циклическая

    Каждый раз, когда драйвер порта WaveCyclic вызывает IDmaChannel::CopyTo для копирования нового блока данных в циклический буфер (из клиентского буфера), позиция записи перемещается в расположение (в буфере клиента) последнего байта в блоке данных.

  • WavePci

    По умолчанию каждый раз, когда драйвер miniport WavePci вызывает IPortWavePciStream::GetMapping для получения нового сопоставления (части буфера клиента) и вызов завершается успешно, позиция записи перемещается в расположение (в буфере клиента) последнего байта в новом сопоставлении.

    Если драйвер miniport WavePci переопределяет поведение по умолчанию, указывая смещение предварительной выборки для драйвера порта, текущая позиция записи всегда равна сумме текущей позиции воспроизведения и смещения предварительной выборки. Дополнительные сведения см. в разделе Смещения предварительной выборки.

В случае потока захвата член PlayOffset указывает позицию записи потока, а элемент WriteOffset — позицию чтения потока. На следующем рисунке показаны позиции записи и чтения в буфере клиента.

Схема, иллюстрирующая позиции записи и чтения в потоке захвата.

Позиция записи — это смещение в байтах последней выборки, которую необходимо зафиксировать на выходе аналогово-цифрового преобразователя или ADC. (Эта позиция указывает расположение буфера, в которое подсистема DMA звукового устройства в конечном итоге запишет образец.) Позиция чтения — это позиция, за которой клиент не может безопасно считывать данные из буфера. По мере выполнения записи потока позиции чтения и записи перемещаются слева направо на предыдущем рисунке. Операции чтения клиента должны отследить позицию чтения. Кроме того, если буфер зациклен, операции чтения клиента должны опережать позицию записи.

Хотя драйвер порта WaveCyclic или WavePci использует драйвер miniport для отслеживания позиции записи, драйвер порта отслеживает положение чтения. Драйверы портов WaveCyclic и WavePci обновляют позицию чтения следующим образом:

  • Волновая циклическая

    Каждый раз, когда драйвер порта WaveCyclic вызывает IDmaChannel::CopyFrom для копирования нового блока данных из циклического буфера (в буфер клиента), позиция чтения перемещается в расположение (в буфере клиента) последнего байта в блоке данных.

  • WavePci

    Каждый раз, когда драйвер miniport WavePci вызывает IPortWavePciStream::ReleaseMapping для освобождения ранее полученного сопоставления (части клиентского буфера), позиция чтения перемещается в расположение (в буфере клиента) последнего байта в освобожденном сопоставлении.

Драйверам минипорта не требуется реализовывать подпрограммы обработчика для запросов свойств KSPROPERTY_AUDIO_POSITION. Вместо этого драйверы портов WaveCyclic и WavePci обрабатывают эти запросы от имени драйверов мини-портов. При обработке запроса get-property драйвер порта WaveCyclic или WavePci уже содержит все сведения, необходимые для вычисления значения WriteOffset , но для вычисления значения PlayOffset ему по-прежнему требуются сведения из драйвера miniport. Чтобы получить эти сведения, драйвер порта вызывает метод IMiniportWaveCyclicStream::GetPosition или IMiniportWavePciStream::GetPosition драйвера miniport.

Для потока отрисовки метод GetPosition извлекает позицию воспроизведения — смещение в байтах образца, который в настоящее время воспроизводится через приложение уровня данных. Для потока захвата метод GetPosition извлекает позицию записи — смещение в байтах последней выборки, захватываемой ADC.

Обратите внимание, что значение смещения, полученное вызовом GetPosition , является либо положением воспроизведения, соответствующим сигналу, который в настоящее время передается через разъем динамиков, либо положением записи, соответствующим сигналу, который в настоящее время получается через разъем микрофона. Это не позиция DMA. (Позиция DMA — это смещение в байтах образца, который обработчик DMA в звуковом устройстве в данный момент передает в буфер DMA или из буфера DMA.)

Некоторые аудиоустройства содержат регистр позиции для отслеживания смещения байтов выборки в настоящее время в каждом DAC или ADC. В этом случае метод GetPosition просто извлекает содержимое регистра позиции для соответствующего потока. Другое звуковое оборудование может предоставлять драйверу только позицию DMA. В этом случае метод GetPosition должен обеспечить наилучшую оценку смещения байтов образца в DAC или ADC с учетом текущей позиции DMA и внутренних задержек буферизации устройства.

Хотя обработчик свойств в драйвере порта WaveCyclic или WavePci должен различать зацикланные и нелоупированные буферы, чтобы определить, следует ли обеспечить относительное или относительное буферное смещение байтов, эта информация (т. е. является ли буфер зацикличной или неоткрытой) является прозрачной для драйвера мини-порта.

Метод IMiniportWaveCyclicStream::GetPosition всегда сообщает о позиции относительно буфера воспроизведения или записи, независимо от того, является ли буфер клиента циклическим или неразрывным. Если буфер клиента зациклен, обработчик свойств преобразует положение относительно буфера, указанное драйвером мини-порта, которое выражается как смещение в циклическом буфере, в смещение в буфер клиента, которое затем обработчик записывает в элемент PlayOffset . Если буфер клиента не является отрезвленным, обработчик свойств преобразует позицию воспроизведения относительно буфера в положение воспроизведения, относительное потоком, прежде чем записывать его в элемент PlayOffset .

Метод IMiniportWavePciStream::GetPosition всегда сообщает о положении относительно потока воспроизведения или записи, независимо от того, является ли буфер клиента циклом или неотложным. Если буфер клиента зациклен, обработчик свойств преобразует положение воспроизведения относительно потока в положение воспроизведения относительно буфера (выраженное в виде смещения в буфер клиента), прежде чем записывать его в элемент PlayOffset в структуре KSAUDIO_POSITION в запросе свойства. Если буфер клиента не отлочен, обработчик свойств записывает относительное положение потока в элемент PlayOffset .

Позиция воспроизведения или записи равна нулю сразу после инициализации потока. При переходе в состояние KSSTATE_STOP (см. KSSTATE) положение сбрасывается до нуля. Когда поток останавливается переходом от KSSTATE_RUN к KSSTATE_PAUSE или KSSTATE_ACQUIRE, позиция зависает. Он размораживать при переходе потока из KSSTATE_PAUSE или KSSTATE_ACQUIRE обратно в KSSTATE_RUN.

Примеры реализации методов GetPosition для драйверов miniport WaveCyclic и WavePci см. в примерах аудиодрайверов в комплекте драйверов Windows (WDK).