オーディオの位置プロパティ

オーディオ ドライバーのクライアントは、KSPROPERTY_AUDIO_POSITION プロパティを使用して、オーディオ ストリーム内の現在の位置を取得して設定します。 このプロパティは、KSAUDIO_POSITION 構造体を使用して現在の位置を記述します。 構造体には、PlayOffsetWriteOffset の 2 つのメンバーが含まれています。

PlayOffset メンバーと WriteOffset メンバーは、オーディオ デバイスの排他的な使用のために現在予約されているクライアント バッファーの領域の境界を定義します。 クライアントは、デバイスがこのリージョンに含まれるいずれかのデータに現在アクセスしている可能性があることを前提とする必要があります。 そのため、クライアントは、この領域の外部にあるバッファーの部分にのみアクセスする必要があります。 ストリームが進むにつれて、領域の境界は移動します。

クライアント バッファーがループされている場合 (つまり、ストリームの種類が KSINTERFACE_STANDARD_LOOPED_STREAMING)、PlayOffsetWriteOffset はバッファー相対オフセットとなります。 つまり、これらは、ループされたクライアント バッファーの先頭からのバイト オフセットとして指定されます。 いずれかのオフセットがバッファーの末尾までインクリメントされると、バッファーの先頭までラップされます。 (バッファーの先頭のオフセットは 0 です)。したがって、どちらのオフセットもバッファー サイズを超えることはありません。

クライアント バッファーがループされないる場合 (つまり、ストリームの種類が KSINTERFACE_STANDARD_STREAMING)、PlayOffsetWriteOffset はストリーム相対オフセットとなります。 つまり、ストリームの先頭からのバイト オフセットとして指定されます。 これらのオフセットは、ストリーム全体を含む最初から最後まで連続する理想的なバッファーへの、オフセットと考えることができます。

レンダー ストリームの場合、PlayOffset メンバーはストリームの再生位置を指定し、WriteOffset メンバーはストリームの書き込み位置を指定します。 次の図は、クライアント バッファー内の再生位置と書き込み位置を示しています。

Diagram illustrating play and write positions in a render stream.

再生位置は、現在再生されているサンプルのバイト オフセットです (つまり、デジタルからアナログへのコンバーター (DAC) の入力でラッチされるサンプル)。 書き込み位置は、クライアントがバッファーに安全に書き込むことができる位置です。 ストリームの再生が進むにつれ、上の図の再生位置と書き込み位置が左から右に移動します。 クライアントの書き込みは、常に書き込み位置より前にある必要があります。 さらに、バッファーがループされている場合、クライアントの書き込みは再生位置を超えてはなりません。

WaveCyclic または WavePci ポート ドライバーは、再生位置を追跡するためにミニポート ドライバーに依存していますが、ポート ドライバーは書き込み位置を追跡します。 WaveCyclic および WavePci ポート ドライバーは、書き込み位置を次のように更新します。

  • WaveCyclic

    WaveCyclic ポート ドライバーが IDmaChannel::CopyTo を呼び出して新しいデータ ブロックを (クライアント バッファーから) 循環バッファーにコピーするたびに、書き込み位置はデータ ブロック内の最後のバイトの位置 (クライアント バッファー内) に進みます。

  • WavePci

    既定では、WavePci ミニポート ドライバーが IPortWavePciStream::GetMapping を呼び出して (クライアント バッファーの一部の) 新しいマッピングを取得し、呼び出しが成功するたびに、書き込み位置は新しいマッピングの最後のバイトの位置 (クライアント バッファー内) に進みます。

    WavePci ミニポート ドライバーが、ポート ドライバーへのプリフェッチ オフセットを指定して既定の動作をオーバーライドする場合、現在の書き込み位置は、常に現在の再生位置とプリフェッチ オフセットの合計と等しくなります。 詳細については、「プリフェッチ オフセット」を参照してください。

キャプチャ ストリームの場合、PlayOffset メンバーはストリームの録音位置を指定し、WriteOffset メンバーはストリームの読み取り位置を指定します。 次の図は、クライアント バッファー内の録音と読み取り位置を示しています。

Diagram illustrating record and read positions in a capture stream.

録音位置は、アナログ デジタル コンバータ (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 メンバーに書き込みます。

再生位置または録音位置は、ストリームの初期化直後にゼロになります。 KSSTATE_STOP 状態に遷移すると (KSSTATE を参照)、位置が 0 にリセットされます。 KSSTATE_RUN から KSSTATE_PAUSE または KSSTATE_ACQUIRE への遷移によってストリームが停止すると、位置がフリーズします。 ストリームが KSSTATE_PAUSE または KSSTATE_ACQUIRE から KSSTATE_RUN に戻ると、フリーズは解除します。

WaveCyclic ミニポート ドライバーと WavePci ミニポート ドライバーの GetPosition メソッドの実装例については、Windows Driver Kit (WDK) のサンプル オーディオ ドライバーを参照してください。