SG Com API 教程
初始化、关闭和日志记录
在使用该库之前,必须使用 SG_COM_Initialize 对其进行初始化;当不再使用该库时,应使用 SG_COM_Shutdown 将其关闭。调用这些函数应该是与 API 的第一次和最后一次交互。
SG_COM_Initialize 采用三个主要参数:日志记录级别 (SG_LoggingLevel)、用于接收日志消息的可选回调 (SG_LoggingCallback) 以及许可证数据。许可证数据可以是许可证文件的路径,或者在非联网许可证的情况下,也可以是加载到内存中的许可证字符串。
创建和销毁引擎和播放器
使用 SG Com 制作角色动画需要引擎和相应的播放器(请参阅引擎和播放器)。
要创建引擎,请使用 SG_COM_CreateEngine,该函数需要引擎配置。要创建播放器,请使用 SG_COM_CreatePlayer,该函数需要播放器配置。
要销毁引擎和播放器,请分别使用 SG_COM_DestroyEngine 和 SG_COM_DestroyPlayer。
引擎配置
SG_COM_EngineConfig 包括以下结构:
角色控制文件,以字节形式加载到内存中。
要输入的音频字节的采样率和采样类型(请参阅引擎输入)。
输入缓冲长度,以输入缓冲可容纳的最大音频时长表示(以秒为单位)(请参阅引擎输入)。该长度应与最长的音频块长度相同。
如果是本地播放器,还可选择相应播放器的句柄(请参阅引擎到播放器的传输)。
SG_COM_EngineBroadcastCallback 函数,每当引擎准备好输出数据包时就会调用该函数。本地播放器不需要该函数(请参阅引擎到播放器的传输)。
SG_COM_EngineStatusCallback 函数,只要引擎状态更新就会调用该函数(请参阅元数据更新)。
播放器配置
SG_COM_PlayerConfig 包括以下结构:
角色控制文件,以字节形式加载到内存中。该文件必须与相应引擎中使用的文件相同。
输出缓冲长度,以输出缓冲可容纳的最大动画时长表示(以秒为单位)。该长度应至少与引擎的输入缓冲区长度相同。也可以配置更长时间,以免播放延迟时更早的动画丢失。
引擎输入
函数 SG_COM_InputAudio 用于将音频输入到引擎中以驱动脸部动画。每次调用 SG_COM_InputAudio 时,都需要提供一个包含一定数量音频样本的字节数组。对于低延迟应用,我们建议在音频可用时立即输入。理想的输入大小为 10 毫秒,因为这是内部处理帧的大小。不过,每个输入包的大小可能会有所不同。上限由您在 SG_COM_EngineConfig.buffer_sec 中指定的缓冲大小决定。
输入音频必须是原始的线性 PCM 单声道音频(请参阅 SG Com 输入),并且采样必须与用于创建引擎的 SG_COM_EngineConfig 一致,特别是 SG_COM_EngineConfig.audio_sample_type 和 SG_COM_EngineConfig.audio_sample_rate。
在某些自定义用例中,您可能还需要 SG_COM_InputAuxData,用于输入辅助(非音频)数据。请注意,辅助数据的采样率始终假定为 100 Hz。
引擎帧处理
使用 SG_COM_InputAudio 或 SG_COM_InputAuxData 输入数据时,不会进行实际处理;输入数据会进入缓冲。为了将输入数据实际处理为动画,必须调用 SG_COM_ProcessTick。该函数将在引擎管道中执行推进一帧输入(10 毫秒)所需的处理。
每输入 10 毫秒的数据就必须至少调用一次引擎帧处理函数。经过 50 毫秒的初始算法延迟后,每次调用 SG_COM_ProcessTick 都将生成一个输出数据包。根据引擎配置的不同,该数据包将被传送到 SG_COM_EngineBroadcastCallback 或直接传送到本地播放器(请参阅引擎到播放器的传输)。
SG_COM_ProcessTick 的设计为在后台线程或线程池中调用。
闲置模式
通常情况下,引擎需要输入才能产生输出。不过,在没有输入的情况下,引擎也可以产生闲置行为,如眨眼、眼球微动和非嘴部表情。要启用闲置行为,请在引擎配置中使用标志 SG_COM_EngineConfigFlag.SG_COM_ENGINE_CONFIG_ENABLE_IDLE。启用闲置模式后,即使没有输入,帧处理也会继续生成输出帧,以闲置动作取代数据驱动的动作。
如果不使用此标志,生成闲置动作的等效方法是使用 SG_COM_InputAudio,并且输入字节全部为零。
闲置动作会与其他输出平滑地融合在一起。当角色进入或离开闲置模式时,动画中不会出现中断或突然变化。
引擎到播放器的传输
引擎的输出数据包必须传送到播放器中。有两种方法可以做到这一点,具体取决于播放器是本地部署还是网络部署(请参阅网络使用的情况与本地使用的情况):
本地使用的情况下,请在引擎配置中提供播放器句柄。引擎的输出数据包将自动输入播放器,无需额外的数据处理。
对于网络使用的情况:
从 SG_COM_EngineBroadcastCallback 获取输出数据包
通过网络传输这些数据包
使用 SG_COM_ReceivePacket 将这些数据包输入远程播放器
动画节点
为了播放输出,首先需要使用 SG_COM_GetAnimationNodes 从播放器获取动画节点。这将提供一个节点数组。每个 SG_AnimationNode 代表 SGX Studio 中定义的角色骨骼控制中的一个对象(请参阅编辑 Speech Graphics 动画控制器)。SG_AnimationNode 的结构包含:
SG_AnimationNode.name,节点的名称
SG_AnimationNode.type,节点的类型(包括 SG_JOINT、SG_BLENDSHAPE 或 SG_CONTROL)
SG_AnimationNode.num_channels,动画通道的数量
SG_AnimationNode.channel_names,包含动画通道名称的数组
SG_AnimationNode.channel_values,包含动画通道当前值的数组
下面的示例展示了如何获取动画节点。
SG_AnimationNode* animation_nodes;
sg_size num_animation_nodes;
SG_COM_GetAnimationNodes(player_handle, &animation_nodes, &num_animation_nodes);
获取动画节点后,必须将节点中的动画通道映射到角色骨骼控制中的相应属性,以便在动画制作过程中将数值从节点快速复制到骨骼控制。因为动画节点不会改变, 这种映射只需在构建播放器后建立一次。
动画播放
要从播放器输出动画,请在应用程序的动画更新循环中定期调用 SG_COM_UpdateAnimation。该函数以时间值作为输入;请参阅同步输出,了解如何保持这些时间值与音频输出同步。
给出一个时间值后,该函数会对播放器中缓冲的动作数据进行采样和解码,生成一帧动画,并将其存储在动画节点的通道中。然后就可以将这些值从动画节点复制到场景中角色骨骼控制的相应属性中。
// Enter the real-time playback loop
float *animation_frame;
for (;;) {
// Update the animation.
err = SG_COM_UpdateAnimation(player_handle, time_ms, ¤t_time_ms);
// Get the current value for each channel of each node
for (size_t i = 0; i<num_animation_nodes; i++) {
for (size_t j = 0; j<animation_nodes[i].num_channels; j++) {
float val = animation_nodes[i].channel_values[j];
// Do something with val.
}
}
}
播放器只包含动画时间轴的有限区间。要检查可播放区间的开始和结束时间,请使用 SG_COM_Get_PlayableRange。该区间的最大时长由播放器配置中指定的输出缓冲时长决定。随着来自引擎的数据不断增加,可播放区间的时间会向前移动(请参阅引擎到播放器的传输)。调用 SG_COM_UpdateAnimation 会将请求的时间剪辑到此范围;因此,获取的动画帧的实际时间值(保存在参数 current_time_ms
中)可能与请求的时间不同。
从 SG_AnimationNode.channel_values 获取的动画值始终是相对于参考姿势的值。因此,通道值应与基准值相加。
使用情绪模式
当您构建新引擎时,角色将处于角色控制文件中标记为“默认”的情绪模式下。要手动更改当前的情绪模式,请使用 SG_COM_SetMode。例如,此调用
SG_COM_SetMode(engine_handle,"angry");
将角色设置为“愤怒”模式。角色将一直保持该模式,直到再次设置或开启自动模式。
情绪模式特定于角色,因此要设置情绪模式,必须知道角色控制文件中提供了哪些情绪模式。例如,在上面的例子中,角色必须定义了情绪模式“愤怒”;如果没有定义,此功能将不起作用。
要获取角色的可用模式列表,请使用 SG_COM_GetModeList。要了解当前激活的情绪模式,请使用 SG_COM_GetMode。
使用自动模式
要使用自动模式,请使用 SG_COM_SetAutoMode 定义映射。例如,下面的代码将 SG_COM_POSITIVE_MODE
映射到“快乐”,将 SG_COM_NEGATIVE_MODE
映射到“愤怒”,将 SG_COM_EFFORT_MODE
映射到“用力声”。
SG_COM_SetAutoMode(engine_handle, SG_COM_POSITIVE_MODE, "happy");
SG_COM_SetAutoMode(engine_handle, SG_COM_NEGATIVE_MODE , "angry");
SG_COM_SetAutoMode(engine_handle, SG_COM_EFFORT_MODE , "effort");
任何未设置为实际情绪模式的自动模式都将无效。要清除所有当前自动模式设置,请使用 SG_COM_UnsetAutoModes。
您还可以设置默认模式,即未检测到自动模式时使用的模式。请使用 SG_COM_SetDefaultMode 执行此操作。
要激活整个自动模式系统,必须调用 SG_COM_ActivateAutoModes。请注意,如果调用 SG_COM_SetMode 手动设置情绪模式,将自动停用自动模式系统。您必须再次调用 SG_COM_ActivateAutoModes 才能重新激活自动模式。在停用和重新激活的过程中,将保留先前设置的自动模式映射。
使用情绪修改器
创建引擎时,引擎的所有情绪修改器都是默认值。要更改修改器的当前设置,请使用 SG_COM_SetModifier。例如,此行会将非嘴部幅值设置为 1.2:
SG_COM_SetModifier(engine_handle, SG_COM_MOD_NONVERBAL_MAG, 1.2);
要获取修改器的当前值,请调用 SG_COM_GetModifier。
使用身份
您可以通过函数 SG_COM_SetRole 使用枚举类型 SG_COM_Role(其值为 SG_COM_ROLE_SPEAK 和 SG_COM_ROLE_LISTEN)在说话和倾听的身份之间切换引擎。
SG_COM_SetRole(engine_handle, SG_COM_ROLE_LISTEN);
SG_COM_SetRole(engine_handle, SG_COM_ROLE_SPEAK);
如果从未调用该函数,SG Com 将保持默认身份 SG_COM_ROLE_SPEAK。
要获取当前身份,请调用 SG_COM_GetRole。