IAudioCaptureClient
COM公式ドキュメント
IAudioCaptureClient インターフェイスを使用すると、クライアントはキャプチャエンドポイントバッファーから入力データを読み取ることができます。
メソッド 3
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
キャプチャエンドポイントバッファー内で次に利用可能なデータパケットへのポインターを取得します。
| ppData | BYTE** | out | クライアントが読み取り可能な次のデータパケットの先頭アドレスを、メソッドが書き込むポインター変数へのポインターです。 |
| pNumFramesToRead | DWORD* | out | メソッドがフレーム数(データパケット内で利用可能なオーディオフレームの数)を書き込む UINT32 変数へのポインターです。クライアントはデータパケット全体を読み取るか、まったく読み取らないかのいずれかにする必要があります。 |
| pdwFlags | DWORD* | out | メソッドがバッファーステータスフラグを書き込む DWORD 変数へのポインターです。メソッドは 0、または次の _AUDCLNT_BUFFERFLAGS 列挙値のうち 1 つ以上のビット単位 OR の組み合わせのいずれかを書き込みます。 AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR Note AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY フラグは Windows Vista ではサポートされていません。
Windows 7 以降の OS リリースでは、このフラグをグリッチ検出に使用できます。キャプチャストリームを開始するには、クライアントアプリケーションは IAudioClient::Start を呼び出し、続いてループ内で GetBuffer を呼び出して、エンドポイントバッファー内で利用可能なすべてのパケットが読み取られるまでデータパケットを読み取る必要があります。GetBuffer は、ppData が指すバッファー内のグリッチを示すために AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY フラグを設定します。 |
| pu64DevicePosition | ULONGLONG* | outoptional | メソッドがデータパケット内の最初のオーディオフレームのデバイス位置を書き込む UINT64 変数へのポインターです。デバイス位置は、ストリームの先頭からのオーディオフレーム数として表されます。クライアントがデバイス位置を必要としない場合、このパラメーターは NULL にできます。詳細については、「解説」を参照してください。 |
| pu64QPCPosition | ULONGLONG* | outoptional | オーディオエンドポイントデバイスがデータパケット内の最初のオーディオフレームのデバイス位置を記録した時点でのパフォーマンスカウンターの値を、メソッドが書き込む UINT64 変数へのポインターです。メソッドは、この値を *pu64QPCPosition に書き込む前に、カウンター値を 100 ナノ秒単位に変換します。クライアントがパフォーマンスカウンター値を必要としない場合、このパラメーターは NULL にできます。詳細については、「解説」を参照してください。 |
戻り値
戻り値には、以下の表に示す値が含まれますが、これらに限定されません。
| 戻りコード | 説明 |
|---|---|
| 呼び出しは成功し、*pNumFramesToRead は 0 以外であり、パケットが読み取り可能であることを示します。 | |
| 呼び出しは成功し、*pNumFramesToRead は 0 であり、読み取り可能なキャプチャデータがないことを示します。 | |
| Windows 7 以降: GetBuffer がデータバッファーの取得に失敗し、*ppData は NULL を指します。詳細については、「解説」を参照してください。 | |
| 以前の IAudioCaptureClient::GetBuffer 呼び出しがまだ有効です。 | |
| オーディオエンドポイントデバイスが取り外されたか、オーディオハードウェアまたは関連するハードウェアリソースが再構成、無効化、削除、またはその他の理由で使用できなくなりました。 | |
|
ストリームのリソースが無効化されました。このエラーは次の理由でスローされる場合があります。 - ストリームが中断されている。 - 排他ストリームまたはオフロードストリームが切断されている。 - 排他モードまたはオフロードストリームを持つパッケージ化されたアプリケーションが休止状態になっている。 - 「保護された出力」ストリームが閉じられている。 |
|
| ストリームのリセットが進行中のため、バッファーにアクセスできません。 | |
| Windows オーディオサービスが実行されていません。 | |
| パラメーター ppData、pNumFramesToRead、または pdwFlags が NULL です。 |
解説(Remarks)
このメソッドは、キャプチャエンドポイントバッファーから次のデータパケットを取得します。ある時点で、バッファーには読み取り可能なパケットが 0 個、1 個、または複数含まれている場合があります。通常、キャプチャエンドポイントバッファーからデータを読み取るバッファー処理スレッドは、スレッドが実行されるたびに利用可能なすべてのパケットを読み取ります。
オーディオキャプチャストリームの処理中、クライアントアプリケーションは GetBuffer と IAudioCaptureClient::ReleaseBuffer メソッドを交互に呼び出します。クライアントは、1 回の GetBuffer 呼び出しにつき、1 つのデータパケットまでしか読み取ることができません。各 GetBuffer 呼び出しの後、クライアントは ReleaseBuffer を呼び出してパケットを解放してからでないと、次のパケットを取得するために再び GetBuffer を呼び出すことができません。
GetBuffer または ReleaseBuffer のいずれかを 2 回以上連続して呼び出すことは許可されておらず、エラーコード AUDCLNT_E_OUT_OF_ORDER で失敗します。呼び出しの正しい順序を保証するため、GetBuffer 呼び出しとそれに対応する ReleaseBuffer 呼び出しは、同じスレッド内で行う必要があります。
各 GetBuffer 呼び出しでは、呼び出し元はパケット全体を取得するか、まったく取得しないかのいずれかにする必要があります。パケットを読み取る前に、呼び出し元はパケットサイズ(pNumFramesToRead パラメーターを通じて取得可能)を確認して、パケット全体を格納するのに十分な空きがあることを確認できます。
各 ReleaseBuffer 呼び出しでは、呼び出し元はバッファーから読み取ったオーディオフレーム数を報告します。この数は、(0 以外の)パケットサイズか、または 0 のいずれかである必要があります。この数が 0 の場合、次の GetBuffer 呼び出しは、前回の GetBuffer 呼び出しと同じパケットを呼び出し元に提示します。
各 GetBuffer 呼び出しの後、パケット内のデータは、次の ReleaseBuffer 呼び出しがバッファーを解放するまで有効なままです。
クライアントは、0 以外の任意のサイズのパケットを正常に取得した GetBuffer 呼び出しの後に、ReleaseBuffer を呼び出す必要があります。サイズ 0 のパケットを解放するために ReleaseBuffer を呼び出すかどうかは、クライアントの選択に委ねられています。
メソッドは、pu64DevicePosition および pu64QPCPosition 出力パラメーターを通じて、デバイス位置とパフォーマンスカウンターを出力します。これらの値は、データパケット内の最初のオーディオフレームのタイムスタンプを提供します。pdwFlags 出力パラメーターを通じて、メソッドは報告されたデバイス位置が有効かどうかを示します。
メソッドが *pu64DevicePosition に書き込むデバイス位置は、現在スピーカーを通じて再生されている(レンダリングストリームの場合)、またはマイクを通じて録音されている(キャプチャストリームの場合)オーディオフレームの、ストリーム相対の位置です。位置は、ストリームの先頭からのフレーム数として表されます。オーディオストリーム内のフレームのサイズは、ストリーム形式を指定する WAVEFORMATEX(または WAVEFORMATEXTENSIBLE)構造体の nBlockAlign メンバーによって指定されます。オーディオフレームのバイト単位のサイズは、ストリーム内のチャネル数にチャネルあたりのサンプルサイズを掛けたものに等しくなります。たとえば、16 ビットサンプルのステレオ(2 チャネル)ストリームの場合、フレームサイズは 4 バイトです。
GetBuffer が *pu64QPCPosition に書き込むパフォーマンスカウンター値は、QueryPerformanceCounter 関数から取得される生のカウンター値ではありません。t を生のカウンター値、f を QueryPerformanceFrequency 関数から取得される周波数とすると、GetBuffer はパフォーマンスカウンター値を次のように計算します。
*pu64QPCPosition = 10,000,000.t/f
結果は 100 ナノ秒単位で表されます。QueryPerformanceCounter および QueryPerformanceFrequency の詳細については、Windows SDK のドキュメントを参照してください。
現在、新しいパケットが利用できない場合、メソッドは *pNumFramesToRead = 0 を設定し、ステータスコード AUDCLNT_S_BUFFER_EMPTY を返します。この場合、メソッドは ppData、pu64DevicePosition、および pu64QPCPosition パラメーターが指す変数には書き込みません。
クライアントは、パケットを取得する GetBuffer 呼び出しと、パケットを解放する ReleaseBuffer 呼び出しの間に過度の遅延を生じさせないようにする必要があります。オーディオエンジンの実装は、GetBuffer 呼び出しと対応する ReleaseBuffer 呼び出しが、同じバッファー処理期間内に行われることを前提としています。1 期間を超えてパケットの解放を遅延させるクライアントは、サンプルデータを失うリスクがあります。
Windows 7 以降では、エンドポイントバッファーを排他モードで使用するオーディオクライアントに対して、GetBuffer が AUDCLNT_E_BUFFER_ERROR エラーコードを返す場合があります。このエラーは、データパケットが利用できなかったためにデータバッファーが取得されなかったことを示します(*ppData は NULL を受け取ります)。
GetBuffer が AUDCLNT_E_BUFFER_ERROR を返した場合、オーディオサンプルを消費するスレッドは次の処理パスを待つ必要があります。クライアントは、失敗した GetBuffer 呼び出しの回数を記録しておくと有益な場合があります。GetBuffer がこのエラーを繰り返し返す場合、クライアントは IAudioClient::Stop、IAudioClient::Reset を呼び出して現在のクライアントをシャットダウンし、オーディオクライアントを解放した後に、新しい処理ループを開始できます。
例
GetBuffer メソッドを呼び出すコード例については、Capturing a Stream を参照してください。
ReleaseBuffer メソッドは、バッファーを解放します。
| NumFramesRead | DWORD | in | クライアントがキャプチャバッファーから読み取ったオーディオフレームの数です。このパラメーターは、以前に取得したデータパケット内のフレーム数と等しいか、または 0 のいずれかである必要があります。 |
戻り値
メソッドが成功した場合、S_OK を返します。失敗した場合、戻り値には以下の表に示す値が含まれますが、これらに限定されません。
| 戻りコード | 説明 |
|---|---|
| NumFramesRead パラメーターがデータパケットサイズまたは 0 以外の値に設定されています。 | |
| この呼び出しの前に、対応する IAudioCaptureClient::GetBuffer 呼び出しが行われていません。 | |
| オーディオエンドポイントデバイスが取り外されたか、オーディオハードウェアまたは関連するハードウェアリソースが再構成、無効化、削除、またはその他の理由で使用できなくなりました。 | |
|
ストリームのリソースが無効化されました。このエラーは次の理由でスローされる場合があります。 - ストリームが中断されている。 - 排他ストリームまたはオフロードストリームが切断されている。 - 排他モードまたはオフロードストリームを持つパッケージ化されたアプリケーションが休止状態になっている。 - 「保護された出力」ストリームが閉じられている。 |
|
| Windows オーディオサービスが実行されていません。 |
解説(Remarks)
クライアントは、以前に IAudioCaptureClient::GetBuffer メソッドを呼び出して取得したデータパケットの読み取りを終えたときに、このメソッドを呼び出す必要があります。
クライアントが GetBuffer 呼び出しから取得したパケット内のデータは、クライアントが ReleaseBuffer を呼び出してパケットを解放するまで、有効なままであることが保証されています。
各 GetBuffer 呼び出しとそれに対応する ReleaseBuffer 呼び出しの間で、クライアントはデータパケット全体を読み取るか、まったく読み取らないかのいずれかにする必要があります。クライアントが GetBuffer 呼び出しの後にパケット全体を読み取った場合、NumFramesRead をデータパケット内の総フレーム数に設定して ReleaseBuffer を呼び出す必要があります。この場合、次の GetBuffer 呼び出しは新しいデータパケットを生成します。クライアントが GetBuffer 呼び出しの後にパケットからデータをまったく読み取らなかった場合、NumFramesRead を 0 に設定して ReleaseBuffer を呼び出す必要があります。この場合、次の GetBuffer 呼び出しは、前回の GetBuffer 呼び出しと同じデータパケットを生成します。
クライアントが NumFramesRead をパケットサイズまたは 0 以外の任意の値に設定して ReleaseBuffer を呼び出した場合、呼び出しは失敗し、エラーコード AUDCLNT_E_INVALID_SIZE を返します。
クライアントは、バッファーを取得する GetBuffer 呼び出しと、バッファーを解放する ReleaseBuffer 呼び出しの間に過度の遅延を生じさせないようにする必要があります。オーディオエンジンの実装は、GetBuffer 呼び出しと対応する ReleaseBuffer 呼び出しが、同じバッファー処理期間内に行われることを前提としています。1 期間を超えてバッファーの解放を遅延させるクライアントは、サンプルデータを失うリスクがあります。
ReleaseBuffer メソッドを呼び出すコード例については、Capturing a Stream を参照してください。
GetNextPacketSize メソッドは、キャプチャエンドポイントバッファー内の次のデータパケットのフレーム数を取得します。
| pNumFramesInNextPacket | DWORD* | out | メソッドがフレーム数(次のキャプチャパケット内のオーディオフレームの数)を書き込む UINT32 変数へのポインターです。 |
戻り値
メソッドが成功した場合、S_OK を返します。失敗した場合、戻り値には以下の表に示す値が含まれますが、これらに限定されません。
| 戻りコード | 説明 |
|---|---|
| オーディオエンドポイントデバイスが取り外されたか、オーディオハードウェアまたは関連するハードウェアリソースが再構成、無効化、削除、またはその他の理由で使用できなくなりました。 | |
|
ストリームのリソースが無効化されました。このエラーは次の理由でスローされる場合があります。 - ストリームが中断されている。 - 排他ストリームまたはオフロードストリームが切断されている。 - 排他モードまたはオフロードストリームを持つパッケージ化されたアプリケーションが休止状態になっている。 - 「保護された出力」ストリームが閉じられている。 |
|
| Windows オーディオサービスが実行されていません。 | |
| パラメーター pNumFramesInNextPacket が NULL です。 |
解説(Remarks)
このメソッドは共有モードストリームでのみ使用してください。排他モードストリームでは機能しません。
次のデータパケットを取得するために IAudioCaptureClient::GetBuffer メソッドを呼び出す前に、クライアントは GetNextPacketSize を呼び出して次のパケット内のオーディオフレーム数を取得できます。GetNextPacketSize によって報告されるフレーム数は、その GetNextPacketSize 呼び出しに続く GetBuffer 呼び出し(pNumFramesToRead 出力パラメーターを通じて)で取得されるフレーム数と一致します。
パケットは常に整数個のオーディオフレームで構成されます。
GetNextPacketSize は、キャプチャエンドポイントバッファー内のパケットを取得および解放する GetBuffer および IAudioCaptureClient::ReleaseBuffer メソッド呼び出しと同じスレッドで呼び出す必要があります。
GetNextPacketSize メソッドを使用するコード例については、Capturing a Stream を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IAudioCaptureClient "{C8ADBD64-E71E-48A0-A4DE-185C395CD317}" #usecom global IAudioCaptureClient IID_IAudioCaptureClient "{}" #comfunc global IAudioCaptureClient_GetBuffer 3 var,var,var,var,var #comfunc global IAudioCaptureClient_ReleaseBuffer 4 int #comfunc global IAudioCaptureClient_GetNextPacketSize 5 var ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。#define global IID_IAudioCaptureClient "{C8ADBD64-E71E-48A0-A4DE-185C395CD317}" #usecom global IAudioCaptureClient IID_IAudioCaptureClient "{}" #comfunc global IAudioCaptureClient_GetBuffer 3 sptr,sptr,sptr,sptr,sptr #comfunc global IAudioCaptureClient_ReleaseBuffer 4 int #comfunc global IAudioCaptureClient_GetNextPacketSize 5 sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。