When creating the interactive music for your game, you may need information about the music's beat. You can request this information from the sound engine using music notifications. The beat is determined by the main music segment currently playing. Since segments can have different time signatures, the beat will change based on the music currently playing. When no music is playing, there will be no notifications.
There are two types of music callbacks:
If you want to receive marker notifications about your music, there are specific things you need to be aware of when designing your application:
AK_MusicSyncBeat = 0x0100, // Enable notifications on Music Beat. AK_MusicSyncBar = 0x0200, // Enable notifications on Music Bar. AK_MusicSyncEntry = 0x0400, // Enable notifications on Music Entry Point. AK_MusicSyncExit = 0x0800, // Enable notifications on Music Exit Point. AK_MusicSyncGrid = 0x1000, // Enable notifications on Music Grid. AK_MusicSyncUserCue = 0x2000, // Enable notifications on Music User Cue. AK_MusicSyncPoint = 0x4000, // Enable notifications on Music synchronisation point. AK_MusicSyncAll = 0xff00, // Use this flag if you want to receive all notifications concerning AK_MusicSync registration.
If you also want to receive a notification at the end of an event, you should use AK_EndOfEvent
| AK_MusicSyncBeat
since the flags are bitwise exclusive.
AkPlayingID AK::SoundEngine::PostEvent( AkUniqueID in_eventID, // Unique ID of the event AkGameObjectID in_gameObjectID, // Associated game object ID AkUInt32 in_uFlags = 0, // Bitmask: see AkCallbackType AkCallbackFunc in_pfnCallback = NULL, // Callback function void * in_pCookie = NULL // Callback cookie that will be sent to the callback function // along with additional information );
static void MusicCallback( AkCallbackType in_eType, // Type of callback reason, in this case it could be AK_MusicSyncBeat AkCallbackInfo* in_pCallbackInfo // Pointer to callback information structure, in this case // AkMusicSyncCallbackInfo*. )
AK_MusicSyncBar
notifications, you should return when any other event type is received.in_pCallbackInfo
into the appropriate information structure type. For music notifications, it is AkMusicSyncCallbackInfo./// Callback information structure corresponding to Ak_MusicSync struct AkMusicSyncCallbackInfo : public AkCallbackInfo { AkPlayingID playingID; ///< Playing ID of Event, returned by PostEvent() AkCallbackType musicSyncType; ///< Would be either AK_MusicSyncEntry, AK_MusicSyncBeat, AK_MusicSyncBar, AK_MusicSyncExit, AK_MusicSyncGrid, AK_MusicSyncPoint or AK_MusicSyncUserCue. AkReal32 fBeatDuration; ///< Beat Duration in seconds. AkReal32 fBarDuration; ///< Bar Duration in seconds. AkReal32 fGridDuration; ///< Grid duration in seconds. AkReal32 fGridOffset; ///< Grid offset in seconds. };
AK_MusicSyncBeat
and AK_MusicSyncBar
in a 4/4 time signature, you will receive 4 beat notifications per bar + one notification for the bar itself. Time "0" also counts for a beat and a bar and in most cases so does the AK_MusicSyncEntry
. This means that if you register for bars, beats and entry points, you will receive three callbacks back to back when the music starts.AK_MusicSyncExit
will only be sent if the end of the body of the current segment is reached. If the music switches to another segment before finishing the current one, the AK_MusicSyncExit
nofification will not be sent.The callback function described above may also be used to manually manage a music playlist's next item selection. This is done by adding the following flag.
AK_MusicPlaylistSelect = 0x0040 // Callback triggered when music playlist container must select the next item to play.
Upon reception of this type of event, the callback function must typecast the parameter in_pCallbackInfo
to type AkMusicPlaylistCallbackInfo.
/// Callback information structure corresponding to Ak_MusicPlaylistSelect struct AkMusicPlaylistCallbackInfo : public AkEventCallbackInfo { AkPlayingID playlistID; ///< ID of active node in music playlist container AkUInt32 uNumPlaylistItems; ///< Number of items in playlist node (may be segments or other playlists) AkUInt32 uPlaylistSelection; ///< Selection: set by sound engine, modified by callback function (if not in range 0 <= uPlaylistSelection < uNumPlaylistItems then ignored) AkUInt32 uPlaylistItemDone; ///< Playlist node done: set by sound engine, modified by callback function (if set to anything but 0 then the current playlist item is done, and uPlaylistSelection is ignored) };
The active playlist node is indicated by the member playlistID
. The sound engine selects the next item in the playlist node to play prior to the callback function call. The selection is contained in the members uPlaylistSelection
and uPlaylistItemDone
. If uPlaylistItemDone
is set to 0 then uPlaylistSelection
determines the next item to play in the playlist node. If uPlaylistItemDone
is not set to 0 then the current playlist node is to end (the parent node will then become the active node). Both members uPlaylistSelection
and uPlaylistItemDone
may be changed by the callback function.
Currently, notification is sent when the buffer is passed down to the hardware. This means that there is a certain constant delay between when the notification is sent and the moment it actually gets played. This gives your application enough time to gather the information on the marker and process it before the sound associated with that marker is really played.
Note that this delay is platform-dependent.
The callbacks are done from the sound engine's main thread. This means that your application should gather all the information it needs from the notification and return immediately. If any processing needs to be done, it should be performed in a separate thread after the relevant information has been copied from the notification.
If the application holds the thread for too long, the sound engine might fall into an underrun state and the output might stop playing.
Questions? Problems? Need more info? Contact us, and we can help!
Visit our Support pageRegister your project and we'll help you get started with no strings attached!
Get started with Wwise