How To Know The Playing Clip

Hello,

I have a radio in my game, as you know radio is just playing music in sequence, so i have setup the FMOD project in one back putting all music in sequence to be played, and i start it by call an event to start it.

My problem is how to know that current song ended and a new one started, also how to know what is the new song name.

Also, if i want to create a favorite list of song, which play songs as you want, how to play a specific song and know that its end to start a new one.

Thanks.

Hi,

For knowing when the current song ended and started, you could create a callback function for FMOD events. The callback function will be triggered when specific event types occur, like when a song stops or a song starts. If you are looking for reference, we have a Timeline-Callback script example here : Unity Integration | 11. Scripting Examples | Timeline Callbacks

For getting an event’s name, you can get the song’s name from the EventDescription.getPath() FMOD Engine|6. Studio API Reference|Studio::EventDescription| Studio::EventDescription::getPath

A similar post you could find here:

For playing a new song when the previous song finished, you could use Event_CALLBACK Unity Integration | 2. User Guide | 2.5 Callbacks, which will be executed when an event starts/stops. Here is a simple script example:

NewRadioControllerTest.cs
using FMOD.Studio;
using FMODUnity;
using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class NewRadioControllerTest : MonoBehaviour
{
    [SerializeField] private EventReference[] radioEventRefs;
    [SerializeField] private int currentSongIndex;

    public class SongInfo
    {
        public int SongIndex = 0;
        public EventReference[] RadioEventRefs;
    }

    private static EVENT_CALLBACK sSongCallback;
    private static SongInfo sSongInfo;
    private static GCHandle sGCHandle;

    private EventInstance mCurrentSong;

    void Start()
    {
        sSongCallback = new EVENT_CALLBACK(SongEventCallback);

        //Create Song Info
        mCurrentSong = RuntimeManager.CreateInstance(radioEventRefs[currentSongIndex]);
        sSongInfo = new SongInfo();
        sSongInfo.RadioEventRefs = radioEventRefs;
        sSongInfo.SongIndex = currentSongIndex;

        SetCallBackAndPlaySong(mCurrentSong);
    }

    void OnDestroy()
    {
        mCurrentSong.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
        mCurrentSong.release();
    }

    // FMOD Event Callback function
    [AOT.MonoPInvokeCallback(typeof(EVENT_CALLBACK))]
    private static FMOD.RESULT SongEventCallback(EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
    {
        EventInstance instance = new EventInstance(instancePtr);

        // Retrieve the user data
        IntPtr songInfoPtr;
        FMOD.RESULT result = instance.getUserData(out songInfoPtr);
        GCHandle gcHandle = GCHandle.FromIntPtr(songInfoPtr);
        SongInfo songInfo = (SongInfo)gcHandle.Target;

        if (type == EVENT_CALLBACK_TYPE.STOPPED)
        {
            Debug.Log("Song has ended.");
            songInfo.SongIndex++;
            songInfo.SongIndex = songInfo.SongIndex % songInfo.RadioEventRefs.Length;

            gcHandle.Free();
            PlayNextSong(instance, songInfo.SongIndex, songInfo);
        }
        return FMOD.RESULT.OK;
    }

    public static void PlayNextSong(EventInstance instance, int index, SongInfo info)
    {
        if (instance.isValid())
        {
            instance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
            instance.release();
            EventInstance newSong = RuntimeManager.CreateInstance(info.RadioEventRefs[index]);
            sSongInfo = info;

            SetCallBackAndPlaySong(newSong);
        }
    }

    public static void SetCallBackAndPlaySong(EventInstance instance) 
    {
        // Pin the class that will store the data modified during the callback
        sGCHandle = GCHandle.Alloc(sSongInfo);

        // Pass the object through the userdata of the instance
        instance.setUserData(GCHandle.ToIntPtr(sGCHandle));
        instance.setCallback(sSongCallback, EVENT_CALLBACK_TYPE.STOPPED);
        instance.start();
    }
}

That way whenever the Song instance’s state has changed, the callback method will also be triggered, for your case, you could start playing the next song when the previous song has ended.

Hope it helps, let me know if you have more questions.