版本

menu_open
Wwise SDK 2024.1.1
创建声音引擎源插件

源插件接口实现

源插件用合成方的方式产生音频内容,并提供给输出缓冲区。这些合成方法包括物理建模、调制合成、采样合成等。可以按照本文档所述的方法实现 AK::IAkSourcePlugin 接口,来编写源插件。这里仅介绍 AK::IAkSourcePlugin 接口的特有函数。请参阅 创建声音引擎插件 了解与其他插件共用的接口组件的相关信息。请参阅随附的 Sine(正弦波)插件示例了解详情(示例 )。

AK::IAkSourcePlugin::Init()

此方法让源插件为数据处理做好准备,分配内存和设置初始条件。

此插件通过指针传递给内存分配器接口(AK::IAkPluginMemAlloc)。您应该通过此接口来执行所有动态内存分配,并使用随附的内存分配宏(请参阅 在音频插件中分配/取消分配内存 )。对于最常见的内存分配需求,即在初始化时分配内存和在终止时释放内存的情况下,插件将不需要保留指向分配器的指针。在终止时也会将此指针提供给插件。

The AK::IAkSourcePluginContext interface allows the plug-in to retrieve information such as the number of loop iterations or other information related to the context in which the source plug-in is operated. It may also access the global context through AK::IAkPluginContextBase::GlobalContext(). Using AK::IAkSourcePluginContext::GetPluginCustomGameData(), the plug-in can retrieve data sent to it from the game through AK::SoundEngine::SendPluginCustomGameData().

插件还接收指向其相关参数节点接口(AK::IAkPluginParam)的指针。大多数插件希望保留对相关参数节点的引用,以便能够在运行时获取参数。请参阅 参数节点与插件之间的通信。 了解更多详情。

所有这些接口将在插件的生命周期内有效,因此必要时在内部引用它们是安全的。

插件运行平台的原生音频格式作为 AK::IAkSourcePlugin::Init() 函数的参数传递。强烈建议插件以平台原生格式输出,以避免音频格式转换造成性能损失。如果源插件不适合以此格式输出,那么也可以输出 16 位带符号采样的交错声道信号。在多声道配置中,源插件还必须指定将输出交错还是非交错数据( AkAudioFormat::uInterleaveID)。默认的原生设置是 AK_NONINTERLEAVED。当输出非交错数据时,源插件应使用 AkAudioBuffer::GetChannel() 方法来访问每个声道的缓冲区。当输出交错数据时,应使用 AkAudioBuffer::GetInterleavedData()。在7.1的情况下,源插件交错数据的声道顺序是 L-R-C-LFE-BL-BR-SL-SR。请参阅 访问使用 AkAudioBuffer 结构的数据 了解更多详情。

输入的声道掩码将默认使用单(仅中置扬声器)声道配置。您可以将此声道掩码更改为希望源插件输出的声道配置。以下代码示例中,声道掩码将改为立体声。在每次执行时收到的音频缓冲区将适配至初始化时插件指定的格式,并且在插件的整个生命周期内保持不变。因此对于稍后在初始化例程中进行处理所需的格式信息,也可以在缓冲区中安全存储。

AKRESULT CAkDCOffset::Init( AK::IAkPluginMemAlloc * in_pAllocator, // 内存分配接口。
AK::IAkSourcePluginContext * in_pSourcePluginContext, // 源插件上下文
AK::IAkPluginParam * in_pParams, // 效果器参数。
AkAudioFormat & io_rFormat // 支持的音频输出格式。
)
{
// 保留指向相关参数节点的指针。
m_pParams = reinterpret_cast<CAkMyPluginParams*>( in_pParams );
// 进行辅助设置来处理循环,并可能更改合成持续时间
m_DurationHandler.Setup( m_pParams->fDuration, in_pSourceFXContext->GetNumLoops(), io_rFormat.uSampleRate );
// 在默认情况下,输出格式设置为单声道(输入)原生格式。更改为立体声输出。
...
return AK_Success;
}
备注: 每次效果器实例化时,都会调用 AK::IAkSourcePlugin::Init(),当声部开始播放或混音总线实例化时,就会实例化效果器。典型情况下,其他声音已经在播放,因此实例化需要在合理的时间段内进行。如果您需要初始化通用/全局数据结构,那么在注册插件库时就应该这样做。请参阅 在插件中使用全局声音引擎回调 了解更多详情。

AK::IAkSourcePlugin::GetDuration()

