音声操作パイプラインの初期化
Game Chat 2 はデフォルトではリアルタイム音声操作を有効にしません。 有効にするには、アプリは chat_manager::initialize でaudioManipulationMode パラメーターを設定して、どの形式の音声操作を有効にしたいかを指定する必要があります。
現在、次の音声操作の形式がサポートされており、game_chat_audio_manipulation_mode_flags 列挙型に含まれています。
game_chat_audio_manipulation_mode_flags::none: 音声操作を無効化します。これはデフォルトの構成です。このモードでは、チャット音声は中断されずに流れます。game_chat_audio_manipulation_mode_flags::pre_encode_stream_manipulation: エンコード前の音声操作を有効化します。このモードでは、ローカルユーザーによって生成されたすべてのチャット音声はエンコードされる前に音声操作パイプラインに送られます。アプリがチャット音声データを検査するだけで操作しない場合でも、エンコードされ送信できるように、変更されていない音声バッファを Game Chat 2 に送り返す責任があります。game_chat_audio_manipulation_mode_flags::post_decode_stream_manipulation: デコード後の音声操作を有効化します。このモードでは、リモートユーザーから受信されたすべてのチャット音声は、受信側でデコードされた後、レンダリングされる前に音声操作パイプラインに送られます。アプリがチャット音声データを検査するだけで操作しない場合でも、レンダリングできるように、変更されていない音声バッファをミックスして Game Chat 2 に送り返す責任があります。
音声ストリーム状態変化の処理
Game Chat 2 は、game_chat_stream_state_change 構造体を通じて音声ストリームの状態への更新を提供します。 これらの更新は、どのストリームが更新されたか、およびどのように更新されたかについての情報を格納します。 これらの更新は、chat_manager::start_processing_stream_state_changes() および chat_manager::finish_processing_stream_state_changes() の一対のメソッドを呼び出すことでポーリングできます。それらは、最新のキューに入っているすべての音声ストリーム状態の更新を game_chat_stream_state_change 構造体ポインターの配列として提供します。アプリは配列を反復処理し、各更新を適切に処理する必要があります。 利用可能なすべての game_chat_stream_state_change 更新が処理された後、その配列はchat_manager::finish_processing_stream_state_changes() を介して Game Chat 2 に戻す必要があります。
これは次の例に示されています。
エンコード前チャット音声データの操作
Game Chat 2 は、pre_encode_audio_stream クラスを介してローカルユーザーのエンコード前のチャット音声データへのアクセスを提供します。ストリームのライフタイム
新しい pre_encode_audio_stream インスタンスがアプリで使用できるようになると、state_change_type フィールドが game_chat_stream_state_change_type::pre_encode_audio_stream_created に設定された game_chat_stream_state_change 構造体を通じて配信されます。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームはエンコード前音声操作に利用可能になります。
既存の pre_encode_audio_stream が音声操作に使用できなくなると、アプリは state_change_type フィールドが game_chat_stream_state_change_type::pre_encode_audio_stream_closed に設定された game_chat_stream_state_change 構造体を通じて通知されます。
これは、この音声ストリームに関連付けられたリソースのクリーンアップを開始するアプリのチャンスです。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームはエンコード前音声操作に利用できなくなります。
閉じられた pre_encode_audio_stream がすべてのリソースを返した後、ストリームは破棄され、アプリは state_change_type フィールドが game_chat_stream_state_change_type::pre_encode_audio_stream_destroyed に設定された game_chat_stream_state_change 構造体を通じて通知されます。
このストリームへの参照またはポインターはクリーンアップする必要があります。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームメモリは無効になります。
ストリームユーザー
ストリームに関連付けられたユーザーのリストは、pre_encode_audio_stream::get_users() を使用して検査できます。音声フォーマット
アプリが Game Chat 2 から取得するバッファの音声フォーマットは、pre_encode_audio_stream::get_pre_processed_format() を使用して検査できます。前処理される音声フォーマットはモノラルです。 アプリは、32 ビット浮動小数点、16 ビット整数、および 32 ビット整数として表されるデータを処理する必要があります。 アプリは、エンコードおよび送信のために送信される操作済みバッファの音声フォーマットを、pre_encode_audio_stream::set_processed_format() を使用して Game Chat 2 に通知する必要があります。エンコード前音声ストリームの処理済みフォーマットは、次の前提条件を満たす必要があります。- フォーマットはモノラルである必要があります。
- フォーマットは、32 ビット浮動小数点 Performance Monitor カウンター (PCM)、32 ビット整数 PCM、または 16 ビット整数 PCM フォーマットである必要があります。
- フォーマットのサンプルレートは、プラットフォームに基づく前提条件に従う必要があります。XBOX One ERA および XBOX Series X|S は 8 KHz、12 KHz、16 KHz、および 24 KHz のサンプルレートをサポートします。XBOX One 用ユニバーサル Windows プラットフォーム (UWP) および Windows PC は、8 KHz、12 KHz、16 KHz、24 KHz、32 KHz、44.1 KHz、および 48 KHz のサンプルレートをサポートします。
エンコード前音声の取得と送信
アプリは、pre_encode_audio_stream::get_available_buffer_count() を使用して、処理できる利用可能なバッファの数についてエンコード前音声ストリームに問い合わせできます。この情報は、アプリが最小限のバッファ数が利用可能になるまで音声処理を遅延させたい場合に使用できます。 各エンコード前音声ストリームでキューに入れられるのは 10 バッファのみで、音声の遅延は音声パイプラインにレイテンシを導入します。アプリは、4 バッファ以上をキューに入れる前にエンコード前音声ストリームをドレインすることをお勧めします。get_next_buffer() での音声バッファの取得
アプリは、pre_encode_audio_stream::get_next_buffer() を使用してエンコード前音声ストリームから音声バッファを取得できます。 新しい音声バッファは、平均して 40 ms ごとに 1 回利用可能になります。 このメソッドが返すバッファは、使用が終わったときに pre_encode_audio_stream::return_buffer() に解放する必要があります。 エンコード前音声ストリームでは、任意の時点で最大 10 個のキューに入れられた、または返却されていないバッファが存在できます。 この制限に達すると、未処理のバッファの一部が返却されるまで、ユーザーの音声ソースからキャプチャされる新しいバッファはドロップされます。submit_buffer() での音声バッファの送信
アプリは、pre_encode_audio_stream::submit_buffer() を使用して、検査および操作した音声バッファを Game Chat 2 にエンコードと送信のために送り返せます。Game Chat 2 はインプレースおよびアウトオブプレースの音声操作をサポートしています。pre_encode_audio_stream::submit_buffer() に送信されるバッファは、必ずしも pre_encode_audio_stream::get_next_buffer() から取得されたバッファと同じである必要はありません。
これらの送信されたバッファのプライバシー/権限は、このストリームに関連付けられたユーザーに基づいて適用されます。
40 ms ごとに、このストリームからの次の 40 ms の音声がエンコードおよび送信されます。
音声の途切れを防ぐには、継続的に聞かれるべき音声のバッファを一定のレートでこのストリームに送信する必要があります。
ストリームコンテキスト
アプリは、pre_encode_audio_stream::set_custom_stream_context() および pre_encode_audio_stream::custom_stream_context() を使用して、エンコード前音声ストリームでカスタムのポインターサイズのコンテキスト値を管理できます。これらのカスタムストリームコンテキストは、Game Chat 2 の音声ストリームと補助データ (たとえば、ストリームメタデータやゲーム状態) 間のマッピングを作成するのに役立ちます。例
以下は、1 つの音声処理フレームでエンコード前音声ストリームを使用する方法を示す簡略化されたエンドツーエンドサンプルです。デコード後チャット音声データの操作
Game Chat 2 は、post_decode_audio_source_stream および post_decode_audio_sink_stream クラスを介してデコード後のチャット音声データへのアクセスを提供します。これは、ユーザーが各ローカルのチャット音声受信者ごとにリモートユーザーからの音声を独自に操作できることを意味します。ソースとシンク
エンコード前パイプラインとは異なり、デコード後の音声データを扱うモデルは、post_decode_audio_source_stream と post_decode_audio_sink_stream の 2 つのクラスに分割されています。 リモートユーザーからのデコードされた音声は post_decode_audio_source_stream オブジェクトから取得され、操作されて、レンダリングのために post_decode_audio_sink_stream オブジェクトに送信されます。 これにより、Game Chat 2 のデコード後音声処理パイプラインと役立つ音声ミドルウェアとの統合が可能になります。ストリームのライフタイム
新しい post_decode_audio_source_stream または post_decode_audio_sink_stream インスタンスがアプリで使用できるようになると、それぞれstate_change_type フィールドが game_chat_stream_state_change_type::post_decode_audio_source_stream_created または game_chat_stream_state_change_type::post_decode_audio_sink_stream_created に設定された game_chat_stream_state_change 構造体を通じて配信されます。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームはデコード後音声操作に利用可能になります。
既存の post_decode_audio_source_stream または post_decode_audio_sink_stream が音声操作に使用できなくなると、アプリは、それぞれ state_change_type フィールドが game_chat_stream_state_change_type::post_decode_audio_source_stream_closed または game_chat_stream_state_change_type::post_decode_audio_sink_stream に設定された game_chat_stream_state_change 構造体を通じて通知されます。
これは、この音声ストリームに関連付けられたリソースのクリーンアップを開始するアプリのチャンスです。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームはデコード後音声操作に利用できなくなります。
ソースストリームの場合、これは操作用にバッファがキューに入らなくなることを意味します。
シンクストリームの場合、これは送信されたバッファがもうレンダリングされないことを意味します。
閉じられた post_decode_audio_source_stream または post_decode_audio_sink_stream がすべてのリソースを返した後、ストリームは破棄され、アプリはそれぞれ state_change_type フィールドが game_chat_stream_state_change_type::post_decode_audio_source_stream_destroyed または game_chat_stream_state_change_type::post_decode_audio_sink_stream_destroyed に設定された game_chat_stream_state_change 構造体を通じて通知されます。
このストリームへの参照またはポインターはクリーンアップする必要があります。
このストリーム状態変化が Game Chat 2 に戻された後、音声ストリームメモリは無効になります。
ストリームユーザー
デコード後ソースストリームに関連付けられたリモートユーザーのリストは、post_decode_audio_source_stream::get_users() を使用して検査できます。 デコード後シンクストリームに関連付けられたローカルユーザーのリストは、post_decode_audio_sink_stream::get_users() を使用して検査できます。音声フォーマット
アプリが Game Chat 2 から取得するバッファの音声フォーマットは、post_decode_audio_source_stream::get_pre_processed_format() を使用して検査できます。前処理された音声フォーマットは常にモノラルの 16 ビット整数 PCM です。 アプリは、レンダリングのために送信される操作済みバッファの音声フォーマットを、post_decode_audio_sink_stream::set_processed_format() を使用して Game Chat 2 に通知する必要があります。デコード後音声シンクストリームの処理済みフォーマットは、次の前提条件を満たす必要があります。- フォーマットのチャンネル数は 64 未満である必要があります。
- フォーマットは、16 ビット整数 PCM (最適)、20 ビット整数 PCM (24 ビットコンテナ内)、24 ビット整数 PCM、32 ビット整数 PCM、または 32 ビット浮動小数点 PCM (16 ビット整数 PCM の次に推奨されるフォーマット) である必要があります。
- フォーマットのサンプルレートは、1,000 から 200,000 サンプル/秒の範囲である必要があります。
エンコード後音声の取得と送信
アプリは、post_decode_audio_source_stream::get_available_buffer_count() を使用して、処理できる利用可能なバッファの数についてデコード後音声ソースストリームに問い合わせできます。 この情報は、アプリが最小限のバッファ数が利用可能になるまで音声処理を遅延させたい場合に使用できます。 各デコード後音声ソースストリームでキューに入れられるのは 10 バッファのみで、音声の遅延は音声パイプラインにレイテンシを導入します。アプリは、4 バッファ以上をキューに入れる前にデコード後音声ストリームをドレインすることをお勧めします。get_next_buffer() での音声バッファの取得
アプリは、post_decode_audio_source_stream::get_next_buffer() を使用してデコード後音声ソースストリームから音声バッファを取得できます。新しい音声バッファは、平均して 40 ms ごとに 1 回利用可能になります。 このメソッドが返すバッファは、使用が終わったときに post_decode_audio_source_stream::return_buffer() に解放する必要があります。 デコード後音声ソースストリームでは、任意の時点で最大 10 個のキューに入れられた、または返却されていないバッファが存在できます。 この制限に達すると、未処理のバッファの一部が返却されるまで、リモートユーザーからの新しいデコードされたバッファはドロップされます。submit_buffer() での音声バッファの送信
アプリは、post_decode_audio_sink_stream::submit_mixed_buffer() を使用して、検査および操作したバッファをデコード後音声シンクストリームを通じてレンダリングのために Game Chat 2 に送り返せます。 Game Chat 2 はインプレースおよびアウトオブプレースの音声操作をサポートしています。post_decode_audio_sink_stream::submit_mixed_buffer() に送信されるバッファは、必ずしも post_decode_audio_source_stream::get_next_buffer() から取得されたバッファと同じである必要はありません。
40 ms ごとに、このストリームからの次の 40 ms の音声がレンダリングされます。
音声の途切れを防ぐには、継続的に聞かれるべき音声のバッファを一定のレートでこのストリームに送信する必要があります。
プライバシーとミキシング
デコード後パイプラインのソース-シンクモデルのため、post_decode_audio_source_stream オブジェクトから取得したバッファをミックスし、ミックスされたバッファをレンダリングのために post_decode_audio_sink_stream オブジェクトに送信するのはアプリの責任です。これはまた、適切なプライバシーと権限を強制してミックスを実行することもアプリの責任であることを意味します。 Game Chat 2 は、post_decode_audio_sink_stream::can_receive_audio_from_source_stream() を提供して、この情報のクエリを簡単かつ効率的にします。チャットインジケーター
デコード後音声操作は、各ユーザーのチャットインジケーターの状態に影響しません。 たとえば、リモートユーザーがミュートされている場合、音声はアプリに提供されます。ただし、そのリモートユーザーのチャットインジケーターは引き続きミュートされていることを示します。 リモートユーザーが話しているとき、その音声は提供されます。ただし、アプリがそのユーザーからの音声を含む音声ミックスを提供するかどうかに関係なく、チャットインジケーターは話していることを示します。 UI とチャットインジケーターの詳細については、Game Chat 2 の使用 を参照してください。 音声ミックス内にどのユーザーが存在するかを決定するために追加のアプリ固有の制約を使用する場合、Game Chat 2 が提供するチャットインジケーターを読み取るときに、同じ制約を考慮するのはアプリの責任です。ストリームコンテキスト
アプリは、post_decode_audio_source_stream::set_custom_stream_context および post_decode_audio_source_stream::custom_stream_context メソッドを使用して、デコード後音声ストリームでカスタムのポインターサイズのコンテキスト値を管理できます。 これらのカスタムストリームコンテキストは、Game Chat 2 の音声ストリームと補助データ (たとえば、ストリームメタデータやゲーム状態) 間のマッピングを作成するのに役立ちます。例
以下は、1 つの音声処理フレームでデコード後音声ストリームを使用する方法を示す簡略化されたエンドツーエンドサンプルです。チャットユーザーのライフタイム
リアルタイム音声操作の有効化は、チャットユーザーのライフタイムに影響します。 chat_manager::remove_user(chatUserX) が呼び出された場合、chatUserX によって指される chat_user オブジェクトは、chatUserX を参照するすべての音声ストリームが破棄されるまで有効なままです。
次のシナリオを考えてみてください。
