Example code for Programmer Instruments doesn't work. "Loading Delay Exceeded"

Hi,

I’m wanting to play audio from a file (currently a sample but I’ve read I can supply a .xm mod music file). Information seems sparse. As a first step, I’m trying to get the only fragment of example code working. Between this, https://fmod.com/docs/2.02/unity/examples-programmer-sounds.html, and the guide on Dialogue, https://www.fmod.com/docs/2.01/studio/dialogue-and-localization.html, I have created an FMOD bank with three sounds in my audio table pointing to three wave files in my Assets/StreamingAssets folder. Pressing a number key gives the warning error:

[FMOD] SoundSourceInstrumentInstance::startChannelIfReady : Loading delay exceeded, sound may play at incorrect time

Does anyone know how to get the Programmer Instrument example using an Audio Tables to work? Better yet, is there an example that shows how to load and play a file (.xm/.s3m/.mod tracker music file)? It feels like tracker support is mentioned as a feature but not showcased and not something we can realistically use.

Additionally, seen the related post about player modifiable audio here and followed:

Followed that to produce this code. I have “sound1.wav” in Assets/StreamingAssets. This code produces the error:

[FMOD] SoundSourceInstrumentInstance::startChannelIfReady : Waveform instance in error state 18

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using UnityEngine;

public class eatme : MonoBehaviour {
	FMOD.Studio.EVENT_CALLBACK soundCallback;
	public FMODUnity.EventReference programmerSoundEventRef;

	// Start is called before the first frame update
	void Start() {
		soundCallback = new FMOD.Studio.EVENT_CALLBACK(PlayFileCallBack);
	}

	[AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
	static FMOD.RESULT PlayFileCallBack(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr) {
		FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);

		if (instance.isValid() == false) {
			UnityEngine.Debug.Log("Failed to create instance, instance invalid");
			return FMOD.RESULT.ERR_EVENT_NOTFOUND;
		}

		//Retrive the user data 
		IntPtr stringPtr;
		instance.getUserData(out stringPtr);

		// Retrieving the path of the audio source from the user data
		GCHandle stringHandle = GCHandle.FromIntPtr(stringPtr);
		String location = stringHandle.Target as String;

		switch (type) {
			case FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND: {
				FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATECOMPRESSEDSAMPLE | FMOD.MODE.NONBLOCKING;
				var parameter = (FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));

				FMOD.Sound audioSound;
				FMOD.RESULT result;

				// Creating the sound using the location of the audio source 
				result = FMODUnity.RuntimeManager.CoreSystem.createSound(location, soundMode, out audioSound);

				if (result == FMOD.RESULT.OK) {
					parameter.sound = audioSound.handle;
					parameter.subsoundIndex = -1;
					Marshal.StructureToPtr(parameter, parameterPtr, false);
				}
				break;
			}
			case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND: {
				var paramerter = (FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
				var sound = new FMOD.Sound(paramerter.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 garbaged collected
				stringHandle.Free();
				break;
			}
		}
		return FMOD.RESULT.OK;
	}

	public void PlayAudioFile(string location) {
		var eventInstance = FMODUnity.RuntimeManager.CreateInstance(programmerSoundEventRef);

		// FMOD.RESULT is a very useful debugging tool to ensure that FMOD functions have run properly 
		FMOD.RESULT result;
		if (eventInstance.isValid() == false) {
			Debug.Log("Failed to create instance, instance invalid");
			return;
		}
		// Lock the file location in memory to be used in the CALLBACK function to find the audio source
		GCHandle stringLocation = GCHandle.Alloc(location);
		// Assigning this data to the created instance 
		result = eventInstance.setUserData(GCHandle.ToIntPtr(stringLocation));

		// Using an if statement like this after most FMOD function calls will help debug errors in code 
		if (result != FMOD.RESULT.OK) {
			Debug.Log("Failed to create evenInstance with  result of " + result);
			return;
		}


		// Check the result after each function call 
		result = eventInstance.setCallback(soundCallback);
		result = eventInstance.start();
		result = eventInstance.release();
		// The sound has successfully been created and played 
	}


	void Update() {
		if (Input.GetKeyDown(KeyCode.Alpha1)) {
			PlayAudioFile("sound1.wav");
		}
	}
}

Hi,

You will get the Waveform instance in error state 18 error when the location variable in your CALLBACK function isn’t pointing to the correct file. There should be other errors in your Unity Console that will help debug the problem as well. For example, mine looks like this:
image

The Waveform error should be accompanied by more specific FMOD errors to help debug the problem.

I believe the problem is in your Update() function. Currently, you are only passing the name of the audio source instead of its full file path. To fix it, simply pass: PlayAudioFile("ProjectName\Assets\StreamingAssets\sound1.wav");, or the full file path where ever that may be. It should now point FMOD directly at the audio source.

Hope this helps and I apologize that was not clear in my example, I’ll fix that!

Thanks. There were no other errors, red or yellow, other than the single Error 18 line. I have changed the filename to:

		PlayAudioFile("Assets\\StreamingAssets\\sound1.wav");

This plays the sound from within the editor and allows me to feed an alternative file. However, every time I press a key to play a sound, the sound plays but I get the warning:

[FMOD] SoundSourceInstrumentInstance::startChannelIfReady : Loading delay exceeded, sound may play at incorrect time

When I try supplying a mod music track (.xm, .mod and .s3m), I get the single yellow warning:

[FMOD] SoundSourceInstrumentInstance::startChannelIfReady : Waveform instance in error state 38

A couple of updated tutorials would be very welcome! It would help to specifically target creating a Programmer Instrument using Audio Tables and how to address swapping sounds with alternatives. This is currently divided between the example code and the chapter on Dialogue. Secondly, a different tutorial on supplying an audio file without using audio tables and being able to point to any particular file.

Cheers!

Hi,

The Loading delay exceeded, sound may play at incorrect time error means that too many samples are being loaded in at once, to solve this we need to change which FMOD.MODE we use when creating the sound. The line we will need to change is:

FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATECOMPRESSEDSAMPLE | FMOD.MODE.NONBLOCKING;

//Too 

FMOD.MODE soundMode = FMOD.MODE.CREATESTREAM;

In the CALLBACK function. This mode is explained under FMOD API Reference | Common | FMOD_MODE.

Waveform instance in error state 38 is due to an invalid seek position being passed into the createSound() function. Unfortunately, I was not able to recreate this error when loading in a mod file. However, a solution may be using StudioSystem.setStreamBufferSize() to increase read head, as explained under Core API Reference | System.

We are always looking to improve our documentation and I have passed on your comments to our dev team.

Fabulous! This fixed both errors and my mod is playing. Now I can add music to my awesome sound effects! :grin:

1 Like