Hi !
Here is a more complete code source:
We are storing inside the EventInstance’s user data a structure called AudioTableInstance that contains FMOD::Sound*
struct AudioTableInstance
{
String sEventDescName;
EventDesc oEventDesc = I_AUDIO_INVALID_EVENT_DESC;
EventInstance oEventInstance = I_AUDIO_INVALID_EVENT_INSTANCE;
String sAudioFile;
void* pSound = NULL; // FMOD::Sound*
int iSubSoundIndex;
bool bIsSoundLengthReady = false;
uint32 iSoundLenghtMs;
};
Programmer Sound EventInstance creation and play command:
AudioTableInstance* AudioDriverFModStudio::CreateAudioTableInstance( const char* pEventName, AudioTableInstanceCallback pCallback, void* pCallbackUserData )
{
// Get event desc
EventDesc oEventDesc = GetEventDesc( pEventName );
if( oEventDesc == I_AUDIO_INVALID_EVENT_DESC )
{
return NULL;
}
FMOD::Studio::EventDescription* pFMODEventDesc = PA_EVENTDESC_TO_FMOD( oEventDesc );
PA_ASSERT( pFMODEventDesc!= NULL );
// Create an event instance
FMOD::Studio::EventInstance* pFMODEventInstance = NULL;
FMOD_RESULT iResult = pFMODEventDesc->createInstance( &pFMODEventInstance );
if( iResult != FMOD_OK )
{
PA_FMOD_LOG_AND_ASSERT_ON_ERROR( ERROR, iResult );
return NULL;
}
AudioTableInstance* pResult = new AudioTableInstance();
pResult->sEventDescName = pEventName;
pResult->oEventDesc = oEventDesc;
pResult->oEventInstance = PA_FMOD_TO_EVENTINSTANCE( pFMODEventInstance );
pResult->pAudioTableInstanceCallback = pCallback;
pResult->pCallbackUserData = pCallbackUserData;
iResult = pFMODEventInstance->setUserData( pResult );
PA_FMOD_LOG_AND_ASSERT_ON_ERROR( ERROR, iResult );
pFMODEventInstance->setCallback( AudioTableSoundCallback, FMOD_STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND | FMOD_STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND | FMOD_STUDIO_EVENT_CALLBACK_SOUND_PLAYED | FMOD_STUDIO_EVENT_CALLBACK_SOUND_STOPPED | FMOD_STUDIO_EVENT_CALLBACK_DESTROYED );
PA_FMOD_LOG_AND_ASSERT_ON_ERROR( ERROR, iResult );
PA_VERIFY( pResult->oLockVar.Create() == PA_OK );
return pResult;
}
void AudioDriverFModStudio::AudioTablePlaySound( AudioTableInstance* pAudioTableInstance, const String& sAudioFile )
{
PA_ASSERT( pAudioTableInstance != NULL );
pAudioTableInstance->sAudioFile = sAudioFile;
pAudioTableInstance->bIsSoundLengthReady = false;
pAudioTableInstance->iSoundLenghtMs = (uint32)-1;
EventInstanceCommand( pAudioTableInstance->oEventInstance,
Audio::IAudioDriver::EVENT_PLAY );
}
And the main callback function:
// Audio Table event callback
FMOD_RESULT F_CALLBACK AudioDriverFModStudio::AudioTableSoundCallback( FMOD_STUDIO_EVENT_CALLBACK_TYPE type, FMOD_STUDIO_EVENTINSTANCE* event, void* parameters )
{
FMOD::Studio::EventInstance* pEventInstance = (FMOD::Studio::EventInstance*)event;
FMOD_RESULT iResult;
AudioDriverFModStudio* pAudioDriver = (AudioDriverFModStudio*)s_pAudioDriver;
PA_ASSERT( pAudioDriver != NULL );
PA_ASSERT( pAudioDriver->m_pSystem != NULL );
PA_ASSERT( pAudioDriver->m_pEventSystem != NULL );
AudioTableInstance* pAudioTableInstance = NULL;
pEventInstance->getUserData( ( void** )&pAudioTableInstance );
PA_ASSERT( pAudioTableInstance != NULL );
switch( type )
{
case FMOD_STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND:
{
FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES* props = (FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES*)parameters;
// get the user - defined context of the programmer sound
PA_ASSERT( pAudioTableInstance != NULL );
// Find the audio file in the audio table with the key
FMOD_STUDIO_SOUND_INFO info;
iResult = pAudioDriver->m_pEventSystem->getSoundInfo( pAudioTableInstance->sAudioFile.c_str(), &info );
PA_FMOD_LOG_STRING_AND_ASSERT_ON_ERROR( ERROR, iResult, pAudioTableInstance->sAudioFile.c_str() );
FMOD::Sound* pSound = NULL;
iResult = pAudioDriver->m_pSystem->createSound( info.name_or_data, FMOD_LOOP_NORMAL | FMOD_CREATECOMPRESSEDSAMPLE | FMOD_NONBLOCKING | info.mode, &info.exinfo, &pSound );
PA_FMOD_LOG_AND_ASSERT_ON_ERROR( ERROR, iResult );
//https://qa.fmod.com/t/how-to-know-the-duration-of-a-programmer-sound-in-advance/14987/2
pAudioTableInstance->pSound = pSound;
pAudioTableInstance->iSubSoundIndex = info.subsoundindex;
props->sound = (FMOD_SOUND*)pSound;
props->subsoundIndex = info.subsoundindex;
return FMOD_OK;
}
case FMOD_STUDIO_EVENT_CALLBACK_SOUND_PLAYED:
{
FMOD::Sound* pSound = (FMOD::Sound*)pAudioTableInstance->pSound;
FMOD::Sound* pSubSound = NULL;
iResult = pSound->getSubSound( pAudioTableInstance->iSubSoundIndex, &pSubSound );
PA_FMOD_LOG_AND_ASSERT_ON_ERROR( ERROR, iResult );
uint32 iSoundLength = 0;
uint32 iSubSoundLength = 0;
iResult = pSound->getLength( &iSoundLength, FMOD_TIMEUNIT_MS );
iResult = pSubSound->getLength( &iSubSoundLength, FMOD_TIMEUNIT_MS );
PA_LOG( "Sound length: %d VS %d", iSoundLength, iSubSoundLength );
return FMOD_OK;
}
}
}
In my case, I’m just using one ProgrammerSound / AudioTable, that can uses different “subsound”
My goal is the get the subsound lengh as soon as possible
On some very short subsound:
returns FMOD_ERR_NOTREADY