Files
UnrealEngine/Engine/Plugins/Experimental/MetasoundExperimental/Source/MetasoundExperimentalRuntime/Private/MetasoundCatCastingNode.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

210 lines
7.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MetasoundCatCastingNode.h"
#include "MetasoundChannelAgnosticType.h"
#include "MetasoundExecutableOperator.h"
#include "MetasoundFacade.h"
#include "MetasoundNodeRegistrationMacro.h"
#include "MetasoundVertex.h"
#include "TypeFamily/ChannelTypeFamily.h"
#define LOCTEXT_NAMESPACE "MetasoundStandardNodes_CatCastingNode"
namespace Metasound
{
class FChannelAgnosticType;
struct FBuildOperatorParams;
class FNodeFacade;
namespace CatCastingPrivate
{
METASOUND_PARAM(InputFromCat, "Input", "CAT to Cast");
METASOUND_PARAM(OutputToCat, "Output", "CAT Result");
class FCatCastingOperatorData final : public TOperatorData<FCatCastingOperatorData>
{
public:
// The OperatorDataTypeName is used when downcasting an IOperatorData to ensure
// that the downcast is valid.
static const FLazyName OperatorDataTypeName;
explicit FCatCastingOperatorData(const FName& InToTypeName, Audio::EChannelTranscodeMethod InTranscodeMethod, Audio::EChannelMapMonoUpmixMethod InMixMethod)
: ToTypeName(InToTypeName)
, TranscodeMethod(InTranscodeMethod)
, MixMethod(InMixMethod)
{}
const FName& GetToType() const
{
return ToTypeName;
}
Audio::EChannelMapMonoUpmixMethod GetMixMethod() const { return MixMethod; }
Audio::EChannelTranscodeMethod GetTranscodeMethod() const { return TranscodeMethod; }
private:
FName ToTypeName;
Audio::EChannelTranscodeMethod TranscodeMethod;
Audio::EChannelMapMonoUpmixMethod MixMethod;
};
// Linkage.
const FLazyName FCatCastingOperatorData::OperatorDataTypeName = TEXT("FCatCastingOperatorData");
}
class FCatCastingOperator final : public TExecutableOperator<FCatCastingOperator>
{
public:
FCatCastingOperator(const FBuildOperatorParams& InParams, FChannelAgnosticTypeReadRef&& InInputCat, const CatCastingPrivate::FCatCastingOperatorData& InData, const FName InConcreteName)
: InputFrom(MoveTemp(InInputCat))
, ToFormatName(InConcreteName)
, OutputCastResult(FChannelAgnosticTypeWriteRef::CreateNew(InParams.OperatorSettings, InConcreteName))
, Settings(InParams.OperatorSettings)
, TranscodeMethod(InData.GetTranscodeMethod())
, MixMethod(InData.GetMixMethod())
{}
virtual ~FCatCastingOperator() override = default;
static const FVertexInterface& GetDefaultInterface()
{
using namespace CatCastingPrivate;
auto CreateDefaultInterface = []()-> FVertexInterface
{
// inputs
FInputVertexInterface InputInterface;
InputInterface.Add(TInputDataVertex<FChannelAgnosticType>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputFromCat)));
// outputs
FOutputVertexInterface OutputInterface;
OutputInterface.Add(TOutputDataVertex<FChannelAgnosticType>(METASOUND_GET_PARAM_NAME_AND_METADATA(OutputToCat)));
return FVertexInterface(InputInterface, OutputInterface);
}; // end lambda: CreateDefaultInterface()
static const FVertexInterface DefaultInterface = CreateDefaultInterface();
return DefaultInterface;
}
static TUniquePtr<IOperator> CreateOperator(const FBuildOperatorParams& InParams, FBuildResults& OutResults)
{
using namespace CatCastingPrivate;
const FCatCastingOperatorData* CatTestingConfigData = CastOperatorData<const FCatCastingOperatorData>(InParams.Node.GetOperatorData().Get());
if (!CatTestingConfigData)
{
return MakeUnique<FNoOpOperator>();
}
const FName CastToName = CatTestingConfigData->GetToType();
const FInputVertexInterfaceData& InputData = InParams.InputData;
const Audio::FChannelTypeFamily* ConcreteToType = Audio::GetChannelRegistry().FindConcreteChannel(CastToName);
TDataReadReference<FChannelAgnosticType> InputCat = InputData.GetOrCreateDefaultDataReadReference<FChannelAgnosticType>(
METASOUND_GET_PARAM_NAME(InputFromCat), InParams.OperatorSettings);
// Make sure the cast is to something sane, otherwise use the inputs type...
const FName CastToNameSane = ConcreteToType ? ConcreteToType->GetName() : InputCat->GetTypeName();
return MakeUnique<FCatCastingOperator>(
InParams,
MoveTemp(InputCat),
*CatTestingConfigData,
CastToNameSane
);
}
virtual void BindInputs(FInputVertexInterfaceData& InOutVertexData) override
{
using namespace CatCastingPrivate;
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputFromCat) , InputFrom);
}
virtual void BindOutputs(FOutputVertexInterfaceData& InOutVertexData) override
{
using namespace CatCastingPrivate;
InOutVertexData.BindWriteVertex(METASOUND_GET_PARAM_NAME(OutputToCat),OutputCastResult);
// Create transcoder
Transcoder = InputFrom->GetType().GetTranscoder(
{
.ToType = OutputCastResult->GetType(),
.TranscodeMethod = TranscodeMethod,
.MixMethod = MixMethod,
}
);
}
void Reset(const FResetParams& InParams)
{
Execute();
}
void Execute()
{
if (Transcoder)
{
using namespace CatCastingPrivate;
using namespace Audio;
TStackArrayOfPointers<const float> Src = MakeMultiMonoPointersFromView(InputFrom->GetRawMultiMono(), Settings.GetNumFramesPerBlock(), InputFrom->NumChannels());
TStackArrayOfPointers<float> Dst = MakeMultiMonoPointersFromView(OutputCastResult->GetRawMultiMono(), Settings.GetNumFramesPerBlock(), OutputCastResult->NumChannels());
Transcoder(Src, Dst, Settings.GetNumFramesPerBlock());
}
}
static FNodeClassMetadata GetNodeInfo()
{
using namespace CatCastingPrivate;
return FNodeClassMetadata
{
FNodeClassName{ "Experimental", "CatCastingOperator", "" },
1, // Major version
0, // Minor version
METASOUND_LOCTEXT("CatCastingNodeName", "CAT Casting Node"),
METASOUND_LOCTEXT("CatCastingNodeNameDescription", "A Node that allows Casting to CATs"),
TEXT("UE"), // Author
METASOUND_LOCTEXT("ExampleConfigurablePromptIfMissing", "Enable the MetaSoundExperimental Plugin"), // Prompt if missing
GetDefaultInterface(),
{}
};
}
private:
using FTranscoder = Audio::FChannelTypeFamily::FTranscoder;
FChannelAgnosticTypeReadRef InputFrom;
FName ToFormatName;
FChannelAgnosticTypeWriteRef OutputCastResult;
FOperatorSettings Settings;
FTranscoder Transcoder;
Audio::EChannelTranscodeMethod TranscodeMethod;
Audio::EChannelMapMonoUpmixMethod MixMethod;
}; // class FCatCastingOperator
using FCatCastingNode = TNodeFacade<FCatCastingOperator>;
// register node config.
METASOUND_REGISTER_NODE_AND_CONFIGURATION(FCatCastingNode, FMetaSoundCatCastingNodeConfiguration);
} // namespace Metasound
TArray<FPropertyTextFName> UMetasoundCatCastingOptionsHelper::GetCastingOptions()
{
const TArray<const Audio::FChannelTypeFamily*> AllFormats = Audio::GetChannelRegistry().GetAllChannelFormats();
TArray<FPropertyTextFName> FormatsOptions;
Algo::Transform(AllFormats, FormatsOptions, [](const Audio::FChannelTypeFamily* i) -> FPropertyTextFName
{ return {.ValueString = i->GetName(), .DisplayName = FText::FromString(i->GetFriendlyName()) }; });
return FormatsOptions;
}
TInstancedStruct<FMetasoundFrontendClassInterface> FMetaSoundCatCastingNodeConfiguration::OverrideDefaultInterface(
const FMetasoundFrontendClass& InNodeClass) const
{
return TInstancedStruct<FMetasoundFrontendClassInterface>::Make(FMetasoundFrontendClassInterface::GenerateClassInterface(Metasound::FCatCastingOperator::GetDefaultInterface()));
}
TSharedPtr<const Metasound::IOperatorData> FMetaSoundCatCastingNodeConfiguration::GetOperatorData() const
{
return MakeShared<Metasound::CatCastingPrivate::FCatCastingOperatorData>(
ToType,
static_cast<Audio::EChannelTranscodeMethod>(TranscodeMethod),
static_cast<Audio::EChannelMapMonoUpmixMethod>(MixMethod)
);
}
#undef LOCTEXT_NAMESPACE //