版本

menu_open
Wwise SDK 2023.1.2
集成 Marker

简介

Marker(标记)是插入 WAV 文件并用在波形中标示位置的标识符。通常可以在 WAV 编辑器应用程序(例如 SoundForge®、Adobe® Audition® 或 CueTool)中创建这些标记。

当播放到特定位置时,应用程序可使用这些标记来获得通知。例如,您可以使用此信息将视觉内容的绘制与正在播放的音频同步,或者了解随机容器正在播放哪个文件,以便在游戏中显示正确的字幕。

备注: 使用 Wwise 标记通知(Marker Notification)功能通常是集成对口型或字幕解决方案最高效的方式。

使用 .wav 文件格式

块(chunk)是用于存储提示点(cue point)或有关提示点的数据的数据存储单元。提示点是 .wav 格式文件中标示的兴趣点。

提示块

提示块(cue chunk)格式用于存储标记位置,标记位置用于提示 .wav 文件中的兴趣点。

偏移量 字节 说明 值
0x00 4 块 ID "cue " (0x63756520)
0x04 4 块数据大小 取决于提示点数量
0x08 4 提示点数量 列中提示点的数量
0x0c 提示点从此开始
#define CueID 'cue ' /* 提示块的块 ID*/
typedef struct {
ID chunkID;
long chunkSize;
long dwCuePoints;
CuePoint points[];
} CueChunk;
typedef struct {
long dwIdentifier;
long dwPosition;
ID fccChunk;
long dwChunkStart;
long dwBlockStart;
long dwSampleOffset;
} CuePoint;

列表块

列表块(list chunk)是包 .wav 文件内部的容器,其中包含子块。相关数据列表块(associated data list chunk,adtl)格式用于存储标签、注释以及与提示点的关联文本。

偏移量 字节 说明 值
0x00 4 块 ID "list" (0x6C696E74)
0x04 4 块数据大小 取决于包含的子块
0x08 4 类型 ID "adtl" (0x6164746C)
0x0c 子块从此开始

标签子块

标签子块(label sub-chunk)格式用于存储提示点的关联字符串。它应该位于关联数据列表块内。

偏移量 字节 说明 值
0x00 4 块 ID "labl" (0x6C61626C)
0x04 4 块数据大小 取决于文本大小
0x08 4 提示点 ID 参阅提示块 dwIdentifier
0x0c 标签(大小可变的文本)

Working with Source Plug-ins

Source plug-ins can also generate marker notifications.

在源插件内,可使用 AK::IAkPluginServiceMarkers::CreateMarkerNotificationService() 创建 AK::IAkPluginServiceMarkers::IAkMarkerNotificationService 实例。然后,可使用 AK::IAkPluginServiceMarkers::IAkMarkerNotificationService::SubmitMarkerNotifications() 将标记通知发给使用 AkAudioMarker 结构的游戏。

{
AkUInt32 dwIdentifier; ///< Identifier.
AkUInt32 dwPosition; ///< Position in the audio data in sample frames.
const char* strLabel; ///< Label of the marker taken from the file.
AkUInt32 dwLabelSize; ///< Length of label read the from the file + terminating null character.
};

Marker Generator Source Plug-in Example

Below is an example of a source plug-in that generates marker notifications.

class MyMarkerGeneratorSourcePlugin : public IAkSourcePlugin
{
private:
IAkSourcePluginContext* m_pSourcePluginContext{};
IAkPluginServiceMarkers::IAkMarkerNotificationService* m_pMarkerNotificationService{};
AkUInt32 m_uElapsedSamples{};
static constexpr AkUInt32 g_uPayloadSize{ 64 };
char m_Payload[g_uPayloadSize]{};
// ...
public:
IAkPluginMemAlloc * in_pAllocator, ///< Interface to the memory allocator to be used by the plug-in
IAkSourcePluginContext * in_pSourcePluginContext, ///< Interface to the source plug-in's context
IAkPluginParam * in_pParams, ///< Interface to the plug-in parameters
AkAudioFormat & io_rFormat ///< Audio format of the output data to be produced by the plug-in (mono native by default)
) override
{
m_pSourcePluginContext = in_pSourcePluginContext;
m_pMarkerNotificationService = AK_GET_PLUGIN_SERVICE_MARKERS(m_pSourcePluginContext)->CreateMarkerNotificationService(m_pSourcePluginContext);
return AK_Success;
}
IAkPluginMemAlloc * in_pAllocator ///< Interface to memory allocator to be used by the plug-in
) override
{
AK_GET_PLUGIN_SERVICE_MARKERS(m_pSourcePluginContext)->TerminateMarkerNotificationService(m_pMarkerNotificationService);
return AK_Success;
}
void Execute(
AkAudioBuffer * io_pBuffer ///< In/Out audio buffer data structure (in-place processing)
) override
{
static constexpr AkUInt32 uNumMarkers{ 1 };
AkAudioMarker markers[uNumMarkers];
markers[0].dwIdentifier = 'mrkr';
markers[0].dwPosition = m_uElapsedSamples;
markers[0].strLabel = m_Payload;
markers[0].dwLabelSize = g_uPayloadSize;
const AkUInt32 offsetsInBuffer[uNumMarkers]{ 0 };
m_pMarkerNotificationService->SubmitMarkerNotifications(markers, offsetsInBuffer, uNumMarkers);
// advance the position of the markers
m_uElapsedSamples += io_pBuffer->MaxFrames();
}
// ...
};

如何使用标记通知

以下是有关如何设置应用程序,以使它能够接收标记通知的说明:

  • 在发送播放事件时,应将 AK_Marker 标识添加到 in_uiFlags 。如果您还想收到End of Event(事件结束)通知,则应使用 AK_EndOfEvent | AK_Marker ,因为这些标志采取按位异或运算。
