版本

menu_open

集成详情——音乐回调

简介

在为游戏创建互动音乐时,您需要音乐的节拍信息。您可以使用音乐通知从声音引擎索取这些信息。节拍由当前正在播放的主要音乐段落(music segment)决定。由于音乐段落可能具有不同的拍号,因此节拍将随着当前正在播放的音乐而变化。当没有音乐在播放时,就不会有通知。

有两种音乐回调类型:

  • 音乐通知(Music Notifications):告诉被调用方当前音乐的播放属性。
  • 音乐播放列表选择(Muisc Playlist Selection):被调用方可以强制选择音乐播放列表中的下一项。

如何使用音乐通知

如果您想收到有关音乐的标记(marker)通知,在设计应用程序时需要特别注意以下几点:

  • 在要发送的播放事件中包含有音乐且您需要跟随音乐的节拍时,您可以添加以下若干个标志:
AK_MusicSyncBeat                = 0x0100,   // 在音乐节拍点上启用通知。
AK_MusicSyncBar                 = 0x0200,   // 音乐小节时间点上启用通知。
AK_MusicSyncEntry               = 0x0400,   // 在音乐入口处启用通知。
AK_MusicSyncExit                = 0x0800,   // 在音乐出口处启用通知。
AK_MusicSyncGrid                = 0x1000,   // 在音乐网格上启用通知。
AK_MusicSyncUserCue             = 0x2000,   // 在音乐用户提示点上启用通知。
AK_MusicSyncPoint               = 0x4000,   // 在音乐同步点上启用通知。
AK_MusicSyncAll                 = 0xff00,   // 如果您想收到有关 AK_MusicSync 注册的所有通知,则使用此标志。

如果您还想在事件结束时收到通知,则应使用 AK_EndOfEvent | AK_MusicSyncBeat,因为这些标志按位做异或运算。

AkPlayingID AK::SoundEngine::PostEvent(
    AkUniqueID in_eventID,                  // 唯一的事件 ID
    AkGameObjectID in_gameObjectID,         // 相关游戏对象 ID
    AkUInt32 in_uFlags = 0,                 // 位掩码:见 AkCallbackType
    AkCallbackFunc in_pfnCallback = NULL,   // 回调函数
    void * in_pCookie = NULL                // 回调的 cookie 将与其他信息一起 
                                            // 发送到回调函数
);
  • 您的回调函数必须采用以下格式:
static void MusicCallback(
    AkCallbackType in_eType,            // 回调原因的类型,在本例中,类型可以是 AK_MusicSyncBeat
    AkCallbackInfo* in_pCallbackInfo    // 指向回调信息结构的指针,在本例中
                                        // AkMusicSyncCallbackInfo*。
  • 当您调用回调函数时,您首先需要检查传入的是哪种通知。例如,如果您只想处理 AK_MusicSyncBar 通知,则当收到任何其它事件类型时,您应该直接返回。
  • 根据通知的类型,您可以将in_pCallbackInfo 类型转换(typecast)为相应的信息结构类型。对于音乐通知,它是 AkMusicSyncCallbackInfo。
/// 对应于 Ak_MusicSync 的回调信息结构
struct AkMusicSyncCallbackInfo : public AkCallbackInfo
{
    AkPlayingID playingID;          ///< 正在播放的事件 ID,由 PostEvent() 返回
    AkCallbackType musicSyncType;   ///< 可以是 AK_MusicSyncEntry、AK_MusicSyncBeat、AK_MusicSyncBar、AK_MusicSyncExit、AK_MusicSyncGrid、AK_MusicSyncPoint 或 AK_MusicSyncUserCue。
    AkReal32 fBeatDuration;         ///< 节拍时长,单位:秒。
    AkReal32 fBarDuration;          ///< 小节时长,单位:秒。
    AkReal32 fGridDuration;         ///< 网格时长,单位:秒。
    AkReal32 fGridOffset;           ///< 网格偏置,单位:秒。
};
注解:
当请求多个音乐通知时,将发送这些额外通知。这意味着,如果您在拍号 4/4 下注册 AK_MusicSyncBeatAK_MusicSyncBar,则每小节中您将收到 4 次节拍通知和小节本身的一次通知。拍号“0”对节拍和小节也很重要,而且在大多数情况下对 AK_MusicSyncEntry 也同样重要。这意味着,如果您注册小节、节拍和入口,则当音乐启动时,您将连续收到三个回调。
速度可通过以下公式计算:速度(以 BPM 为单位)= 60.0 / fBeatDuration
拍号的上限值可通过以下公式计算:上限值 = fBarDuration / fBeatDuration。 这告诉您每个小节有多少拍。
只有到达当前音乐段落的末尾时,才会发送通知 AK_MusicSyncExit 。如果在完成当前音乐前,音乐切换到另一段落,则不会发送 AK_MusicSyncExit 通知。
参见:
快速入门示例集成——事件

如何使用音乐播放列表回调

上述回调函数还可用于手动管理音乐播放列表中的下一项选择。这可以通过添加以下标志来实现。

AK_MusicPlaylistSelect          = 0x0040    // 当音乐播放列表容器必须选择要播放的下一项时,将触发回调。

一旦收到此类事件,回调函数必须把参数 in_pCallbackInfo 强制转换成类型 AkMusicPlaylistCallbackInfo。

/// 对应于 Ak_MusicPlaylistSelect 的回调信息结构
struct AkMusicPlaylistCallbackInfo : public AkEventCallbackInfo
{
    AkPlayingID playlistID;         ///< 音乐播放列表容器中的活跃节点的 ID
    AkUInt32 uNumPlaylistItems;     ///< 播放列表节点中的项目数(可以是段落或其它播放列表)
    AkUInt32 uPlaylistSelection;    ///< 选择:由声音引擎设置,由回调函数更改(如果不在值域 0 <= uPlaylistSelection < uNumPlaylistItems 范围内,则忽略)
    AkUInt32 uPlaylistItemDone;     ///< 播放列表节点已完成:由声音引擎设置,回调函数更改(如果设置为除 0 以外的任何值,则执行当前播放列表条目,并忽略 uPlaylistSelection)
};

活跃的播放列表节点通过成员 playlistID 标示。在调用回调函数前,声音引擎选择播放列表节点中的下一项。此选择包含在成员 uPlaylistSelectionuPlaylistItemDone 中。如果 uPlaylistItemDone 设为 0,则 uPlaylistSelection 决定播放列表节点中要播放的下一项。如果 uPlaylistItemDone 未设为 0,则当前播放列表节点跳到末尾(然后父节点将变成活动节点)。成员 uPlaylistSelectionuPlaylistItemDone 可通过回调函数来更改。

通知延迟

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

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

回调线程

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

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

参见:
集成详情——事件

此页面对您是否有帮助?

需要技术支持?

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

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

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

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

开始 Wwise 之旅