“[FMOD] ShadowEventInstance::createProgrammerSound : Programmer sound callback is not set for instrument”

Hi, im getting all the time this message (“[FMOD] ShadowEventInstance::createProgrammerSound : Programmer sound callback is not set for instrument”) when trying to sound a dialogue.
The programmer instrument is properly created. I´m using 2 localized audio tables for two languages, one of them which also returns an error (that is already loaded regardless if its language is selected).
The code is the same as provided by the FMOD website, the only difference is that i call the method from another script.
Any idea?

Thank you

Hi,

Thank you for sharing the information.

Could I please grab the version number of your FMOD Unity integration?

This warning message indicates that FMOD is expecting a programmer sound callback to be set, but it hasn’t been. This callback is necessary for programmer instruments, as they rely on you to provide the audio data during playback. The programmer sound example script demonstrates how to set up a callback for programmer sounds.

Could you please share the exact error message? Is it the same error message as the one you mentioned above?

Unfortunately, I was not able to reproduce the issue from my side. Would it be possible to share a code snippet showing how you are calling the method from another script?

Thank you for your fast reply,

The intengration number is : Version: 2.02.26

The error returned for a localized bank is: [FMOD] Unable to load Dialogues_SPA - bank already loaded. This may occur when attempting to load another localized bank before the first is unloaded, or if a bank has been loaded via the API.
UnityEngine.Debug:LogWarningFormat (string,object)

Finally, the code im using. I´ve created the main Callback code (same as FMOD website in the script SoundManager.cs) and i´m calling it from the script Dialog.cs:

SoundManager.cs

public class SoundManager : MonoBehaviour
{
    public static SoundManager Instance { get; private set; }
 
    EVENT_CALLBACK dialogueCallback;
    public FMODUnity.EventReference Dialog;
public void PlayDialog(ETranslateID ID)
   {
       //RuntimeManager.PlayOneShot("event:/Dialog/" + ID.ToString());
       //RuntimeManager.PlayOneShot("event:/Dialog/dialog_0a");
 
       var dialogueInstance = RuntimeManager.CreateInstance(FMODEvents.Instance.Dialog);//Esto está bien
      // Pin the key string in memory and pass a pointer through the user data
       GCHandle stringHandle = GCHandle.Alloc(ID.ToString());
       Debug.LogError("Esto es " + stringHandle);
       dialogueInstance.setUserData(GCHandle.ToIntPtr(stringHandle));
       dialogueInstance.setCallback(dialogueCallback);
       dialogueInstance.start();
       dialogueInstance.getPlaybackState(out PLAYBACK_STATE dialoguesState);//Se inicia con normalidad
       dialogueInstance.release();
   }
 