AkUniqueID in_eventID, // 唯一的事件 ID
AkGameObjectID in_gameObjectID, // 相关游戏对象 ID
AkUInt32 in_uFlags = 0, // 位掩码:见 AkCallbackType
AkCallbackFunc in_pfnCallback = NULL, // 回调函数
void * in_pCookie = NULL // 回调的 cookie 将与其他信息一起
// 发送到回调函数
);
  • 您的回调函数必须采用以下格式:
static void MarkersCallback(
AkCallbackType in_eType, // 回调原因的类型,在本例中,类型为接收到
// 标记事件时的 AK_Marker。
AkCallbackInfo* in_pCallbackInfo // 指向回调信息结构的指针,在本例中为
// AkMarkerCallbackInfo*。
  • 当您调用回调函数时,您首先需要检查传入的是哪种通知。例如,如果您只想处理AK_Marker 通知,则在收到任何其他事件类型时应返回。
  • 根据通知的类型,您可以将in_pCallbackInfo 类型转换(typecast)为相应的信息结构类型。对于 AK_Marker 通知,相应的信息结构类型为 AkMarkerCallbackInfo。
// 对应于 AK_Marker 的回调信息结构。
{
AkUInt32 uIdentifier; // Cue point identifier
AkUInt32 uPosition; // Position in the cue point (unit: sample frames)
const char* strLabel; // Label of the marker (null-terminated)
AkUInt32 uLabelSize; // Size of the label string (including the terminating null character)
};
  • 如果之后您打算引用标签,则一定要复制strLabel 字符串成员的内容,因为在回调返回后,指针可能会被作废。
参见
快速入门示例集成——事件

通知延迟

目前当缓冲区向下传递到硬件时发送通知。这意味着,发送通知与遇到标记之间存在一定延时。这样在真正播放与标记关联的声音之前,应用程序有足够的时间来收集并处理标记中的信息。

注意这个延时取决于平台。

回调线程

Marker 回调和 End of Event 回调从声音引擎的主线程完成。这意味着您的应用程序应从通知中收集它所需的全部信息,并立即返回。如果需要进行任何处理,则应当从通知中复制相关信息后,使用单独的线程来执行。

如果应用程序占用线程太久,声音引擎可能掉入 underrun(欠载运行)状态,导致输出停止播放。

注解
在回调函数返回后,声音引擎将释放被引用的数据,因此应复制来自回调函数的标签字符串。

Wwise 捕获日志和标记

Wwise Profiler 可以显示来自声音引擎的标记通知。为此,必须确保启用 Profiler Settings 对话框中的 Markers Notification Data 选项。当播放到达标记处并已请求通知时,Capture Log 中将在新的一行中显示相关信息。注意,如果需要可以过滤掉这些通知,方法是取消选择 Capture Log Filter 对话框中的 Markers Notification Data 复选框。

参见
集成详情——事件
Defines the parameters of a marker.
Definition: AkAudioMarker.h:16
const char * strLabel
Label of the marker (null-terminated)
Definition: AkCallback.h:119
AkUInt32 dwIdentifier
Identifier.
Definition: AkAudioMarker.h:17
AkUInt64 AkGameObjectID
Game object ID
Definition: AkTypes.h:142
AKRESULT
Standard function call result.
Definition: AkTypes.h:213
AkUInt32 dwLabelSize
Length of label read the from the file + terminating null character.
Definition: AkAudioMarker.h:20
AkCallbackType
Type of callback. Used as a bitfield in methods AK::SoundEngine::PostEvent() and AK::SoundEngine::Dyn...
Definition: AkCallback.h:48
AKSOUNDENGINE_API AKRESULT Init(const AkCommSettings &in_settings)
#define NULL
Definition: AkTypes.h:46
@ AK_Success
The operation was successful.
Definition: AkTypes.h:215
AKSOUNDENGINE_API void Term()
AkUInt32 uIdentifier
Cue point identifier
Definition: AkCallback.h:117
AkUInt32 AkUniqueID
Unique 32-bit ID
Definition: AkTypes.h:134
AkUInt32 uLabelSize
Size of the label string (including the terminating null character)
Definition: AkCallback.h:120
AkUInt32 uPosition
Position in the cue point (unit: sample frames)
Definition: AkCallback.h:118
void(* AkCallbackFunc)(AkCallbackType in_eType, AkCallbackInfo *in_pCallbackInfo)
Definition: AkCallback.h:266
const char * strLabel
Label of the marker taken from the file.
Definition: AkAudioMarker.h:19
#define AK_GET_PLUGIN_SERVICE_MARKERS(plugin_ctx)
Definition: IAkPlugin.h:1756
uint32_t AkUInt32
Unsigned 32-bit integer
AkUInt32 dwPosition
Position in the audio data in sample frames.
Definition: AkAudioMarker.h:18
AKSOUNDENGINE_API AkPlayingID PostEvent(AkUniqueID in_eventID, AkGameObjectID in_gameObjectID, AkUInt32 in_uFlags=0, AkCallbackFunc in_pfnCallback=NULL, void *in_pCookie=NULL, AkUInt32 in_cExternals=0, AkExternalSourceInfo *in_pExternalSources=NULL, AkPlayingID in_PlayingID=AK_INVALID_PLAYING_ID)
Defines the parameters of an audio buffer format.
Definition: AkCommonDefs.h:63
AkUInt32 AkPlayingID
Playing ID
Definition: AkTypes.h:137
AkForceInline AkUInt16 MaxFrames() const
Definition: AkCommonDefs.h:643

此页面对您是否有帮助?

需要技术支持?

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

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

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

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

开始 Wwise 之旅