2020-07-23 20:32:26 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "MetasoundSource.h"
|
|
|
|
|
|
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
#include "Internationalization/Text.h"
|
|
|
|
|
#include "AssetRegistryModule.h"
|
|
|
|
|
|
|
|
|
|
#include "MetasoundAssetBase.h"
|
2020-09-15 16:06:12 -04:00
|
|
|
#include "MetasoundBop.h"
|
2020-11-17 17:52:08 -04:00
|
|
|
#include "MetasoundEngineEnvironment.h"
|
2020-07-23 20:32:26 -04:00
|
|
|
#include "MetasoundGenerator.h"
|
|
|
|
|
#include "MetasoundAudioFormats.h"
|
|
|
|
|
#include "MetasoundPrimitives.h"
|
|
|
|
|
|
|
|
|
|
#include "MetasoundArchetypeRegistration.h"
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
|
#include "EdGraph/EdGraph.h"
|
|
|
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MetasoundSource"
|
|
|
|
|
|
|
|
|
|
static FName MetasoundSourceArchetypeName = FName(TEXT("Metasound Source"));
|
|
|
|
|
|
|
|
|
|
UMetasoundSource::UMetasoundSource(const FObjectInitializer& ObjectInitializer)
|
|
|
|
|
: Super(ObjectInitializer)
|
|
|
|
|
, FMetasoundAssetBase(RootMetasoundDocument)
|
|
|
|
|
{
|
|
|
|
|
// TODO:
|
|
|
|
|
NumChannels = 1;
|
|
|
|
|
Duration = INDEFINITELY_LOOPING_DURATION;
|
|
|
|
|
bLooping = true;
|
|
|
|
|
|
|
|
|
|
// todo: ensure that we have a method so that the audio engine can be authoritative over the sample rate the UMetasoundSource runs at.
|
|
|
|
|
SampleRate = 48000.0f;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMetasoundSource::SetMetadata(FMetasoundClassMetadata& InMetadata)
|
|
|
|
|
{
|
|
|
|
|
RootMetasoundDocument.RootClass.Metadata = InMetadata;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UMetasoundSource::IsPlayable() const
|
|
|
|
|
{
|
|
|
|
|
// todo: cache off whether this metasound is buildable to an operator.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UMetasoundSource::SupportsSubtitles() const
|
|
|
|
|
{
|
|
|
|
|
return Super::SupportsSubtitles();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float UMetasoundSource::GetDuration()
|
|
|
|
|
{
|
|
|
|
|
// eh? this is kind of a weird field anyways.
|
|
|
|
|
return Super::GetDuration();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ISoundGeneratorPtr UMetasoundSource::CreateSoundGenerator(const FSoundGeneratorInitParams& InParams)
|
|
|
|
|
{
|
2020-11-17 17:52:08 -04:00
|
|
|
using namespace Metasound;
|
|
|
|
|
|
2020-07-23 20:32:26 -04:00
|
|
|
NumChannels = 1;
|
|
|
|
|
Duration = INDEFINITELY_LOOPING_DURATION;
|
|
|
|
|
bLooping = true;
|
|
|
|
|
SampleRate = InParams.SampleRate;
|
2020-08-24 10:57:03 -04:00
|
|
|
const float BlockRate = 100.f; // Metasound graph gets evaluated 100 times per second.
|
2020-07-23 20:32:26 -04:00
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
FOperatorSettings InSettings(InParams.SampleRate, BlockRate);
|
|
|
|
|
FMetasoundEnvironment Environment;
|
2020-07-23 20:32:26 -04:00
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
// Add audio device ID to environment.
|
|
|
|
|
FAudioDeviceHandle DeviceHandle;
|
|
|
|
|
if (UWorld* World = GetWorld())
|
|
|
|
|
{
|
|
|
|
|
DeviceHandle = World->GetAudioDevice();
|
|
|
|
|
}
|
|
|
|
|
if (!DeviceHandle.IsValid())
|
|
|
|
|
{
|
|
|
|
|
if (FAudioDeviceManager* DeviceManager = FAudioDeviceManager::Get())
|
|
|
|
|
{
|
|
|
|
|
DeviceHandle = DeviceManager->GetMainAudioDeviceHandle();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Environment.SetValue<FAudioDeviceHandle>(GetAudioDeviceHandleVariableName(), DeviceHandle);
|
2020-07-23 20:32:26 -04:00
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
TArray<IOperatorBuilder::FBuildErrorPtr> BuildErrors;
|
|
|
|
|
|
|
|
|
|
Frontend::FGraphHandle RootGraph = GetRootGraphHandle();
|
2020-07-23 20:32:26 -04:00
|
|
|
ensureAlways(RootGraph.IsValid());
|
|
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
TUniquePtr<IOperator> Operator = RootGraph.BuildOperator(InSettings, Environment, BuildErrors);
|
2020-07-23 20:32:26 -04:00
|
|
|
if (ensureAlways(Operator.IsValid()))
|
|
|
|
|
{
|
2020-11-17 17:52:08 -04:00
|
|
|
FDataReferenceCollection Outputs = Operator->GetOutputs();
|
2020-07-23 20:32:26 -04:00
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
FMetasoundGeneratorInitParams InitParams =
|
2020-07-23 20:32:26 -04:00
|
|
|
{
|
|
|
|
|
MoveTemp(Operator),
|
2020-11-17 17:52:08 -04:00
|
|
|
Outputs.GetDataReadReferenceOrConstruct<FAudioBuffer>(GetAudioOutputName(), InSettings.GetNumFramesPerBlock()),
|
|
|
|
|
Outputs.GetDataReadReferenceOrConstruct<FBop>(GetIsFinishedOutputName(), InSettings, false)
|
2020-07-23 20:32:26 -04:00
|
|
|
};
|
|
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
return ISoundGeneratorPtr(new FMetasoundGenerator(MoveTemp(InitParams)));
|
2020-07-23 20:32:26 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return ISoundGeneratorPtr(nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMetasoundSource::PostLoad()
|
|
|
|
|
{
|
|
|
|
|
Super::PostLoad();
|
|
|
|
|
|
|
|
|
|
ConformDocumentToArchetype();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FString& UMetasoundSource::GetOnPlayInputName()
|
|
|
|
|
{
|
|
|
|
|
static FString BopInputName = FString(TEXT("On Play"));
|
|
|
|
|
return BopInputName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FString& UMetasoundSource::GetAudioOutputName()
|
|
|
|
|
{
|
|
|
|
|
static FString AudioOutputName = FString(TEXT("Generated Audio"));
|
|
|
|
|
return AudioOutputName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FString& UMetasoundSource::GetIsFinishedOutputName()
|
|
|
|
|
{
|
|
|
|
|
static FString OnFinishedOutputName = FString(TEXT("On Finished"));
|
|
|
|
|
return OnFinishedOutputName;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
const FString& UMetasoundSource::GetAudioDeviceHandleVariableName()
|
|
|
|
|
{
|
|
|
|
|
static FString AudioDeviceHandleVarName = FString(TEXT("AudioDeviceHandle"));
|
|
|
|
|
return AudioDeviceHandleVarName;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-23 20:32:26 -04:00
|
|
|
FMetasoundArchetype UMetasoundSource::GetArchetype() const
|
|
|
|
|
{
|
|
|
|
|
FMetasoundArchetype Archetype;
|
|
|
|
|
Archetype.ArchetypeName = MetasoundSourceArchetypeName;
|
|
|
|
|
|
|
|
|
|
FMetasoundInputDescription OnPlayBop;
|
|
|
|
|
OnPlayBop.Name = GetOnPlayInputName();
|
2020-07-30 16:57:04 -04:00
|
|
|
OnPlayBop.DisplayName = FText::FromString(OnPlayBop.Name);
|
2020-07-23 20:32:26 -04:00
|
|
|
OnPlayBop.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FBop>();
|
2020-07-30 16:57:04 -04:00
|
|
|
OnPlayBop.ToolTip = LOCTEXT("OnPlayBopToolTip", "Bop executed when this source is first played.");
|
2020-07-23 20:32:26 -04:00
|
|
|
|
|
|
|
|
Archetype.RequiredInputs.Add(OnPlayBop);
|
|
|
|
|
|
|
|
|
|
FMetasoundOutputDescription GeneratedAudio;
|
|
|
|
|
GeneratedAudio.Name = GetAudioOutputName();
|
2020-07-30 16:57:04 -04:00
|
|
|
GeneratedAudio.DisplayName = FText::FromString(GeneratedAudio.Name);
|
2020-07-23 20:32:26 -04:00
|
|
|
GeneratedAudio.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FAudioBuffer>();
|
2020-07-30 16:57:04 -04:00
|
|
|
GeneratedAudio.ToolTip = LOCTEXT("GeneratedAudioToolTip", "The resulting output audio from this source.");
|
2020-07-23 20:32:26 -04:00
|
|
|
Archetype.RequiredOutputs.Add(GeneratedAudio);
|
|
|
|
|
|
|
|
|
|
FMetasoundOutputDescription OnFinished;
|
|
|
|
|
OnFinished.Name = GetIsFinishedOutputName();
|
2020-07-30 16:57:04 -04:00
|
|
|
OnFinished.DisplayName = FText::FromString(OnFinished.Name);
|
2020-07-23 20:32:26 -04:00
|
|
|
OnFinished.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FBop>();
|
2020-07-30 16:57:04 -04:00
|
|
|
OnFinished.ToolTip = LOCTEXT("OnFinishedToolTip", "Bop executed to initiate stopping the source.");
|
2020-07-23 20:32:26 -04:00
|
|
|
Archetype.RequiredOutputs.Add(OnFinished);
|
|
|
|
|
|
2020-11-17 17:52:08 -04:00
|
|
|
FMetasoundEnvironmentVariableDescription AudioDeviceHandle;
|
|
|
|
|
AudioDeviceHandle.Name = GetAudioDeviceHandleVariableName();
|
|
|
|
|
AudioDeviceHandle.DisplayName = FText::FromString(AudioDeviceHandle.Name);
|
|
|
|
|
AudioDeviceHandle.ToolTip = LOCTEXT("AudioDeviceHandleToolTip", "Audio device handle");
|
|
|
|
|
Archetype.EnvironmentVariables.Add(AudioDeviceHandle);
|
|
|
|
|
|
2020-07-23 20:32:26 -04:00
|
|
|
return Archetype;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|