다음을 통해 공유


오디오 위치 속성

오디오 드라이버의 클라이언트는 KSPROPERTY_AUDIO_POSITION 속성을 사용하여 오디오 스트림에서 현재 위치를 가져와서 설정합니다. 이 속성은 KSAUDIO_POSITION 구조를 사용하여 현재 위치를 설명합니다. 구조체에는 PlayOffset 및 WriteOffset 의 두 멤버 가 포함됩니다.

PlayOffsetWriteOffset 멤버는 오디오 디바이스의 전용 사용을 위해 현재 예약된 클라이언트 버퍼 영역의 경계를 정의합니다. 클라이언트는 디바이스가 현재 이 지역에 포함된 데이터에 액세스할 수 있다고 가정해야 합니다. 따라서 클라이언트는 이 지역 외부에 있는 버퍼 부분만 액세스해야 합니다. 스트림이 진행되면서 영역의 경계가 이동합니다.

클라이언트 버퍼가 루프되는 경우(즉, 스트림 형식이 KSINTERFACE_STANDARD_LOOPED_STREAMING), PlayOffsetWriteOffset 은 버퍼 상대 오프셋입니다. 즉, 루프된 클라이언트 버퍼의 시작부터 바이트 오프셋으로 지정됩니다. 오프셋 중 하나가 버퍼의 끝에 도달하면, 버퍼의 시작 부분으로 순환됩니다. (버퍼의 시작 부분에 있는 오프셋은 0입니다.) 따라서 두 오프셋 모두 버퍼 크기를 초과하지 않습니다.

클라이언트 버퍼가 없는 경우(즉, 스트림 형식이 KSINTERFACE_STANDARD_STREAMING), PlayOffsetWriteOffset 은 스트림 상대 오프셋입니다. 즉, 스트림 시작부터 바이트 오프셋으로 지정됩니다. 이러한 오프셋은 전체 스트림을 포함하고 처음부터 끝까지 연속되는 이상화된 버퍼에 대한 오프셋으로 생각할 수 있습니다.

렌더링 스트림의 경우 PlayOffset 멤버는 스트림의 재생 위치를 지정하고 WriteOffset 멤버는 스트림의 쓰기 위치를 지정합니다. 다음 그림에서는 클라이언트 버퍼의 재생 및 쓰기 위치를 보여 줍니다.

렌더링 스트림의 재생 및 쓰기 위치를 보여 주는 다이어그램

재생 위치는 현재 재생 중인 샘플의 바이트 오프셋입니다(즉, 디지털-아날로그 변환기 또는 DAC의 입력에 래치되는 샘플). 쓰기 위치는 클라이언트가 버퍼에 안전하게 쓸 수 있는 위치입니다. 스트림이 재생되면 이전 그림에서 재생 및 쓰기 위치가 왼쪽에서 오른쪽으로 이동합니다. 클라이언트의 쓰기는 쓰기 위치보다 앞서 있어야 합니다. 또한 버퍼가 루프 처리되면 클라이언트의 쓰기가 재생 위치를 추월해서는 안 됩니다.

WaveCyclic 또는 WavePci 포트 드라이버는 미니포트 드라이버를 사용하여 재생 위치를 추적하지만 포트 드라이버는 쓰기 위치를 추적합니다. WaveCyclic 및 WavePci 포트 드라이버는 다음과 같이 쓰기 위치를 업데이트합니다.

  • WaveCyclic

    WaveCyclic 포트 드라이버가 IDmaChannel::CopyTo 를 호출하여 새 데이터 블록을 클라이언트 버퍼의 순환 버퍼로 복사할 때마다 쓰기 위치는 데이터 블록의 마지막 바이트 위치(클라이언트 버퍼)로 이동합니다.

  • WavePci

    기본적으로 WavePci 미니포트 드라이버가 IPortWavePciStream::GetMapping 을 호출하여 새 매핑(클라이언트 버퍼의 일부)을 획득하고 호출이 성공할 때마다 쓰기 위치는 새 매핑에서 마지막 바이트의 위치(클라이언트 버퍼)로 이동합니다.

    WavePci 미니포트 드라이버가 포트 드라이버에 대한 프리페치 오프셋을 지정하여 기본 동작을 재정의하는 경우 현재 쓰기 위치는 항상 현재 재생 위치의 합계 및 프리페치 오프셋과 같습니다. 자세한 내용은 프리페치 오프셋을 참조하세요.

캡처 스트림의 경우 PlayOffset 멤버는 스트림의 레코드 위치를 지정하고 WriteOffset 멤버는 스트림의 읽기 위치를 지정합니다. 다음 그림에서는 클라이언트 버퍼의 레코드 및 읽기 위치를 보여 줍니다.

캡처 스트림의 레코드 및 읽기 위치를 보여 주는 다이어그램

기록 위치는 아날로그-디지털 변환기(ADC)의 출력에서 가장 최근에 래치된 샘플의 바이트 오프셋입니다. (이 위치는 오디오 디바이스의 DMA 엔진이 결국 샘플을 쓸 버퍼 위치를 지정합니다.) 읽기 위치는 클라이언트가 버퍼에서 안전하게 읽을 수 없는 위치입니다. 스트림의 기록이 진행되면 이전 그림에서 읽기 및 레코드 위치가 왼쪽에서 오른쪽으로 이동합니다. 클라이언트의 읽기는 읽기 위치를 따라가야 합니다. 또한 버퍼가 순환된다면 클라이언트의 읽기 작업이 레코드 위치보다 먼저 수행되어야 합니다.

