IAudioRenderClient
COM公式ドキュメント
IAudioRenderClient インターフェイスは、クライアントがレンダリング エンドポイント バッファーに出力データを書き込むことを可能にします。
メソッド 2
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
レンダリング エンドポイント バッファー内の次に利用可能な領域へのポインターを取得します。呼び出し元はこの領域にデータ パケットを書き込むことができます。
| NumFramesRequested | DWORD | in | 呼び出し元がバッファーの要求領域に書き込む予定のデータ パケット内のオーディオ フレーム数。呼び出しが成功すると、*ppData が指すバッファー領域のサイズは NumFramesRequested で指定されたサイズと一致します。 |
| ppData | BYTE** | out | ポインター変数へのポインター。このメソッドは、呼び出し元がデータ パケットを書き込むバッファー領域の開始アドレスをこの変数に書き込みます。 |
戻り値
メソッドが成功した場合は S_OK を返します。失敗した場合の戻り値には、次の表に示す値が含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
|
GetBuffer がデータ バッファーの取得に失敗し、*ppData は NULL を指します。詳細については「解説」を参照してください。 |
|
| NumFramesRequested の値が、利用可能なバッファー領域(バッファー サイズからパディング サイズを引いた値)を超えています。 | |
| ストリームが排他モードでイベント駆動型バッファリングを使用していますが、クライアントがバッファー サイズと異なるサイズのパケットを取得しようとしました。 | |
| 以前の IAudioRenderClient::GetBuffer 呼び出しがまだ有効です。 | |
| オーディオ エンドポイント デバイスが取り外されたか、オーディオ ハードウェアまたは関連するハードウェア リソースが再構成、無効化、削除、またはその他の理由で使用不能になりました。 | |
|
ストリームのリソースが無効化されました。このエラーは次の理由でスローされることがあります。 - ストリームが中断されている。 - 排他ストリームまたはオフロード ストリームが切断された。 - 排他モードまたはオフロード ストリームを持つパッケージ アプリケーションが休止状態になった。 - 「保護された出力」ストリームが閉じられた。 |
|
| ストリームのリセットが進行中のため、バッファーにアクセスできません。 | |
| Windows オーディオ サービスが実行されていません。 | |
| パラメーター ppData が NULL です。 |
解説(Remarks)
呼び出し元は、バッファー内の利用可能な領域以下のパケット サイズを要求できます(ただし、イベント駆動型バッファリングを使用する排他モード ストリームの場合を除きます。詳細については IAudioClient::Initialize を参照してください)。利用可能な領域とは、単にバッファー サイズから、既に再生キューに入っているバッファー内のデータ量を引いた値です。呼び出し元がバッファーの利用可能な領域を超える NumFramesRequested の値を指定した場合、呼び出しは失敗し、エラー コード AUDCLNT_E_BUFFER_TOO_LARGE を返します。
クライアントは、オーディオ ストリームにグリッチが発生しないよう、十分な量のデータをバッファーに書き込む責任があります。バッファリング要件の詳細については、IAudioClient::Initialize を参照してください。
GetBuffer を呼び出してデータ パケットを取得した後、クライアントはパケットにレンダリング データを書き込み、IAudioRenderClient::ReleaseBuffer メソッドを呼び出してパケットをオーディオ エンジンに引き渡します。
クライアントは、0 以外の任意のサイズのパケットを正常に取得した GetBuffer 呼び出しの後、ReleaseBuffer を呼び出す必要があります。サイズ 0 のパケットを解放するための ReleaseBuffer の呼び出しは、行っても行わなくてもかまいません。
0 以外のパケット サイズの場合、クライアントは GetBuffer と ReleaseBuffer の呼び出しを交互に行う必要があります。各 GetBuffer 呼び出しの後には、対応する ReleaseBuffer 呼び出しが続く必要があります。クライアントが GetBuffer を呼び出してデータ パケットを取得した後は、ReleaseBuffer を呼び出して前のパケットを解放するまで、次のデータ パケットを取得できません。GetBuffer または ReleaseBuffer のいずれかを 2 回以上連続して呼び出すことは許可されておらず、エラー コード AUDCLNT_E_OUT_OF_ORDER で失敗します。
呼び出しの正しい順序を保証するため、GetBuffer 呼び出しと対応する ReleaseBuffer 呼び出しは同じスレッド内で行う必要があります。
オーディオ フレームのサイズは、クライアントが IAudioClient::GetMixFormat メソッドを呼び出して取得する WAVEFORMATEX 構造体の nBlockAlign メンバーで指定されます。
呼び出し元が NumFramesRequested = 0 を設定した場合、メソッドはステータス コード S_OK を返しますが、ppData パラメーターが指す変数には書き込みません。
クライアントは、バッファーを取得する 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 メソッドを呼び出すコード例については、次のトピックを参照してください。
ReleaseBuffer メソッドは、前回の IAudioRenderClient::GetBuffer メソッド呼び出しで取得したバッファー領域を解放します。
| NumFramesWritten | DWORD | in | クライアントがデータ パケットに書き込んだオーディオ フレーム数。このパラメーターの値は、IAudioRenderClient::GetBuffer メソッドに渡された NumFramesRequested パラメーターで指定されたデータ パケットのサイズ以下でなければなりません。 |
| dwFlags | DWORD | in | バッファー構成フラグ。呼び出し元はこのパラメーターに 0 を設定するか、次の _AUDCLNT_BUFFERFLAGS 列挙値(フラグ ビット)を設定できます。 このフラグ ビットが設定されている場合、オーディオ エンジンは、パケットに含まれるデータ値に関係なく、データ パケットを無音を含むものとして扱います。このフラグにより、クライアントがレンダリング バッファーに明示的に無音データを書き込む必要がなくなります。 |
戻り値
メソッドが成功した場合は S_OK を返します。失敗した場合の戻り値には、次の表に示す値が含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| NumFramesWritten の値が、前回の IAudioRenderClient::GetBuffer 呼び出しで指定された NumFramesRequested の値を超えています。 | |
| ストリームが排他モードでイベント駆動型バッファリングを使用していますが、クライアントがバッファー サイズと異なるサイズのパケットを解放しようとしました。 | |
| この呼び出しの前に、対応する IAudioRenderClient::GetBuffer の呼び出しがありませんでした。 | |
| オーディオ エンドポイント デバイスが取り外されたか、オーディオ ハードウェアまたは関連するハードウェア リソースが再構成、無効化、削除、またはその他の理由で使用不能になりました。 | |
|
ストリームのリソースが無効化されました。このエラーは次の理由でスローされることがあります。 - ストリームが中断されている。 - 排他ストリームまたはオフロード ストリームが切断された。 - 排他モードまたはオフロード ストリームを持つパッケージ アプリケーションが休止状態になった。 - 「保護された出力」ストリームが閉じられた。 |
|
| Windows オーディオ サービスが実行されていません。 | |
|
パラメーター dwFlags が有効な値ではありません。 |
解説(Remarks)
クライアントは、直前の IAudioRenderClient::GetBuffer メソッド呼び出しで要求したのと同じ数のフレームを解放する必要があります。このルールの唯一の例外は、クライアントが常に ReleaseBuffer を呼び出して 0 フレームを解放できることです(ただし、ストリームが排他モードでイベント駆動型バッファリングを使用している場合を除きます)。
この動作は、以前に要求した長さ 0 のパケットを「解放」する便利な手段をクライアントに提供します。この場合、ReleaseBuffer の呼び出しは任意です。GetBuffer を呼び出して長さ 0 のパケットを取得した後、クライアントは再度 GetBuffer を呼び出す前に ReleaseBuffer を呼び出さないという選択肢を持ちます。
さらに、直前の GetBuffer 呼び出しで 0 以外のサイズのパケットを取得した場合でも、NumFramesRequested を 0 に設定して ReleaseBuffer を呼び出すと成功します(ただし、ストリームが排他モードでイベント駆動型バッファリングを使用している場合を除きます)。この呼び出しの意味は、クライアントがパケットを解放する前にデータを書き込まなかったということです。したがって、このメソッドはパケットが表すバッファー部分を未使用として扱い、次の GetBuffer 呼び出しでこのバッファー部分を再びクライアントに利用可能にします。
クライアントは、バッファーを取得する GetBuffer 呼び出しと、バッファーを解放する ReleaseBuffer 呼び出しの間に過度の遅延を生じさせないようにする必要があります。オーディオ エンジンの実装は、GetBuffer 呼び出しと対応する ReleaseBuffer 呼び出しが同一のバッファー処理周期内で行われることを前提としています。バッファーの解放を 1 周期を超えて遅延させるクライアントは、サンプル データを失うおそれがあります。
ReleaseBuffer メソッドを呼び出すコード例については、次のトピックを参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IAudioRenderClient "{F294ACFC-3146-4483-A7BF-ADDCA7C260E2}" #usecom global IAudioRenderClient IID_IAudioRenderClient "{}" #comfunc global IAudioRenderClient_GetBuffer 3 int,var #comfunc global IAudioRenderClient_ReleaseBuffer 4 int,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。#define global IID_IAudioRenderClient "{F294ACFC-3146-4483-A7BF-ADDCA7C260E2}" #usecom global IAudioRenderClient IID_IAudioRenderClient "{}" #comfunc global IAudioRenderClient_GetBuffer 3 int,sptr #comfunc global IAudioRenderClient_ReleaseBuffer 4 int,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。