Files
UnrealEngine/Engine/Plugins/Runtime/Metasound/Source/MetasoundEngine/Private/Interfaces/MetasoundInterface.cpp
2025-05-18 13:04:45 +08:00

161 lines
5.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Interfaces/MetasoundInterface.h"
#include "Algo/Transform.h"
#include "AudioParameterControllerInterface.h"
#include "IAudioParameterInterfaceRegistry.h"
#include "IAudioParameterTransmitter.h"
#include "Interfaces/MetasoundFrontendInterfaceRegistry.h"
#include "Interfaces/MetasoundFrontendSourceInterface.h"
#include "Interfaces/MetasoundInputFormatInterfaces.h"
#include "Interfaces/MetasoundOutputFormatInterfaces.h"
#include "Metasound.h"
#include "MetasoundFrontendDataTypeRegistry.h"
#include "MetasoundFrontendDocument.h"
#include "MetasoundFrontendTransform.h"
#include "MetasoundLog.h"
#include "MetasoundParameterTransmitter.h"
#include "MetasoundSource.h"
#include "MetasoundUObjectRegistry.h"
#include "Templates/SharedPointer.h"
#include "Templates/UniquePtr.h"
#include "UObject/Class.h"
#include "UObject/NoExportTypes.h"
namespace Metasound::Engine
{
FInterfaceRegistryEntry::FInterfaceRegistryEntry(FMetasoundFrontendInterface&& InInterface, FName InRouterName, bool bInIsDeprecated)
: Interface(MoveTemp(InInterface))
, RouterName(InRouterName)
, bIsDeprecated(bInIsDeprecated)
{
}
FInterfaceRegistryEntry::FInterfaceRegistryEntry(const FMetasoundFrontendInterface& InInterface, FName InRouterName, bool bInIsDeprecated)
: Interface(InInterface)
, RouterName(InRouterName)
, bIsDeprecated(bInIsDeprecated)
{
}
FInterfaceRegistryEntry::FInterfaceRegistryEntry(const FMetasoundFrontendInterface& InInterface, TUniquePtr<Frontend::IDocumentTransform>&& InUpdateTransform, FName InRouterName, bool bInIsDeprecated)
: Interface(InInterface)
, UpdateTransform(MoveTemp(InUpdateTransform))
, RouterName(InRouterName)
, bIsDeprecated(bInIsDeprecated)
{
}
FName FInterfaceRegistryEntry::GetRouterName() const
{
return RouterName;
}
const FMetasoundFrontendInterface& FInterfaceRegistryEntry::GetInterface() const
{
return Interface;
}
bool FInterfaceRegistryEntry::IsDeprecated() const
{
return bIsDeprecated;
}
bool FInterfaceRegistryEntry::UpdateRootGraphInterface(Frontend::FDocumentHandle InDocument) const
{
if (UpdateTransform.IsValid())
{
return UpdateTransform->Transform(InDocument);
}
return false;
}
bool FInterfaceRegistryEntry::UpdateRootGraphInterface(FMetaSoundFrontendDocumentBuilder& InDocumentBuilder) const
{
if (UpdateTransform.IsValid())
{
return UpdateRootGraphInterface(InDocumentBuilder.GetMetasoundAsset().GetDocumentHandle());
}
return InDocumentBuilder.AddInterface(GetInterface().Metadata.Version.Name);
}
void RegisterAudioFormatInterfaces()
{
using namespace Frontend;
IInterfaceRegistry& Reg = IInterfaceRegistry::Get();
// Input Formats
{
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(InputFormatMonoInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(InputFormatStereoInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(InputFormatQuadInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(InputFormatFiveDotOneInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(InputFormatSevenDotOneInterface::CreateInterface()));
}
// Output Formats
{
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(OutputFormatMonoInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(OutputFormatStereoInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(OutputFormatQuadInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(OutputFormatFiveDotOneInterface::CreateInterface()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(OutputFormatSevenDotOneInterface::CreateInterface()));
}
}
void RegisterExternalInterfaces()
{
// Register External Interfaces (Interfaces defined externally & can be managed directly by end-user).
auto RegisterExternalInterface = [](Audio::FParameterInterfacePtr Interface)
{
using namespace Frontend;
bool bSupportedInterface = false;
IMetasoundUObjectRegistry::Get().IterateRegisteredUClasses([&bSupportedInterface, &Interface](UClass& InRegisteredClass)
{
const TArray<const UClass*> SupportedUClasses = Interface->FindSupportedUClasses();
bSupportedInterface |= SupportedUClasses.IsEmpty();
for (const UClass* SupportedUClass : SupportedUClasses)
{
check(SupportedUClass);
bSupportedInterface |= SupportedUClass->IsChildOf(&InRegisteredClass);
}
});
if (bSupportedInterface)
{
IInterfaceRegistry::Get().RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(FMetasoundFrontendInterface(Interface), Audio::IParameterTransmitter::RouterName));
}
else
{
UE_LOG(LogMetaSound, Warning, TEXT("Parameter interface '%s' not supported by MetaSounds"), *Interface->GetName().ToString());
}
};
Audio::IAudioParameterInterfaceRegistry::Get().IterateInterfaces(RegisterExternalInterface);
Audio::IAudioParameterInterfaceRegistry::Get().OnRegistration(MoveTemp(RegisterExternalInterface));
}
void RegisterInterfaces()
{
using namespace Frontend;
IInterfaceRegistry& Reg = IInterfaceRegistry::Get();
// Default Source Interfaces
{
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(SourceInterface::CreateInterface(*UMetaSoundSource::StaticClass()), MakeUnique<SourceInterface::FUpdateInterface>()));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(SourceOneShotInterface::CreateInterface(*UMetaSoundSource::StaticClass())));
Reg.RegisterInterface(MakeUnique<FInterfaceRegistryEntry>(SourceStartTimeInterface::CreateInterface(*UMetaSoundSource::StaticClass())));
}
RegisterAudioFormatInterfaces();
RegisterExternalInterfaces();
}
} // namespace Metasound::Engine