Download

Cannot get AudioComponent PlaybackTime

Hello guys.I don’t really know if I should put it here on in Audio group but it’s code so I’ve chosen to post it here.
I’m struggling with getting PlaybackTime as I mentioned in title.My AudioComponent is created with use of SpawnSound2D engine node. My function now looks like this:



 float MyAudioClass::GetPlaybackTime(UAudioComponent* AudioComponent)
 {
     if (AudioComponent)
     {
         FAudioDevice* AudioDevice = AudioComponent->GetAudioDevice();
         if (AudioDevice)
         {
             FActiveSound* ActiveSound = AudioDevice->FindActiveSound(AudioComponent->GetAudioComponentID());
             if (ActiveSound)
             {
                 return ActiveSound->PlaybackTime;
             }
             return 0;
         }
         return 0;
     }
     return 0;
 }


The error i get is : Assertion failed: IsInAudioThread()

Sadly, I’ve never before worked with Sound so I can’t quite understand why it doesn’t work. It crashes exactly with this line:
FActiveSound* ActiveSound = AudioDevice->FindActiveSound(AudioComponent->GetAudioComponentID());
If anyone can point for me why is that I will be so glad :3

You can’t get the Active Sound because you’re trying to run that function / dereference on the Game Thread, but Audio runs in it’s own Audio Thread. If you look at the function definition for FindActiveSound(), it’s failing on the check:



FActiveSound* FAudioDevice::FindActiveSound(const uint64 AudioComponentID)
{
	check(IsInAudioThread());

	// find the active sound corresponding to this audio component
	return AudioComponentIDToActiveSoundMap.FindRef(AudioComponentID);
}


If you want to get the Playback Time of an active sound, the best way is to make a binding to the Playback Delegates in the AudioComponent:



	/** called when we finish playing audio, either because it played to completion or because a Stop() call turned it off early */
	UPROPERTY(BlueprintAssignable)
	FOnAudioPlaybackPercent OnAudioPlaybackPercent;

	/** shadow delegate for non UObject subscribers */
	FOnAudioPlaybackPercentNative OnAudioPlaybackPercentNative;


Thank you TheJamsh! It was really helpfull for me. Didn’t knew what that before. Gonna check it out now. I’ll post here how it went for me :smiley:

No worries, this caught me out recently too :slight_smile:

Okay I’ve got one more question. It seems that I cannot bind it like I did before with OnAudioFinished. I mean, I’m providing the same arguments but it doesn’t take it :stuck_out_tongue:
It looks like this:
AudioComponent->OnAudioPlaybackPercent.AddDynamic(this,&UAudioController::SoundFinished);

Does it mean that I can’t use AddDynamic? It says:
no instance of function template matches the argument list :confused:

Ok, I’m retarded. I didn’t noticed that this delegate need parameters of const USoundWave* and float. Still i have no clue how cna i get my audio component inside of this function :confused:

So I can’t quite make it work :frowning: What I’ve done for now is this:
1.) I’m Creating AudioComponent.
2.)Then I’m binding delegate like this: AudioComponent->OnAudioPlaybackPercent.AddDynamic(this, &UAudioController::GimmePlaybackPosition);
Function I binded looks like this:



void UAudioController::GimmePlaybackPosition(const USoundWave* SoundWave, float PlaybackPercent)
{
	FAudioDevice* AudioDevice = GEngine->GetAudioDevice();
	if (AudioDevice)
	{
		FActiveSound* ActiveSound = AudioDevice->FindActiveSound(AudioComponentID);
		if (ActiveSound)
		{
			PlaybackTime=ActiveSound->PlaybackTime;
		}
		
	}
}


PlaybackTime is static float and AudioComponentID is static uint64. Can you show me some example how to do this properly? No clue here at all, couse this “solution” provides exactly same error

This is how I use it:

Header



	UPROPERTY(BlueprintReadOnly, Category = "Components")
	UAudioComponent* MusicAudioComponent;

	UFUNCTION()
	void OnMusicPlayback(const USoundWave* PlayingWave, const float PlaybackPercent);


CPP



UECGame_AudioManager::UECGame_AudioManager(const FObjectInitializer& OI)
	: Super(OI)
{
	// Create the Music Component
	MusicAudioComponent = OI.CreateDefaultSubobject<UAudioComponent>(this, TEXT("MusicAudioComponent"));
	MusicAudioComponent->OnAudioPlaybackPercent.AddDynamic(this, &UECGame_AudioManager::OnMusicPlayback);
}

void UECGame_AudioManager::OnMusicPlayback(const USoundWave* PlayingWave, const float PlaybackPercent)
{
	const float CurrentPlaybackTime = PlayingWave->Duration * PlaybackPercent;
}


In your example you’re still trying to call AudioDevice->FindActiveSound(). You can’t do that.