When you load an FMOD Studio bank that has an audio table attached to it, the keys in that audio table are front loaded into your game. There is no need to point to the audio table itself as this is done automatically.
It’s important to have each key be unique if you are loading multiple banks that have audio tables. If there are any keys that are duplicates across audio tables, the most recently loaded bank will take priority.
To understand how
DialogueEventCallback works it’s important to realise that the
FMOD.Studio.EventInstance objects created in C# are actually wrappers for unamanged objects created by the FMOD studio runtime library. The unmanaged objects do all the work and the C# wrappers store links to the unmanaged objects and allow C# code to perform operations on the unamanged objects.
FMODUnity.RuntimeManager.CreateInstance a new unmanaged event instance is created by the FMOD studio runtime library and a wrapper for that unmanaged object is returned and stored in
dialogueInstance. The remainder of the
PlayDialogue function performs a number of operations on the event instance. The wrapper is used to store the audio table key which was passed to
PlayDialogue in the event instance’s user data, and uses the
setCallback method to tell the FMOD studio runtime library which function to call to handle callbacks for the event instance. Because the audio table key string needs to be kept until the event instance is finished with it we have to pin the memory for the string in
PlayDialogue. When the
PlayDialogue function returns the
dialogueInstance wrapper goes out of scope and can be cleaned up, but the unmanaged event instance sticks around (it will be cleaned up later on by the FMOD studio runtime library, after the event has finished playing).
Later on, the callback is invoked by the FMOD studio runtime library when it needs to create the programmer sound for the event. The
instancePtr parameter is a link to the same unmanaged event instance which was created by
PlayDialogue. The callback can’t do anything directly with the unmanaged event instance so it creates a new C# wrapper for it. It’s important to understand that this is just a new wrapper, and not a new event instance, so when the callback retrieves the user data from the event instance it will get the audio table key which was stored there in
When the callback is called to process the
CREATE_PROGRAMMER_SOUND event the extra
parameterPtr parameter is used to pass a link to an
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES structure. The callback has to create an unmanaged FMOD sound for the event to play and store it in the structure. This is done in the example by using the audio table key retrieved from the event instance’s user data to lookup the information needed to create the correct sound using
FMODUnity.RuntimeManager.LowlevelSystem.createSound. The output FMOD.Sound from
FMODUnity.RuntimeManager.LowlevelSystem.createSound is actually a C# wrapper for the unmanaged FMOD sound and we use
dialogueSound.getRaw() to retrieve a link to the unmanaged FMOD sound which needs to be returned in the
PROGRAMMER_SOUND_PROPERTIES structure. This is the important / interesting output of the callback in this case.
The callback will be called again to cleanup the programmer sound when the event is finished with it. In this case the
instancePtr parameter is once again a link to the unmanaged event instance and
parameterPtr is a link to an
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES structure which contains a link to an unmanaged FMOD sound which the callback needs to clean up. The callback creates a new C# wrapper for the lowlevel sound and calls release on the wrapper to clean it up.
The callback is called one last time when the event is destroyed. This is the right time to unpin the string memory containing the audio table key which was originally passed to
PlayDialogue so that it can be cleaned up by the garbage collector.
I hope this has cleared up how to use programmer sounds.