Timeline marker callback script in C# only reading first marker

Hi, I’m the sound designer for a project that’s using interactive music and we want to use a marker as a callback to reset a parameter during an event. I’m not a programmer and my programmer has never used FMOD before and we can’t get the timeline marker callbacks working properly. Using the example script in FMOD’s API he is able to read the first marker in the event, but no others. He is able to progress through the event normally so he should be passing the other markers in the timeline. The marker we need to use is called “To Loop Start” and it’s near the end of the event. Here is a copy of his script:

using System;
using System.Runtime.InteropServices;
using UnityEngine;

class ScriptUsageTimeline:MonoBehaviour
{
// Variables that are modified in the callback need to be part of a seperate class.
// This class needs to be ‘blittable’ otherwise it can’t be pinned in memory.
[StructLayout(LayoutKind.Sequential)]
class TimelineInfo
{
public int currentMusicBar = 0;
public FMOD.StringWrapper lastMarker = new FMOD.StringWrapper();
}

TimelineInfo timelineInfo;
GCHandle timelineHandle;

FMOD.Studio.EVENT_CALLBACK beatCallback;
FMOD.Studio.EventInstance musicInstance;

void Start()
{
    timelineInfo = new TimelineInfo();

    // Explicitly create the delegate object and assign it to a member so it doesn't get freed
    // by the garbage collected while it's being used
    beatCallback = new FMOD.Studio.EVENT_CALLBACK(BeatEventCallback);

    musicInstance = FMODUnity.RuntimeManager.CreateInstance("event:/Music/Bard/Phase 1/3D/Bard Index Temp");

    // Pin the class that will store the data modified during the callback
    timelineHandle = GCHandle.Alloc(timelineInfo,GCHandleType.Pinned);
    // Pass the object through the userdata of the instance
    musicInstance.setUserData(GCHandle.ToIntPtr(timelineHandle));

    musicInstance.setCallback(beatCallback,FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_BEAT | FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER);
    musicInstance.start();
}

void OnDestroy()
{
    musicInstance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
    musicInstance.release();
    timelineHandle.Free();
}

void OnGUI()
{
    GUILayout.Box(String.Format("Current Bar = {0}, Last Marker = {1}",timelineInfo.currentMusicBar,(string)timelineInfo.lastMarker));
}

[AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
static FMOD.RESULT BeatEventCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type,FMOD.Studio.EventInstance instance,IntPtr parameterPtr)
{
    // Retrieve the user data
    IntPtr timelineInfoPtr;
    instance.getUserData(out timelineInfoPtr);

    // Get the object to store beat and marker details
    GCHandle timelineHandle = GCHandle.FromIntPtr(timelineInfoPtr);
    TimelineInfo timelineInfo = (TimelineInfo)timelineHandle.Target;

    switch(type)
    {
        case FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_BEAT:
            {
                var parameter = (FMOD.Studio.TIMELINE_BEAT_PROPERTIES)Marshal.PtrToStructure(parameterPtr,typeof(FMOD.Studio.TIMELINE_BEAT_PROPERTIES));
                timelineInfo.currentMusicBar = parameter.bar;
            }
            break;
        case FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER:
            {
                var parameter = (FMOD.Studio.TIMELINE_MARKER_PROPERTIES)Marshal.PtrToStructure(parameterPtr,typeof(FMOD.Studio.TIMELINE_MARKER_PROPERTIES));
                timelineInfo.lastMarker = parameter.name;
            }
            break;
    }
    return FMOD.RESULT.OK;
}

}

From what I can see, your code is basically the same as our examples which have no problem displaying the correct marker.

Trying to debug callbacks in Unity can be a pain and cause Unity to lockup, I would start by adding in some Debug.Log lines to see if the code is being called at all.

Thanks, Cameron! We were able to get it working fine a few days ago. We needed to adapt it better to suit our event.