Wwise SDK 2019.2.15
|
Effect 效果器插件接收已有的声音作为输入音频数据,将 DSP 算法作用于这些输入数据。编写效果器插件的工作主要包括实现 AK::IAkInPlaceEffectPlugin 或者 AK::IAkOutOfPlaceEffectPlugin 接口中的一个。在此只介绍与这些接口相关的函数。请参阅 如何创建 Wwise 声音引擎插件 了解与其他插件类型(AK::IAkPlugin 接口)共享的接口组件的信息。另请参阅随附的 AkDelay 插件了解详情(示例 )。
此方法为效果器插件用于处理数据做准备,分配内存并设置初始条件。
此插件通过指针传递给内存分配器接口(AK::IAkPluginMemAlloc)。您应该通过此接口来执行所有动态内存分配,并使用随附的内存分配宏(请参阅 在音频插件中分配/取消分配内存 )。对于最常见的内存分配需求,即在初始化时分配内存和在终止时释放内存的情况下,插件将不需要保留指向分配器的指针。在终止时也会将此指针提供给插件。
AK::IAkEffectPluginContext 接口可用于获取信息,例如旁通掉状态或与效果器插件工作环境相关的其他信息。该接口还可以通过 AK::IAkPluginContextBase::GlobalContext() 访问全局上下文。
插件还接收指向其相关参数节点接口(AK::IAkPluginParam)的指针。大多数插件希望保留对相关参数节点的引用,以便能够在运行时获取参数。请参阅 参数节点与插件之间的通信。 了解更多详情。
所有这些接口将在插件的生命周期内有效,因此必要时在内部引用它们是安全的。
效果器插件还接收输入/输出音频格式(此格式在插件寿命期间保持不变),以便能够为给定的声道配置分配内存和设置处理。
![]() |
备注: 每次效果器实例化时都会调用 AK::IAkEffectPlugin::Init(),当声部开始播放或者混音总线实例化时,就会发生效果器实例化。典型情况下,其他声音已经在播放,因此实例化需要在合理的时间段内进行。如果您需要初始化通用/全局数据结构,那么在注册插件库时就应该这样做。请参阅 在插件中使用全局声音引擎回调 了解更多详情。 |
效果器插件可选择实现以下 2 个接口之一:AK::IAkInPlaceEffectPlugin或AK::IAkOutOfPlaceEffectPlugin。一般大多数效果器应该采用原地效果(它们对输入和输出数据使用相同的音频缓冲区)。然而,当数据流有变时(例如 time-stretching 时间伸缩效果器),则必须实现非原地接口。
![]() |
注意: 具有不同输入/输出声道配置的非原地效果器可插入 Master-Mixer hierarchy(主混音器层级结构)中。然而,无法将变速率效果器放置在混音总线上。具有不同输入/输出缓冲长度的效果器只可插入 Actor-Mixer hierarchy(用作源效果器)。 |
此方法原地执行给定音频缓冲区上的插件信号处理算法(请参阅 访问使用 AkAudioBuffer 结构的数据 了解详情)。此结构向插件提供有关输入采样点中有多少点有效(AkAudioBuffer::uValidFrames)和缓冲区可容纳的最大音频采样帧数(AkAudioBuffer::MaxFrames() method)的信息。AkAudioBuffer::eState结构成员向插件指示"这是不是最后一次执行":AK_NoMoreData 表示"是",AK_DataReady 表示"不是"。
当虚声部从已用时间播放(Play from Elapsed Time)时,AK::IAkInPlaceEffectPlugin::TimeSkip() 将替代 Execute(),以便插件能够在需要的情况下保持更新它们的内部状态。
此方法对非原地算法执行插件的信号处理。使用两个 AkAudioBuffer 结构,一个用于输入缓冲区,另一个用于输出缓冲区。管线使用输出音频缓冲区的 eState 来确定效果器的当前状态。只有当效果器在以下两种情况之一下才需要返回:一是处理完输入缓冲区时(会返回 AK_DataNeeded,以便稍后处理更多的数据),二是在填满整个输出缓冲区时(返回 AK_DataReady)。在非原地效果中还可实现效果器尾音,方法是将收到的 AK_NoMoreData 更改为 AK_DataReady,直至效果器排空其内部状态(此时应返回 AK_NoMoreData)。
直接处理完整个输入缓冲区,管线才会释放输入缓冲区。因此,一定要使用 in_uInOffset 编置参数开始读取上次 Execute() 调用停止时未读完的数据。下面示例介绍如何实现这一点。
当虚声部采用 Play from Elapsed Time 时,AK::IAkOutOfPlaceEffectPlugin::TimeSkip() 将替代 Execute(),以便插件能够在需要的情况下能一直更新其内部状态。然后此函数负责告诉管线,产生给定数量的输出帧通常需要处理多少输入采样点。
某些效果器具有内部状态,在输入完成播放后,必须输出该内部状态,以便正确进行衰减,最典型的是带延时线(delay line)的效果器。效果器 API 使得即使在没有任何有效输入数据的情况下也可继续执行。当 AkAudioBuffer 结构的 eState 标志变成 AK_NoMoreData 时,在完成当前执行后,管线不会再将有效的输入采样帧送到插件。然后插件可以自由在缓冲区中写入新帧(最大帧数为 MaxFrames() 返回的值),以便在完成输入信号后清空延时线。应始终告诉音频管线已经输出了多少帧,方法是正确更新 uValidFrames 字段。如果需要再次调用插件 Execute() 函数来完成效果器尾音刷新,则应将 eState 成员应为 AK_DataReady。只有当效果器为 eState 字段设置了 AK_NoMoreData 时,管线才会停止调用插件 Execute()。
处理尾音的最简单方法是使用 SDK 中提供的 AkFXTailHandler 服务类。由于一份 AkFXTailHandler 用作插件的类成员,因此我们在原位效果器中唯一需要做的是调用 AkFXTailHandler::HandleTail(),并将它和输出完成时要输出的音频样本总数(根据参数的不同,各个执行之间存在差异)传输给 AkAudioBuffer。请参阅 AkDelay 插件源代码了解详情(示例 )。
在 Wwise 或游戏中可通过各种机制(例如 UI、事件和 RTPC)旁通插件。在这些情况下,不会调用插件 Execute() 函数。当解除旁通的时候,插件继续运行并再次调用 Execute() 函数时,插件将重新启动它的处理工作。旁通时将调用插件的 Reset() 函数,以清除延时线和其他状态信息,从而在最终解除旁通时能够有一个全新的开始。请参阅 AK::IAkPlugin::Reset() 了解详情。
![]() |
注意: 运行时旁通和解除旁通插件可能导致信号中断,具体取决于插件和被处理的声音素材。 |
有关更多信息,请参阅以下各节:
在用于监控的时候,插件可能需要将信息发回到 Wwise。常见例子有发送有关音频信号的信息(如 VU 电平表)、运行时信息比如内存占用等等。
在通过性能分析系统异步发送数据前,效果器应该首先确定是否可通过调用 AK::IAkEffectPluginContext::CanPostMonitorData() 将数据发送到此效果器插件的对应 UI。 要做到这点,您需要将指针缓存到插件执行环境(execution context)中,该执行环境会在在效果器初始化时交给插件。 注意,只有插件位于总线上时才可发送数据,因为在这种情况下,它与其效果器设置视图呈一对一的关系。
如果数据可以发送并且构建目标版本可与 Wwise 通信(即非 Release 版本),则您可以发布任何大小的数据块。您可以通过 AK::IAkEffectPluginContext::PostMonitorData() 来按照您的喜好组织数据块。监控数据一旦发布,您就可以安心地放弃插件中的数据块了。