# Get Programmer Instrument Sound Length

**URL:** <https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413>\
**Category:** Unity\
**Created:** [November 9, 2020, 1:22pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413 "2020-11-09T13:22:32Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![NikMikk](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/nikmikk/32/5599_2.png) [@NikMikk](https://qa.fmod.com/u/NikMikk)\
**Post date:** [November 9, 2020, 1:22pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/1 "2020-11-09T13:22:32Z")

</div>

I’m using a programmer instrument together with an audio table to play music inside my cassette player and I want to display the duration of the played track, currently “played time” works but I can’t seem to get the total length of the track.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/4/4f92019abe1a705b5c49312624537906adda153c.jpeg)

I’ve been reading on the forum and the closest I got was this post:  
https://qa.fmod.com/t/get-length-duration-of-programmer-instrument-audio-table-loaded-sound/13911

Following the post above I get the correct subSound index based on the audio table but I can’t get the length to work consistently, it works like 1/20 times for some reason?

Here’s the full callback:

```
[AOT.MonoPInvokeCallback(typeof(EVENT_CALLBACK))]
static RESULT PlayMusicEventCallback(EVENT_CALLBACK_TYPE type, EventInstance eventInstance, IntPtr parameterPtr)
{
	// Retrieve the user data
	eventInstance.getUserData(out var 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:
		{
			const MODE soundMode = MODE.LOOP_OFF | MODE.CREATESTREAM | MODE.NONBLOCKING;
			var parameter = (PROGRAMMER_SOUND_PROPERTIES) Marshal.PtrToStructure(parameterPtr, typeof(PROGRAMMER_SOUND_PROPERTIES));

			var keyResult = RuntimeManager.StudioSystem.getSoundInfo(key, out var musicSoundInfo);
			if (keyResult != RESULT.OK)
			{
				break;
			}

            // Attempt to get the track's length!
			var soundResult = RuntimeManager.CoreSystem.createSound(musicSoundInfo.name_or_data, soundMode | musicSoundInfo.mode, ref musicSoundInfo.exinfo, out Sound musicSound);
			Sound subSound;
			musicSound.getSubSound(musicSoundInfo.subsoundindex, out subSound); 
			uint length = 0; 
			subSound.getLength(out length, FMOD.TIMEUNIT.MS); 
			
			CassettePlayer.instance.SetMaxTrackDuration(length);
			Debug.Log(length);
			
			if (soundResult == RESULT.OK)
			{
				parameter.sound = musicSound.handle;
				parameter.subsoundIndex = musicSoundInfo.subsoundindex;
				Marshal.StructureToPtr(parameter, parameterPtr, false);
			}
			else
			{
				Debug.LogError("Error creating sound!");
			}
			
			break;
		}

		case EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
		{
			var parameter = (PROGRAMMER_SOUND_PROPERTIES) Marshal.PtrToStructure(parameterPtr, typeof(PROGRAMMER_SOUND_PROPERTIES));
			var sound = new Sound {handle = parameter.sound};
			sound.release();
			break;
		}
		case EVENT_CALLBACK_TYPE.DESTROYED:
		{
			// Now the event has been destroyed, unpin the string memory so it can be garbage collected
			stringHandle.Free();
			break;
		}
	}

	return RESULT.OK;
}
```

---

<div class="post-metadata">

**Author:** ![cameron-fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/cameron-fmod/32/261_2.png) [@cameron-fmod](https://qa.fmod.com/u/cameron-fmod)\
**Post date:** [November 11, 2020, 3:50am UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/2 "2020-11-11T03:50:02Z")

</div>

`subSound.getLength` (as well as `musicSound.getSubSound`) will return an `FMOD.RESULT` that could indicate why it isn’t working.

---

<div class="post-metadata">

**Author:** ![NikMikk](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/nikmikk/32/5599_2.png) [@NikMikk](https://qa.fmod.com/u/NikMikk)\
**Post date:** [November 13, 2020, 10:42pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/3 "2020-11-13T22:42:00Z")

</div>

I’m getting an `ERR_NOTREADY` result from the getSubSound, might be because we’re streaming the audio using `MODE.CREATESTREAM`?

Here’s code snipped again (runs inside `CREATE_PROGRAMMER_SOUND` callback)

```
var soundResult = RuntimeManager.CoreSystem.createSound(musicSoundInfo.name_or_data, soundMode | musicSoundInfo.mode, ref musicSoundInfo.exinfo, out Sound musicSound);
Sound subSound;
RESULT result = musicSound.getSubSound(musicSoundInfo.subsoundindex, out subSound);
if (result != RESULT.OK)
{
	Debug.LogError(result.ToString());
}
else
{
	uint length = 0;
	result = subSound.getLength(out length, FMOD.TIMEUNIT.MS);
	if (result != RESULT.OK)
	{
		Debug.LogError(result.ToString());
	}
	else
	{
		CassettePlayer.instance.SetMaxTrackDuration(length);
	}
}
```

---

<div class="post-metadata">

**Author:** ![cameron-fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/cameron-fmod/32/261_2.png) [@cameron-fmod](https://qa.fmod.com/u/cameron-fmod)\
**Post date:** [November 15, 2020, 11:18pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/4 "2020-11-15T23:18:39Z")

</div>

This is because you are using `NONBLOCKING` when you create the sound:

> [System::createSound](https://www.fmod.com/resources/documentation-api?version=2.1&page=core-api-system.html#system_createsound)
> 
> Use [FMOD\_NONBLOCKING](https://www.fmod.com/resources/documentation-api?version=2.1&page=core-api-common.html#fmod_nonblocking) to have the sound open or load in the background. You can use [Sound::getOpenState](https://www.fmod.com/resources/documentation-api?version=2.1&page=core-api-sound.html#sound_getopenstate) to determine if it has finished loading / opening or not. While it is loading (not ready), sound functions are not accessible for that sound.

---

<div class="post-metadata">

**Author:** ![NikMikk](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/nikmikk/32/5599_2.png) [@NikMikk](https://qa.fmod.com/u/NikMikk)\
**Post date:** [November 20, 2020, 1:36pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/5 "2020-11-20T13:36:55Z")

</div>

Using LateUpdate to check if [Sound::getOpenState](https://www.fmod.com/resources/documentation-api?version=2.1&page=core-api-sound.html#sound_getopenstate) == OK fixed my issue, Thanks Cameron!

Here’s the code:

```
// Inside LateUpdate switch case logic
var result = musicSound.getOpenState(out var openState, out _, out _, out _);
if (result == RESULT.OK)
{
	if (openState != OPENSTATE.ERROR)
	{
		musicSound.getSubSound(subSoundIndex, out var subSound);
		// Wait until the length have been fetched!
		result = subSound.getLength(out var length, FMOD.TIMEUNIT.MS);
		if (result == RESULT.OK)
		{
			CassettePlayer.instance.SetMaxTrackDuration((int) length);
			gotMaxLength = true;
		}
	}
}
```

---

<div class="post-metadata">

**Author:** ![chadfind](https://avatars.discourse-cdn.com/v4/letter/c/49beb7/32.png) [@chadfind](https://qa.fmod.com/u/chadfind)\
**Post date:** [February 9, 2025, 6:42pm UTC](https://qa.fmod.com/t/get-programmer-instrument-sound-length/16413/6 "2025-02-09T18:42:26Z")

</div>

Thank you both for posting this - was having issues with getting length and thought one reason might be because it wasn’t ready (among a few other reasons I had listed to test). This was super helpful in quickly solving that!