在初始化阶段之后,声音引擎调用此方法来确定声源的大致持续时间,以便在声音过渡期间处理交叉淡变。返回声源的预计持续时间,单位:毫秒。如果循环的迭代次数有限,则返回的持续时间将与总体持续时间相符,即播放声音的迭代次数将被考虑在内。当选择了无限循环或者声源的持续时间未知时,返回的持续时间应为零。注意,当选择了无限循环时,通过 AK::IAkSourcePluginContext::GetNumLoops() 获得的循环迭代次数总是为零。

// 获取声源的持续时间,单位:毫秒。
AkTimeMs CAkDCOffset::GetDuration( ) const
{
return m_DurationHandler.GetDuration() * 1000.f;
}
备注: 如果使用了 RTPC 参数对插件的持续时间进行更改,交叉渐变的过渡时间可能不符合预期长度。
备注: 对于源插件,处理大多数耗时管理(包括循环)的最简单方法是使用 AkFXDurationHandler 服务,如正弦插件示例中所示(示例 )。

AK::IAkSourcePlugin::StopLooping()

声音引擎在收到中断动作时将调用此方法。中断动作是一个流畅的停止操作。 插件可在此函数中实现一种流畅终止声音播放的方法。通常它仅停止循环,如果有释音将会播放释音。 如果此函数忽略或者处理了中断命令,须返回 AK_Success。 如果插件不能处理命令,则函数应返回 AK_Fail,这会让声源停止播放。