   [AOT.MonoPInvokeCallback(typeof(EVENT_CALLBACK))]
   static FMOD.RESULT DialogueEventCallback(EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
   {
       FMOD.Studio.EventInstance instance = new EventInstance(instancePtr);
 
       // Retrieve the user data
       IntPtr stringPtr;
       instance.getUserData(out stringPtr);
 
       // Get the string object
       GCHandle stringHandle = GCHandle.FromIntPtr(stringPtr);
       String key = stringHandle.Target as String;

       switch (type)
       {
           case EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND: //Crea el sonido
               {
                   FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATECOMPRESSEDSAMPLE | FMOD.MODE.NONBLOCKING;
                   var parameter = (PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(PROGRAMMER_SOUND_PROPERTIES));
 
                   if (key.Contains("."))
                   {
                       FMOD.Sound dialogueSound;
                       var soundResult = RuntimeManager.CoreSystem.createSound(Application.streamingAssetsPath + "/" + key, soundMode, out dialogueSound);
                       if (soundResult == FMOD.RESULT.OK)
                       {
                           parameter.sound = dialogueSound.handle;
                           parameter.subsoundIndex = -1;
                           Marshal.StructureToPtr(parameter, parameterPtr, false);
                         
                       }
                   }
                   else
                   {
                       FMOD.Studio.SOUND_INFO dialogueSoundInfo;
                       var keyResult = FMODUnity.RuntimeManager.StudioSystem.getSoundInfo(key, out dialogueSoundInfo);
                       Debug.LogError("El sonido es " + dialogueSoundInfo);
                       if (keyResult != FMOD.RESULT.OK)
                       {
                           break;
                       }
                       FMOD.Sound dialogueSound;
                       var soundResult = FMODUnity.RuntimeManager.CoreSystem.createSound(dialogueSoundInfo.name_or_data, soundMode | dialogueSoundInfo.mode, ref dialogueSoundInfo.exinfo, out dialogueSound);
                       if (soundResult == FMOD.RESULT.OK)
                       {
                           parameter.sound = dialogueSound.handle;
                           parameter.subsoundIndex = dialogueSoundInfo.subsoundindex;
                           Marshal.StructureToPtr(parameter, parameterPtr, false);
                       }
                   }
                   break;
               }
           case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
               {
                   var parameter = (FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
                   var sound = new FMOD.Sound(parameter.sound);
                   sound.release();
 
                   break;
               }
           case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROYED:
               {
                   // Now the event has been destroyed, unpin the string memory so it can be garbage collected
                   stringHandle.Free();
 
                   break;
               }
       }
       return FMOD.RESULT.OK;
   }

The Dialog.cs script is
void DisplayData(DialogStepData stepData)
{
this.stepData = stepData;

    if (stepData.TextID == ETranslateID.EMPTY)
    {
        Text.transform.parent.gameObject.SetActive(false);
    } else
    {
        SoundManager.Instance.PlayDialog(stepData.TextID);
        Diálogo = true;
        Text.text = data.Talkers[stepData.Talker]
            .Replace("$", Overmind.GetTranslatedText(data.TalkersIDs[stepData.Talker])) 
            + Overmind.GetTranslatedText(stepData.TextID);
        if (stepData.Talker == 0)
        {
            TalkerChanged.Invoke(true);
        } else
        {
            TalkerChanged.Invoke(false);
        }
        Text.transform.parent.gameObject.SetActive(true);
    }

    for (int i = 0; i < AnswerTexts.Length; i++)
    {
        AnswerTexts[i].gameObject.SetActive(false);
    }
    for (int i = 0; i < stepData.AnswerIDs.Count; ++i)
    {
        if (stepData.Silent)
        {
            AnswerTexts[i].text = Overmind.GetTranslatedText(stepData.AnswerIDs[i]);
        }
        else
        {
            AnswerTexts[i].text = (i + 1) + ". " + Overmind.GetTranslatedText(stepData.AnswerIDs[i]);
        }
        AnswerTexts[i].gameObject.SetActive(true);
    }
}

Thank you in advance

This warning is benign. You could find a discussion of the same issue in this post:

From the code you shared, it seems that the dialogueCallback is declared but not assigned to DialogueEventCallback. Without this assignment, the callback won’t execute as expected.

To resolve this, please assign the callback in the Start or Awake method like this:

dialogueCallback = DialogueEventCallback;

Hope this helps, let me know if the issue persist.

Thank you very much for the reply
Unfortunately the problem persists.

I added the code you suggested to my start method, but the problem is the same.

private void Start()
    {
        
        UpdateSoundSettings();
        dialogueCallback = new FMOD.Studio.EVENT_CALLBACK(DialogueEventCallback);
       dialogueCallback = DialogueEventCallback;
        Dialog = FMODUnity.EventReference.Find("event:/EL TERROR ERRANTE/Conversations/Dialogues");
        

    }

Thank you for the code.

Looking at that code snippet we now need to set the callback to the event:

private void Start()
{
    UpdateSoundSettings();
    dialogueCallback = new FMOD.Studio.EVENT_CALLBACK(DialogueEventCallback);
    // dialogueCallback = DialogueEventCallback; ## We don't want to reassign the variable ##
    Dialog = FMODUnity.EventReference.Find("event:/EL TERROR ERRANTE/Conversations/Dialogues");

    // ## From the SoundManager.cs PlayDialog() function ##
    var dialogueInstance = RuntimeManager.CreateInstance(FMODEvents.Instance.Dialog);//Esto está bien
    // Pin the key string in memory and pass a pointer through the user data
    GCHandle stringHandle = GCHandle.Alloc(ID.ToString());
    Debug.LogError("Esto es " + stringHandle);
    dialogueInstance.setUserData(GCHandle.ToIntPtr(stringHandle));
    // ## Now we have assigned the callback we want to set it to the instance. ##
    dialogueInstance.setCallback(dialogueCallback);
    // ##
    dialogueInstance.start();
    dialogueInstance.getPlaybackState(out PLAYBACK_STATE dialoguesState);//Se inicia con normalidad
    dialogueInstance.release();
}