Detecting when a Localised Audio Table's programmer sound ends

Hello,

I have a Localised Audio Table set up in FMOD to deal with dialogue. I’ve followed the Unity scripting example (https://www.fmod.com/resources/documentation-unity?version=2.2&page=examples-programmer-sounds.html) which works fine.

In order to close the dialogue box etc. after the dialogue has finished, I need to know when the audio ends, but can’t see how to do this.

I’ve tried invoking an event in DialogueEventCallback (in the DESTROY_PROGRAMMER_SOUND case) but this crashes Unity… from searching on the forums, this is because the callback is on a different thread.

I’ve tried waiting for the dialogueInstance created in PlayDialogue to have the STOPPED state (using dialogueInstance.getPlaybackState(out playbackState); ) but the state goes from STARTING to PLAYING, but then keeps the PLAYING state.

Am I doing something wrong/is there another way to detect when the sound ends?

Here’s my code:

public FMOD.Studio.EventInstance PlayDialogue(string key)
{
    var dialogueInstance = FMODUnity.RuntimeManager.CreateInstance(voiceEvent);

    // Pin the key string in memory and pass a pointer through the user data
    GCHandle stringHandle = GCHandle.Alloc(key, GCHandleType.Pinned);
    dialogueInstance.setUserData(GCHandle.ToIntPtr(stringHandle));

    dialogueInstance.setCallback(voiceCallback);
    dialogueInstance.start();
    dialogueInstance.release();

    return dialogueInstance;
}

voiceCallback is a copy of what’s in here: https://www.fmod.com/resources/documentation-unity?version=2.2&page=examples-programmer-sounds.html
I call this:

FMOD.Studio.EventInstance dialogueInstance = FMODManager.instance.PlayDialogue(line.line);
StartCoroutine(EndDialogue(dialogueInstance));

And:

IEnumerator EndDialogue(FMOD.Studio.EventInstance dialogueInstance)
        {
            FMOD.Studio.PLAYBACK_STATE playbackState = FMOD.Studio.PLAYBACK_STATE.STARTING;

            while (playbackState != FMOD.Studio.PLAYBACK_STATE.STOPPED)
            {
                dialogueInstance.getPlaybackState(out playbackState);
                print("Current state: " + playbackState);
                yield return null;
            }

            //hide dialogue box
            //stop character talking
            //ETC
        }

^^ this logs out STARTING about 3 times, then PLAYING until I’ve stopped Unity’s play mode.

The problem is that you are releasing the instance:

FMOD - Studio API Reference | Studio::EventInstance (studio eventinstance release)
Event instances marked for release are destroyed by the asynchronous update when they are in the stopped state

You should only release an instance once your are finished with it, outside of callbacks you won’t be able to assume that it is still valid. Instead you could use the EndDialogue function to hide the box and release the instance once you are finished with it.

Thanks - I admit I copied the example and didn’t look into each line of it! :slight_smile:

Releasing the instance after I’ve finished with it does allow the playback state to change to STOPPING and STOPPED, but way after the audio finishes.

As an example, my first line of dialogue should end at about timeline position 3100 (I’ve logged that out too), but the playback state doesn’t change until 10,005. The .wav file does end as soon as the speech is finished.

Any ideas what the problem could be?

I would check the length of the event in Studio, if there are instruments on the timeline then the event won’t stop until it has finished playing everything on the timeline.

It’s just dialogue (a single Programmer instrument) - there are no other instruments.

That instrument is 10 seconds long on the timeline, if it is not set to ‘async’ then each time you play the event it will play for a minimum of 10 seconds.

I was already set to async.

I’ve managed to fix it by deleting the programmer instrument, then adding a new one!

Thanks for your help.