Assertion failed isInAudioThread()

227276-captura.png

The game crashed in a develoment build, when try to set a different audio in audio component
FAudioDevice::FindActiveSound() //why this crash on develoment build and not in other? Bug?

Same thing for me on 4.22.3, and it also happens when I play in standalone game mode but not in-engine and not in the shipping version. I’m using the Oculus Lipsync SDK btw, I think that was what triggered that behaviour, hopefully, it gets fixed by 4.23.something. Cheers :slight_smile:

UE4 heavily use assertion. Assertion fail happens if mentioned condition fails, this condition is what code susspect to be true for stable operation, anything else is expected to cause a crash, so insted of letting that happen it crashes it self with info which condition failed. You can read about assertion here

So by that it sould be very clear what failed, IsInAudioThread() means that this function was expected to only run on audio thread and you calling it from game thread. I also check the code and theres no check for development build, this check happens out of the bat always on that function, so cause might be something else (like you calling this function only in development build or function you make a call is executed by audio thread on other builds then devlopment build, or something else).

You can access audio thread controls from this class:

What will interest you the most is RunCommandOnAudioThread(TFunction<void()>) which let you execute function in audio thread, it is best to use lamdas (nested functions) to pass this pointer:

	FAudioThread::RunCommandOnAudioThread([this]()
	{
		//code that will run in audio thread

	});

You can pass more variables in by adding it like this [this,VarA,VarB]

Now here the catch, if you know a little big about threading you should know this function won’t be executed with sequance of game thread, it will be executed later on (next time when audio thread will be free), so you wont be able to get return of a function, because when it’s gonna run you game thread function is most likely already be finished. So best practice is to do actual actions then getting values. here nice exmaple from FAudioDevice (this function was made to run on both game and audio thread and you can see code is breaching off depending on which thread it runs):

void FAudioDevice::StopActiveSound(const uint64 AudioComponentID)
{
	if (!IsInAudioThread())
	{
		DECLARE_CYCLE_STAT(TEXT("FAudioThreadTask.StopActiveSound"), STAT_AudioStopActiveSound, STATGROUP_AudioThreadCommands);

	FAudioDevice* AudioDevice = this;
	FAudioThread::RunCommandOnAudioThread([AudioDevice, AudioComponentID]()
	{
		AudioDevice->StopActiveSound(AudioComponentID);
	}, GET_STATID(STAT_AudioStopActiveSound));

	return;
}

FActiveSound* ActiveSound = FindActiveSound(AudioComponentID);
if (ActiveSound)
{
	AddSoundToStop(ActiveSound);
}
}

If you can’t, you will need to do call back to game thread with RunCommandOnGameThread to send results back

Thanks for the thorough explanation!!! :slight_smile: Unfortunately, I haven’t modified any audio object at any time. Would you think that piece code is out of place and could cause this assertion to fail? Otherwise, I’m afraid it’s some engine code doing the mischief :confused:

	if (AudioComponent)
	{
		FAudioDevice *AudioDevice = AudioComponent->GetAudioDevice();
		if (AudioDevice)
		{
			FActiveSound *ActiveSound = AudioDevice->FindActiveSound(AudioComponent->GetAudioComponentID());
			if (ActiveSound)
			{
				Percent = ActiveSound->PlaybackTime / AudioComponent->Sound->GetDuration();
			}
		}
	}

Did you install any plugins for your project?

Multiple, but if I would blame any would be the Oculus Lipsync SDK, which messes with audio and was the one we added that made the game start displaying that behavior.

Yes, sorry forgot to mention more direcly FindActiveSound is indeed audio thread only and cause assert fail. So you can try to do this:

FAudioDevice *AudioDevice = AudioComponent->GetAudioDevice();
uint64 AudioComponentID = AudioComponent->GetAudioComponentID();

 FAudioThread::RunCommandOnAudioThread([this, AudioDevice, AudioComponentID]()
 {
             FActiveSound *ActiveSound = AudioDevice->FindActiveSound(AudioComponentID);
             if (ActiveSound)
             {
                 this->PlaybackTime = ActiveSound->PlaybackTime;
             }

 });

PlaybackTime would be variable on object you operating in, make sure that only audio thread set this variable, also make sure you don’t do any other call to audio thread. Problem with this one is fact that you will need to process result in different event, i don’t know what you trying to do. If it’s for UI display then you can do function binding to show result on widget

Again keep in mind you be running between threads which may or not run on different CPU cores independently, it like heaving two independent heads that execute code which one fon’t wait for another and they not aware of there positions to each other. If you do function call in audio thread it will be audio thread that will execute the code not game thread, your code surly is design by assumption that only single thread is running it on specific order (most of enigne code is like that too), if you start calling things in audio thread that asumpt order will be disrupted and things may start to happening out of order and mess up leading to crash or unpredictable behavior, so you should not perform any writing operations on audio thread other then that playback time just to pass that value.

Please describe what you actually trying to do, maybe there a lot better alternative way to do this from what you trying to achieve potentially even avoiding interaction with audio thread all together.