WaveCyclic 또는 WavePci 포트 드라이버는 미니포트 드라이버를 사용하여 레코드 위치를 추적하지만 포트 드라이버는 읽기 위치를 추적합니다. WaveCyclic 및 WavePci 포트 드라이버는 다음과 같이 읽기 위치를 업데이트합니다.

  • WaveCyclic

    WaveCyclic 포트 드라이버가 IDmaChannel::CopyFrom 을 호출하여 순환 버퍼(클라이언트 버퍼)에서 새 데이터 블록을 복사할 때마다 읽기 위치는 데이터 블록의 마지막 바이트 위치(클라이언트 버퍼)로 이동합니다.

  • WavePci

    WavePci 미니포트 드라이버가 IPortWavePciStream::ReleaseMapping 을 호출하여 이전에 획득한 매핑(클라이언트 버퍼의 일부)을 해제할 때마다 읽기 위치는 릴리스된 매핑에서 마지막 바이트의 위치(클라이언트 버퍼)로 이동합니다.

미니포트 드라이버는 KSPROPERTY_AUDIO_POSITION 속성 요청에 대한 처리기 루틴을 구현할 필요가 없습니다. 대신 WaveCyclic 및 WavePci 포트 드라이버는 미니포트 드라이버를 대신하여 이러한 요청을 처리합니다. get-property 요청을 처리할 때 WaveCyclic 또는 WavePci 포트 드라이버에는 WriteOffset 값을 계산하는 데 필요한 모든 정보가 이미 있지만 여전히 PlayOffset 값을 계산하려면 미니포트 드라이버의 정보가 필요합니다. 이 정보를 얻기 위해 포트 드라이버는 미니포트 드라이버의 IMiniportWaveCyclicStream::GetPosition 또는 IMiniportWavePciStream::GetPosition 메서드를 호출합니다.

렌더링 스트림의 경우 GetPosition 메서드는 현재 DAC를 통해 재생 중인 샘플의 바이트 오프셋인 재생 위치를 검색합니다. 캡처 스트림의 경우 GetPosition 메서드는 ADC에서 캡처할 최신 샘플의 바이트 오프셋인 레코드 위치를 검색합니다.

GetPosition 호출에 의해 검색되는 오프셋 값은 현재 스피커 잭을 통해 전송되는 신호에 해당하는 재생 위치이거나 마이크 잭을 통해 현재 수신되는 신호에 해당하는 레코드 위치입니다. DMA 위치가 아닙니다. (DMA 위치는 오디오 디바이스의 DMA 엔진이 현재 DMA 버퍼에서 전송 중인 샘플의 바이트 오프셋입니다.)

일부 오디오 하드웨어에는 현재 각 DAC 또는 ADC에 있는 샘플의 바이트 오프셋을 추적하는 위치 레지스터가 포함되어 있습니다. 이 경우 GetPosition 메서드는 적절한 스트림에 대한 위치 레지스터의 내용을 검색하기만 하면 됩니다. 다른 오디오 하드웨어는 드라이버에 DMA 위치만 제공할 수 있습니다. 이 경우 GetPosition 메서드는 현재 DMA 위치와 디바이스 내부 버퍼링 지연을 고려하여 DAC 또는 ADC에서 샘플의 바이트 오프셋을 가장 잘 예측해야 합니다.

WaveCyclic 또는 WavePci 포트 드라이버의 속성 처리기는 스트림 상대 바이트 오프셋 또는 버퍼 상대 바이트 오프셋을 제공할지 여부를 결정하기 위해 루프된 버퍼와 비루핑 버퍼를 구분해야 하지만 이 세부 정보(즉, 버퍼가 루프되는지 아니면 루프가 없는지 여부)는 미니포트 드라이버에 투명합니다.

IMiniportWaveCyclicStream::GetPosition 메서드는 클라이언트 버퍼가 루프 또는 로프되지 않은지 여부에 관계없이 항상 버퍼 상대 재생 또는 레코드 위치를 보고합니다. 클라이언트 버퍼가 루프될 경우, 속성 처리기는 미니포트 드라이버가 보고한 버퍼 상대 위치를 순환 버퍼의 오프셋으로부터 클라이언트 버퍼의 오프셋으로 변환합니다. 그런 다음 처리기는 변환된 오프셋을 PlayOffset 멤버에 기록합니다. 클라이언트 버퍼가 없는 경우 속성 처리기는 PlayOffset 멤버에 쓰기 전에 버퍼 상대 재생 위치를 스트림 상대 재생 위치로 변환합니다.

IMiniportWavePciStream::GetPosition 메서드는 클라이언트 버퍼가 루프 또는 로프되지 않은지 여부에 관계없이 항상 스트림 상대 재생 또는 레코드 위치를 보고합니다. 클라이언트 버퍼가 루프되는 경우 속성 처리기는 속성 요청의 KSAUDIO_POSITION 구조에서 PlayOffset 멤버에 쓰기 전에 스트림 상대 재생 위치를 버퍼 상대 플레이 위치(클라이언트 버퍼에 오프셋으로 표시됨)로 변환합니다. 클라이언트 버퍼가 없는 경우 속성 처리기는 PlayOffset 멤버에 스트림 상대 위치를 씁니다.

스트림을 초기화한 직후 재생 또는 레코드 위치가 0입니다. KSSTATE_STOP 상태로 전환하면( KSSTATE 참조) 위치가 0으로 다시 설정됩니다. 스트림이 KSSTATE_RUN KSSTATE_PAUSE 또는 KSSTATE_ACQUIRE 전환하여 중지되면 위치가 중지됩니다. 스트림이 KSSTATE_PAUSE 전환되거나 다시 KSSTATE_RUN KSSTATE_ACQUIRE 때 고정되지 않습니다.

WaveCyclic 및 WavePci 미니포트 드라이버에 대한 GetPosition 메서드의 구현 예제는 WDK(Windows 드라이버 키트)의 샘플 오디오 드라이버를 참조하세요.