初始化音频处理管道
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() 检查与流关联的用户列表。音频格式
可以使用 pre_encode_audio_stream::get_pre_processed_format() 检查应用从 Game Chat 2 检索的缓冲区的音频格式。预处理音频格式为单声道。 应用应准备处理表示为 32 位浮点、16 位整数和 32 位整数的数据。 应用必须使用 pre_encode_audio_stream::set_processed_format() 告知 Game Chat 2 提交给它进行编码和传输的已处理缓冲区的音频格式。编码前音频流的已处理格式必须满足以下前置条件。- 格式必须是单声道。
- 格式必须是 32 位浮点性能监视器计数器 (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 可用一次。 此方法返回的缓冲区在使用完毕后必须释放到 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 音频流和辅助数据(例如流元数据和游戏状态)之间创建映射。示例
以下是一个简化的端到端示例,说明如何在一个音频处理帧中使用编码前音频流。处理解码后聊天音频数据
Game Chat 2 通过 post_decode_audio_source_stream 和 post_decode_audio_sink_stream 类提供对解码后聊天音频数据的访问。这意味着用户可以为每个聊天音频的本地接收器唯一地处理来自远程用户的音频。源和接收器
与编码前管道不同,处理解码后音频数据的模型分为两个类:post_decode_audio_source_stream 和 post_decode_audio_sink_stream。 可以从 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() 检查与解码后接收器流关联的本地用户列表。音频格式
可以使用 post_decode_audio_source_stream::get_pre_processed_format() 检查应用从 Game Chat 2 检索的缓冲区的音频格式。预处理音频格式始终为单声道、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 可用一次。 此方法返回的缓冲区在使用完毕后必须释放到 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 音频流和辅助数据(例如流元数据和游戏状态)之间创建映射。示例
以下是一个简化的端到端示例,说明如何在一个音频处理帧中使用解码后音频流。聊天用户生命周期
启用实时音频处理会影响聊天用户的生命周期。 如果调用 chat_manager::remove_user(chatUserX),则chatUserX 指向的 chat_user 对象将保持有效,直到引用 chatUserX 的所有音频流都已被销毁。
考虑以下场景。
