Files
UnrealEngine/Engine/Source/Runtime/MovieSceneTracks/Private/Systems/MovieSceneAudioSystem.h
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

147 lines
4.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreTypes.h"
#include "EntitySystem/MovieSceneEntityIDs.h"
#include "EntitySystem/MovieSceneSequenceInstanceHandle.h"
#include "MovieSceneTracksComponentTypes.h"
#include "UObject/ObjectMacros.h"
#include "Channels/MovieSceneAudioTriggerChannel.h"
#include "EntitySystem/MovieSceneEntitySystem.h"
#include "Generators/SoundWaveScrubber.h"
#include "MovieSceneAudioSystem.generated.h"
class IAudioParameterControllerInterface;
class UAudioComponent;
class UMovieSceneAudioSection;
class USoundBase;
struct FMoveSceneAudioTriggerState;
namespace UE::MovieScene
{
struct FGatherAudioInputs;
struct FGatherAudioTriggers;
struct FEvaluateAudio;
struct FPreAnimatedAudioStorage;
struct FAudioComponentInputEvaluationData
{
TMap<FName, float> Inputs_Float;
TMap<FName, FString> Inputs_String;
TMap<FName, bool> Inputs_Bool;
TMap<FName, int32> Inputs_Int;
TArray<FName> Inputs_Trigger;
};
struct FAudioComponentEvaluationData
{
/** The audio component that was created to play audio */
TWeakObjectPtr<UAudioComponent> AudioComponent;
#if WITH_EDITOR
/** While in editor, we can scrub the audio in the audio component. */
TObjectPtr<UScrubbedSound> ScrubbedSound;
#endif
/** Volume multiplier to use this frame */
double VolumeMultiplier = 1.0;
/** Pitch multiplier to use this frame */
double PitchMultiplier = 1.0;
/**
* Set whenever we ask the Audio component to start playing a sound.
* Used to detect desyncs caused when Sequencer evaluates at more-than-real-time.
*/
TOptional<float> PartialDesyncComputation;
/** Previous audio time taking into account any time dilation */
TOptional<float> LastAudioTime;
/** The context time from the previous evaluation pass */
TOptional<float> LastContextTime;
/** Flag to keep track of audio components evaluated on a given frame */
bool bEvaluatedThisFrame = false;
/** Flag to keep track of if the audio component was played in a previous frame. */
bool bAudioComponentHasBeenPlayed = false;
};
}
/**
* System for evaluating audio tracks
*/
UCLASS()
class UMovieSceneAudioSystem : public UMovieSceneEntitySystem
{
GENERATED_BODY()
public:
using FInstanceHandle = UE::MovieScene::FInstanceHandle;
using FMovieSceneEntityID = UE::MovieScene::FMovieSceneEntityID;
using FAudioComponentEvaluationData = UE::MovieScene::FAudioComponentEvaluationData;
using FAudioComponentInputEvaluationData = UE::MovieScene::FAudioComponentInputEvaluationData;
UMovieSceneAudioSystem(const FObjectInitializer& ObjInit);
//~ UMovieSceneEntitySystem members
virtual void OnLink() override;
virtual void OnUnlink() override;
virtual void OnSchedulePersistentTasks(UE::MovieScene::IEntitySystemScheduler* TaskScheduler) override;
virtual void OnRun(FSystemTaskPrerequisites& InPrerequisites, FSystemSubsequentTasks& Subsequents) override;
/**
* Get the evaluation data for the given actor and section. Pass a null actor key for root (world) audio.
*/
FAudioComponentEvaluationData* GetAudioComponentEvaluationData(FInstanceHandle InstanceHandle, FObjectKey ActorKey, FObjectKey SectionKey);
/**
* Adds an audio component to the given bound sequencer object.
* WARNING: Only to be called on the game thread.
*/
FAudioComponentEvaluationData* AddBoundObjectAudioComponent(FInstanceHandle InstanceHandle, UMovieSceneAudioSection* Section, UObject* PrincipalObject);
/**
* Adds an audio component to the world, for playing root audio tracks.
* WARNING: Only to be called on the game thread.
*/
FAudioComponentEvaluationData* AddRootAudioComponent(FInstanceHandle InstanceHandle, UMovieSceneAudioSection* Section, UWorld* World);
/**
* Stop the audio on the audio component associated with the given audio section.
*/
void StopSound(FInstanceHandle InstanceHandle, FObjectKey ActorKey, FObjectKey SectionKey);
/**
* Reset shared accumulation data required every evaluation frame
*/
void ResetSharedData();
// To expose the class to GC //
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
private:
using FInstanceObjectKey = TTuple<FInstanceHandle, FObjectKey>;
/** Map of all created audio components */
using FAudioComponentBySectionKey = TMap<FInstanceObjectKey, FAudioComponentEvaluationData>;
using FAudioComponentsByActorKey = TMap<FObjectKey, FAudioComponentBySectionKey>;
FAudioComponentsByActorKey AudioComponentsByActorKey;
/** Map of audio input values, rebuilt every frame */
using FAudioInputsBySectionKey = TMap<FInstanceObjectKey, FAudioComponentInputEvaluationData>;
FAudioInputsBySectionKey AudioInputsBySectionKey;
/** Pre-animated state */
TSharedPtr<UE::MovieScene::FPreAnimatedAudioStorage> PreAnimatedStorage;
friend struct UE::MovieScene::FGatherAudioInputs;
friend struct UE::MovieScene::FGatherAudioTriggers;
friend struct UE::MovieScene::FEvaluateAudio;
};