在当前循环迭代后停止播放 AKRESULT CAkDCOffset::StopLooping() { m_DurationHandler.SetLooping( 1 ); // 不再循环。 return AK_Success; }

备注: 此函数是可选的。如果不实现,声源将忽略中断命令并一直正常播放至结束。

AK::IAkSourcePlugin::GetEnvelope()

调用此方法可以获取预估的振幅包络值(标准化值,位于 0 和 1 之间),该值将于源插件下次调用 Execute() 时生成。在 Wwise 的当前版本中,HDR 处理算法使用该方法来获取包络线的预估值,从而对比其更轻的声音进行相应衰减。此功能是可选的:在 HDR 总线下使用您的插件时,如果返回 1(默认值),则更轻声音的衰减值将保持恒定。

如果选择实现,请确保其返回标准化包络值,即您所知道的即将生成波形的峰值,或者对振幅包络和增益解耦,那么仅返回包络线的当前值即可。

AK::IAkSourcePlugin::Execute()

此方法执行源插件音频信号处理算法,并填充指定的音频输出缓冲区(访问使用 AkAudioBuffer 结构的数据 )。进入函数时,输出缓冲区的 AkAudioBuffer::uValidFrames 字段将为零,即声道缓冲区中不含有效的音频采样帧。AkAudioBuffer::MaxFrames() 方法返回声源应填充的最大音频采样帧数。插件需确定要产生多少个输出采样帧,这可能取决于持续时间等参数值。在执行 DSP 后,源插件须通过设置音频缓冲区的 AkAudioBuffer::uValidFrames 字段,告诉音频管线已经生成了多少有效采样帧。

备注: 一般而言,算法应尽量完整填充缓冲区,以避免管线资源不足。

只要源插件将 AkAudioBuffer 结构的 eState 字段设置为 AK_DataReady,就会调用 Execute() 例程。返回 AK_NoMoreData 时,音频管线将终止且不再调用插件。 Wwise supports source plug-ins that output to any configuration listed on the Understanding Bus Configurations page except Audio Objects.

源插件执行的重要注意事项

  • 源插件须保持生成完整的采样帧,即生成指定输出格式中每个声道的采样。
  • 确保插件在运行时检查 RTPC 所需参数。应该在共享参数接口中实现存取方法,从参数节点获取值,并在运行时按照所需的频率调用它们。更多信息请参阅 参数节点与插件之间的通信。 。对于大多数参数值,每帧检查一次就够了。请查看代码示例来了解如何使用参数值渐变(例如渐增)来避免信号不连续(示例 )。
  • 在 Wwise 中使用插件时,无论参数是否与 RTPC 关联,参数变化都会发送至参数节点。这样必要时,插件就可以在运行时更改非 RTPC 值,从而方便 Wwise 使用。如果不希望插件支持此功能,应在初始化时复制这些参数值,确保它们在插件的存续期间保持不变。请参阅 CAkToneGen::Init 来查看相关示例。
  • 您应对 AK::IAkSourcePlugin::Execute() 方法中执行的处理加以优化,以便在缓冲区时间内能够完成,不然可能导致此声源和其他声源管线出现 Source starvation,还可能对声音引擎性能产生巨大影响。

DC offset (DC偏置)插件的 Execute() 函数如下所示。请参阅 CAkSrcSine::Execute() 和各种乐音发生器 DSP 例程了解更多详情。

// 此示例中是一个简单应用,通过使用 RTPC 参数来输出稳定 DC 偏置信号。
void CAkDCOffset::Execute( AkAudioBuffer * io_pBuffer )
{
// 在更改(如 RTPC 参数) 时设置新的持续时间;
m_DurationHandler.SetDuration( m_pParams->fDuration );
// 确定执行期间需要多少采样帧,并根据当前状态设置 uValidFrames 和 eState
m_DurationHandler.ProduceBuffer( io_pBuffer );
// 获取 RTPC DC 偏置参数
AkReal32 fDCOffset = m_pParams->GetDCOffset( );
// DC 偏置输出 DSP(支持任意数量的声道)
for ( unsigned int i = 0; i < m_uNumChannels; ++i )
{
AkSampleType * pBufOut = io_pBuffer->GetChannel(i); // AkSampleType 取决于平台(在软件平台上使用 AkReal32)。
AkUInt32 uFrameCount = io_pBuffer->uValidFrames;
while ( uFrameCount-- )
{
*pBufOut++ = AK_FLOAT_TO_SAMPLETYPE( fDCOffset ); // DC-offset 输出,会将标准浮点数转化为支持的格式。
}
}
}

AK::IAkSourcePlugin::TimeSkip()

当虚声部设置为“Play from elapsed time”时,将使用 AK::IAkSourcePlugin::TimeSkip() 替代 Execute(),来让源插件在必要时更新其内部状态(例如高级合成时间)。它可以用来模拟将要进行的处理,同时避免在执行插件时占用大量 CPU。根据要求的帧数,通过 io_uFrames 参数来调整调用 Execute() 将要产生的帧数,并根据此时是否存在音频输出来返回 AK_DataReady 或 AK_NoMoreData。

返回 AK_NotImplemented 将导致声部正常处理(就像不是虚声部一样),因此“Play from elapsed time”将不能起到节省 CPU 的作用。

// 此示例显示当虚声部设置为“Play from elapsed time”时应如何跳过某些帧的处理。
AKRESULT CAkDCOffset::TimeSkip( AkUInt32 &io_uFrames )
{
AkUInt16 uValidFrames = (AkUInt16)io_uFrames;
AkUInt16 uMaxFrames = (AkUInt16)io_uFrames;
AKRESULT eResult = m_DurationHandler.ProduceBuffer( uMaxFrames, uValidFrames );
io_uFrames = uValidFrames;
return eResult;
}
\

更多信息请参阅以下部分: 声音引擎插件概述实现效果器插件接口编写音频插件的设计工具部分

AkSampleType * GetChannel(AkUInt32 in_uIndex)
Definition: AkCommonDefs.h:432
uint16_t AkUInt16
Unsigned 16-bit integer
AkInt32 AkTimeMs
Time in ms
Definition: AkTypes.h:56
AKRESULT
Standard function call result.
Definition: AkTypes.h:134
AkChannelConfig channelConfig
Channel configuration.
Definition: AkCommonDefs.h:63
AKSOUNDENGINE_API AKRESULT Init(const AkCommSettings &in_settings)
float AkReal32
32-bit floating point
@ AK_Success
The operation was successful.
Definition: AkTypes.h:136
AkUInt16 uValidFrames
Number of valid sample frames in the audio buffer
Definition: AkCommonDefs.h:513
AkReal32 AkSampleType
Audio sample data type (32 bit floating point)
Definition: AkCommonDefs.h:314
AkForceInline void SetStandard(AkUInt32 in_uChannelMask)
Set channel config as a standard configuration specified with given channel mask.
uint32_t AkUInt32
Unsigned 32-bit integer
#define AK_SPEAKER_SETUP_STEREO
2.0 setup channel mask
Defines the parameters of an audio buffer format.
Definition: AkCommonDefs.h:60
#define AK_FLOAT_TO_SAMPLETYPE(__in__)
This function can be useful to convert from normalized floating point audio samples to HW-pipeline fo...
Definition: IAkPlugin.h:1319
AkUInt32 uSampleRate
Number of samples per second
Definition: AkCommonDefs.h:61

此页面对您是否有帮助?

需要技术支持?

仍有疑问?或者问题?需要更多信息?欢迎联系我们,我们可以提供帮助!

查看我们的“技术支持”页面

介绍一下自己的项目。我们会竭力为您提供帮助。

来注册自己的项目,我们帮您快速入门,不带任何附加条件!

开始 Wwise 之旅