2020-07-23 20:32:26 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundSource.h"
2020-12-14 15:48:27 -04:00
# include "AssetRegistryModule.h"
2020-07-23 20:32:26 -04:00
# include "CoreMinimal.h"
# include "Internationalization/Text.h"
# include "MetasoundAssetBase.h"
2020-12-14 15:48:27 -04:00
# include "MetasoundAudioFormats.h"
2020-11-17 17:52:08 -04:00
# include "MetasoundEngineEnvironment.h"
2021-01-22 03:05:22 -04:00
# include "MetasoundFrontendController.h"
# include "MetasoundFrontendQuery.h"
# include "MetasoundFrontendQuerySteps.h"
2020-07-23 20:32:26 -04:00
# include "MetasoundGenerator.h"
2021-01-22 03:05:22 -04:00
# include "MetasoundInstanceTransmitter.h"
2020-12-14 15:48:27 -04:00
# include "MetasoundLog.h"
2021-02-16 01:26:50 -04:00
# include "MetasoundOperatorSettings.h"
2020-07-23 20:32:26 -04:00
# include "MetasoundPrimitives.h"
2021-01-22 03:05:22 -04:00
# include "MetasoundReceiveNode.h"
2021-01-27 15:54:01 -04:00
# include "MetasoundTrigger.h"
2020-07-23 20:32:26 -04:00
# 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 )
2020-12-14 15:48:27 -04:00
, FMetasoundAssetBase ( GetMonoSourceArchetype ( ) )
2020-07-23 20:32:26 -04:00
{
2021-01-11 14:18:46 -04:00
bRequiresStopFade = true ;
2020-07-23 20:32:26 -04:00
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.
2021-02-16 01:26:50 -04:00
SampleRate = 48000.f ;
2020-07-23 20:32:26 -04:00
}
2020-12-14 15:48:27 -04:00
# if WITH_EDITOR
void UMetasoundSource : : PostEditChangeProperty ( FPropertyChangedEvent & InEvent )
{
Super : : PostEditChangeProperty ( InEvent ) ;
if ( InEvent . GetPropertyName ( ) = = GET_MEMBER_NAME_CHECKED ( UMetasoundSource , OutputFormat ) )
{
switch ( OutputFormat )
{
case EMetasoundSourceAudioFormat : : Stereo :
NumChannels = 2 ;
2021-01-22 03:05:22 -04:00
ensure ( SetMetasoundArchetype ( GetStereoSourceArchetype ( ) ) ) ;
2020-12-14 15:48:27 -04:00
break ;
case EMetasoundSourceAudioFormat : : Mono :
default :
NumChannels = 1 ;
2021-01-22 03:05:22 -04:00
ensure ( SetMetasoundArchetype ( GetMonoSourceArchetype ( ) ) ) ;
2020-12-14 15:48:27 -04:00
break ;
}
}
}
# endif
2020-07-23 20:32:26 -04:00
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
Duration = INDEFINITELY_LOOPING_DURATION ;
bLooping = true ;
2021-01-11 14:18:46 -04:00
VirtualizationMode = EVirtualizationMode : : PlayWhenSilent ;
2020-07-23 20:32:26 -04:00
SampleRate = InParams . SampleRate ;
2021-02-16 01:26:50 -04:00
FOperatorSettings InSettings = GetOperatorSettings ( static_cast < FSampleRate > ( SampleRate ) ) ;
2020-11-17 17:52:08 -04:00
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
2021-01-22 03:05:22 -04:00
const FMetasoundFrontendDocument * OriginalDoc = GetDocument ( ) . Get ( ) ;
if ( nullptr = = OriginalDoc )
{
UE_LOG ( LogMetasound , Error , TEXT ( " Cannot create sound generator. Null Metasound document in UMetasoundSource [Name:%s] " ) , * GetName ( ) ) ;
return ISoundGeneratorPtr ( nullptr ) ;
}
// Inject receive nodes for unused transmittable inputs. Perform edits on a copy
// of the document to avoid altering document.
// TODO: Use a light wrapper of the document instead of a copy.
FMetasoundFrontendDocument DocumentWithInjectedReceives ;
ensure ( CopyDocumentAndInjectReceiveNodes ( InParams . InstanceID , * OriginalDoc , DocumentWithInjectedReceives ) ) ;
// Create handles for new root graph
Frontend : : FConstDocumentHandle NewDocumentHandle = Frontend : : IDocumentController : : CreateDocumentHandle ( Frontend : : MakeAccessPtr < const FMetasoundFrontendDocument > ( DocumentWithInjectedReceives . AccessPoint , DocumentWithInjectedReceives ) ) ;
Frontend : : FConstGraphHandle RootGraph = NewDocumentHandle - > GetRootGraph ( ) ;
2020-11-17 17:52:08 -04:00
2021-01-13 10:48:59 -04:00
ensureAlways ( RootGraph - > IsValid ( ) ) ;
2020-07-23 20:32:26 -04:00
2021-01-22 03:05:22 -04:00
// Create the operator from the graph handle.
TArray < IOperatorBuilder : : FBuildErrorPtr > BuildErrors ;
2021-01-13 10:48:59 -04:00
TUniquePtr < IOperator > Operator = RootGraph - > BuildOperator ( InSettings , Environment , BuildErrors ) ;
2020-12-14 15:48:27 -04:00
2021-02-10 21:43:31 -04:00
// Log build errors
for ( const IOperatorBuilder : : FBuildErrorPtr & Error : BuildErrors )
{
if ( Error . IsValid ( ) )
{
UE_LOG ( LogMetasound , Warning , TEXT ( " MetasoundSource [%s] build error [%s] \" %s \" " ) , * GetName ( ) , * ( Error - > GetErrorType ( ) . ToString ( ) ) , * ( Error - > GetErrorDescription ( ) . ToString ( ) ) ) ;
}
}
2020-12-14 15:48:27 -04:00
if ( ! Operator . IsValid ( ) )
{
UE_LOG ( LogMetasound , Error , TEXT ( " Failed to build Metasound operator from graph in MetasoundSource [%s] " ) , * GetName ( ) ) ;
}
else
2020-07-23 20:32:26 -04:00
{
2020-11-17 17:52:08 -04:00
FDataReferenceCollection Outputs = Operator - > GetOutputs ( ) ;
2020-12-14 15:48:27 -04:00
TArrayView < FAudioBufferReadRef > OutputBuffers ;
2020-07-23 20:32:26 -04:00
2020-12-14 15:48:27 -04:00
// Get output audio buffers.
if ( EMetasoundSourceAudioFormat : : Stereo = = OutputFormat )
{
if ( ! Outputs . ContainsDataReadReference < FStereoAudioFormat > ( GetAudioOutputName ( ) ) )
{
UE_LOG ( LogMetasound , Warning , TEXT ( " MetasoundSource [%s] does not contain stereo output [%s] in output " ) , * GetName ( ) , * GetAudioOutputName ( ) ) ;
}
OutputBuffers = Outputs . GetDataReadReferenceOrConstruct < FStereoAudioFormat > ( GetAudioOutputName ( ) , InSettings ) - > GetBuffers ( ) ;
}
else if ( EMetasoundSourceAudioFormat : : Mono = = OutputFormat )
{
2021-01-11 14:18:46 -04:00
if ( ! Outputs . ContainsDataReadReference < FMonoAudioFormat > ( GetAudioOutputName ( ) ) )
2020-12-14 15:48:27 -04:00
{
UE_LOG ( LogMetasound , Warning , TEXT ( " MetasoundSource [%s] does not contain mono output [%s] in output " ) , * GetName ( ) , * GetAudioOutputName ( ) ) ;
}
OutputBuffers = Outputs . GetDataReadReferenceOrConstruct < FMonoAudioFormat > ( GetAudioOutputName ( ) , InSettings ) - > GetBuffers ( ) ;
}
2021-01-11 14:18:46 -04:00
// References must be cached before moving the operator to the InitParams
FDataReferenceCollection Inputs = Operator - > GetInputs ( ) ;
2021-01-27 15:54:01 -04:00
FTriggerWriteRef PlayTrigger = Inputs . GetDataWriteReferenceOrConstruct < FTrigger > ( GetOnPlayInputName ( ) , InSettings , false ) ;
FTriggerReadRef FinishTrigger = Outputs . GetDataReadReferenceOrConstruct < FTrigger > ( GetIsFinishedOutputName ( ) , InSettings , false ) ;
2021-01-11 14:18:46 -04:00
2020-12-14 15:48:27 -04:00
// Create the FMetasoundGenerator.
2020-11-17 17:52:08 -04:00
FMetasoundGeneratorInitParams InitParams =
2020-07-23 20:32:26 -04:00
{
MoveTemp ( Operator ) ,
2020-12-14 15:48:27 -04:00
OutputBuffers ,
2021-01-11 14:18:46 -04:00
MoveTemp ( PlayTrigger ) ,
MoveTemp ( FinishTrigger )
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
}
2020-12-14 15:48:27 -04:00
return ISoundGeneratorPtr ( nullptr ) ;
2020-07-23 20:32:26 -04:00
}
2021-01-22 03:05:22 -04:00
TUniquePtr < IAudioInstanceTransmitter > UMetasoundSource : : CreateInstanceTransmitter ( const FAudioInstanceTransmitterInitParams & InParams ) const
{
Metasound : : FMetasoundInstanceTransmitter : : FInitParams InitParams ( GetOperatorSettings ( InParams . SampleRate ) , InParams . InstanceID ) ;
for ( const FSendInfoAndVertexName & InfoAndName : GetSendInfos ( InParams . InstanceID ) )
{
InitParams . Infos . Add ( InfoAndName . SendInfo ) ;
}
return MakeUnique < Metasound : : FMetasoundInstanceTransmitter > ( InitParams ) ;
}
bool UMetasoundSource : : GetReceiveNodeMetadataForDataType ( const FName & InTypeName , FMetasoundFrontendClassMetadata & OutMetadata ) const
{
using namespace Metasound ;
FFrontendQuery Query ;
Query . AddStep < FGenerateAllAvailableNodeClasses > ( )
. AddStep < FFilterClassesByClassName > ( FReceiveNodeNames : : GetClassNameForDataType ( InTypeName ) ) ;
FFrontendQuerySelectionView Result = Query . ExecuteQuery ( ) ;
TArrayView < const FFrontendQueryEntry * const > Selection = Result . GetSelection ( ) ;
if ( Selection . Num ( ) > 0 )
{
check ( Selection [ 0 ] - > Value . IsType < FMetasoundFrontendClass > ( ) ) ;
OutMetadata = Selection [ 0 ] - > Value . Get < FMetasoundFrontendClass > ( ) . Metadata ;
return true ;
}
return false ;
}
Metasound : : Frontend : : FNodeHandle UMetasoundSource : : AddInputPinForSendAddress ( const Metasound : : FMetasoundInstanceTransmitter : : FSendInfo & InSendInfo , Metasound : : Frontend : : FGraphHandle InGraph ) const
{
FMetasoundFrontendClassInput Description ;
FGuid PointID = InGraph - > GetNewPointID ( ) ;
Description . Name = InSendInfo . Address . ChannelName . ToString ( ) ;
Description . TypeName = Metasound : : GetMetasoundDataTypeName < Metasound : : FSendAddress > ( ) ;
Description . Metadata . Description = FText : : GetEmpty ( ) ;
Description . PointIDs . Add ( PointID ) ;
FMetasoundFrontendVertexLiteral DefaultValue ;
DefaultValue . PointID = PointID ;
DefaultValue . Value . Set ( InSendInfo . Address . ChannelName . ToString ( ) ) ;
Description . Defaults . Add ( DefaultValue ) ;
return InGraph - > AddInputVertex ( Description ) ;
}
bool UMetasoundSource : : CopyDocumentAndInjectReceiveNodes ( uint64 InInstanceID , const FMetasoundFrontendDocument & InSourceDoc , FMetasoundFrontendDocument & OutDestDoc ) const
{
using namespace Metasound ;
OutDestDoc = InSourceDoc ;
Frontend : : FDocumentHandle Document = Frontend : : IDocumentController : : CreateDocumentHandle ( Frontend : : MakeAccessPtr ( OutDestDoc . AccessPoint , OutDestDoc ) ) ;
Frontend : : FGraphHandle RootGraph = Document - > GetRootGraph ( ) ;
TArray < FSendInfoAndVertexName > SendInfoAndVertexes = GetSendInfos ( InInstanceID ) ;
// Inject receive nodes for each transmittable input
for ( const FSendInfoAndVertexName & InfoAndVertexName : SendInfoAndVertexes )
{
// Add receive node to graph
FMetasoundFrontendClassMetadata ReceiveNodeMetadata ;
bool bSuccess = GetReceiveNodeMetadataForDataType ( InfoAndVertexName . SendInfo . TypeName , ReceiveNodeMetadata ) ;
if ( ! bSuccess )
{
// TODO: log warning
continue ;
}
Frontend : : FNodeHandle ReceiveNode = RootGraph - > AddNode ( ReceiveNodeMetadata ) ;
// Add receive node address to graph
Frontend : : FNodeHandle AddressNode = UMetasoundSource : : AddInputPinForSendAddress ( InfoAndVertexName . SendInfo , RootGraph ) ;
TArray < Frontend : : FOutputHandle > AddressNodeOutputs = AddressNode - > GetOutputs ( ) ;
if ( AddressNodeOutputs . Num ( ) ! = 1 )
{
// TODO: log warning
continue ;
}
Frontend : : FOutputHandle AddressOutput = AddressNodeOutputs [ 0 ] ;
TArray < Frontend : : FInputHandle > ReceiveAddressInput = ReceiveNode - > GetInputsWithVertexName ( Metasound : : FReceiveNodeNames : : GetAddressInputName ( ) ) ;
if ( ReceiveAddressInput . Num ( ) ! = 1 )
{
// TODO: log error
continue ;
}
ensure ( ReceiveAddressInput [ 0 ] - > Connect ( * AddressOutput ) ) ;
// Swap input node connections with receive node connections
Frontend : : FNodeHandle InputNode = RootGraph - > GetInputNodeWithName ( InfoAndVertexName . VertexName ) ;
if ( ! ensure ( InputNode - > GetOutputs ( ) . Num ( ) = = 1 ) )
{
// TODO: handle input node with varying number of outputs or varying output types.
continue ;
}
Frontend : : FOutputHandle InputNodeOutput = InputNode - > GetOutputs ( ) [ 0 ] ;
if ( ensure ( ReceiveNode - > IsValid ( ) ) )
{
TArray < Frontend : : FOutputHandle > ReceiveNodeOutputs = ReceiveNode - > GetOutputs ( ) ;
if ( ! ensure ( ReceiveNodeOutputs . Num ( ) = = 1 ) )
{
// TODO: handle array outputs and receive nodes of varying formats.
continue ;
}
TArray < Frontend : : FInputHandle > ReceiveDefaultInputs = ReceiveNode - > GetInputsWithVertexName ( Metasound : : FReceiveNodeNames : : GetDefaultDataInputName ( ) ) ;
if ( ensure ( ReceiveDefaultInputs . Num ( ) = = 1 ) )
{
Frontend : : FOutputHandle ReceiverNodeOutput = ReceiveNodeOutputs [ 0 ] ;
for ( Frontend : : FInputHandle NodeInput : InputNodeOutput - > GetCurrentlyConnectedInputs ( ) )
{
// Swap connections to receiver node
ensure ( InputNodeOutput - > Disconnect ( * NodeInput ) ) ;
ensure ( ReceiverNodeOutput - > Connect ( * NodeInput ) ) ;
}
ReceiveDefaultInputs [ 0 ] - > Connect ( * InputNodeOutput ) ;
}
}
}
return true ;
}
TArray < FString > UMetasoundSource : : GetTransmittableInputVertexNames ( ) const
{
using namespace Metasound ;
// Unused inputs are all input vertices that are not in the archetype.
TArray < FString > ArchetypeInputVertexNames ;
for ( const FMetasoundFrontendClassVertex & Vertex : GetMetasoundArchetype ( ) . Interface . Inputs )
{
ArchetypeInputVertexNames . Add ( Vertex . Name ) ;
}
Frontend : : FConstGraphHandle RootGraph = GetRootGraphHandle ( ) ;
TArray < FString > GraphInputVertexNames = RootGraph - > GetInputVertexNames ( ) ;
// Filter graph inputs by archetype inputs.
GraphInputVertexNames = GraphInputVertexNames . FilterByPredicate ( [ & ] ( const FString & InName ) { return ! ArchetypeInputVertexNames . Contains ( InName ) ; } ) ;
auto IsDataTypeTransmittable = [ & ] ( const FString & InVertexName )
{
Frontend : : FConstClassInputAccessPtr ClassInputPtr = RootGraph - > FindClassInputWithName ( InVertexName ) ;
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
FDataTypeRegistryInfo TypeInfo ;
if ( Frontend : : GetTraitsForDataType ( ClassInput - > TypeName , TypeInfo ) )
{
return TypeInfo . bIsTransmittable ;
}
}
return false ;
} ;
GraphInputVertexNames = GraphInputVertexNames . FilterByPredicate ( IsDataTypeTransmittable ) ;
return GraphInputVertexNames ;
}
2021-02-16 01:26:50 -04:00
Metasound : : FOperatorSettings UMetasoundSource : : GetOperatorSettings ( Metasound : : FSampleRate InSampleRate ) const
2021-01-22 03:05:22 -04:00
{
constexpr float BlockRate = 100.f ; // Metasound graph gets evaluated 100 times per second.
return Metasound : : FOperatorSettings ( InSampleRate , BlockRate ) ;
}
2021-02-19 14:00:43 -04:00
Metasound : : FSendAddress UMetasoundSource : : CreateSendAddress ( uint64 InInstanceID , const FString & InVertexName , const FName & InDataTypeName ) const
2021-01-22 03:05:22 -04:00
{
using namespace Metasound ;
FSendAddress Address ;
Address . Subsystem = GetSubsystemNameForSendScope ( ETransmissionScope : : Global ) ;
2021-02-19 14:00:43 -04:00
Address . ChannelName = FName ( FString : : Printf ( TEXT ( " %d:%s:%s " ) , InInstanceID , * InVertexName , * InDataTypeName . ToString ( ) ) ) ;
2021-01-22 03:05:22 -04:00
return Address ;
}
TArray < UMetasoundSource : : FSendInfoAndVertexName > UMetasoundSource : : GetSendInfos ( uint64 InInstanceID ) const
{
using FSendInfo = Metasound : : FMetasoundInstanceTransmitter : : FSendInfo ;
using namespace Metasound : : Frontend ;
TArray < FSendInfoAndVertexName > SendInfos ;
FConstGraphHandle RootGraph = GetRootGraphHandle ( ) ;
TArray < FString > SendVertices = GetTransmittableInputVertexNames ( ) ;
for ( const FString & VertexName : SendVertices )
{
FConstNodeHandle InputNode = RootGraph - > GetInputNodeWithName ( VertexName ) ;
2021-02-19 14:00:43 -04:00
// TODO: re-expose InputNode Inputs. Currently they are hidden since they cannot be
// connected. But instead, they should be accessible through this API, but fail
// to connect. As a quick fix, the output handles are used, but this is not
// sustainable for situations where the input node is specialized.
2021-01-22 03:05:22 -04:00
for ( FConstOutputHandle InputHandle : InputNode - > GetConstOutputs ( ) )
{
FSendInfoAndVertexName Info ;
// TODO: incorporate PointID into address. But need to ensure that PointID
// will be maintained after injecting Receive nodes.
2021-02-19 14:00:43 -04:00
Info . SendInfo . Address = CreateSendAddress ( InInstanceID , InputHandle - > GetName ( ) , InputHandle - > GetDataType ( ) ) ;
2021-01-22 03:05:22 -04:00
Info . SendInfo . ParameterName = FName ( InputHandle - > GetDisplayName ( ) . ToString ( ) ) ; // TODO: display name hack. Need to have nameing consistent in editor for inputs
Info . SendInfo . TypeName = InputHandle - > GetDataType ( ) ;
Info . VertexName = VertexName ;
SendInfos . Add ( Info ) ;
}
}
return SendInfos ;
}
const TArray < FMetasoundFrontendArchetype > & UMetasoundSource : : GetPreferredMetasoundArchetypes ( ) const
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
static const TArray < FMetasoundFrontendArchetype > Preferred ( { GetMonoSourceArchetype ( ) , GetStereoSourceArchetype ( ) } ) ;
2020-12-14 15:48:27 -04:00
return Preferred ;
}
2020-07-23 20:32:26 -04:00
const FString & UMetasoundSource : : GetOnPlayInputName ( )
{
2021-01-11 14:18:46 -04:00
static const FString TriggerInputName = TEXT ( " On Play " ) ;
return TriggerInputName ;
2020-07-23 20:32:26 -04:00
}
const FString & UMetasoundSource : : GetAudioOutputName ( )
{
2021-01-11 14:18:46 -04:00
static const FString AudioOutputName = TEXT ( " Generated Audio " ) ;
2020-07-23 20:32:26 -04:00
return AudioOutputName ;
}
const FString & UMetasoundSource : : GetIsFinishedOutputName ( )
{
2021-01-11 14:18:46 -04:00
static const FString OnFinishedOutputName = TEXT ( " On Finished " ) ;
2020-07-23 20:32:26 -04:00
return OnFinishedOutputName ;
}
2020-11-17 17:52:08 -04:00
const FString & UMetasoundSource : : GetAudioDeviceHandleVariableName ( )
{
2021-01-11 14:18:46 -04:00
static const FString AudioDeviceHandleVarName = TEXT ( " AudioDeviceHandle " ) ;
2020-11-17 17:52:08 -04:00
return AudioDeviceHandleVarName ;
}
2021-01-13 10:48:59 -04:00
const FMetasoundFrontendArchetype & UMetasoundSource : : GetBaseArchetype ( )
2020-07-23 20:32:26 -04:00
{
2021-01-13 10:48:59 -04:00
auto CreateBaseArchetype = [ ] ( ) - > FMetasoundFrontendArchetype
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
FMetasoundFrontendArchetype Archetype ;
2020-12-14 15:48:27 -04:00
2021-01-13 10:48:59 -04:00
FMetasoundFrontendClassVertex OnPlayTrigger ;
2021-01-11 14:18:46 -04:00
OnPlayTrigger . Name = UMetasoundSource : : GetOnPlayInputName ( ) ;
2021-01-13 10:48:59 -04:00
OnPlayTrigger . Metadata . DisplayName = FText : : FromString ( OnPlayTrigger . Name ) ;
2021-01-27 15:54:01 -04:00
OnPlayTrigger . TypeName = Metasound : : Frontend : : GetDataTypeName < Metasound : : FTrigger > ( ) ;
2021-01-13 10:48:59 -04:00
OnPlayTrigger . Metadata . Description = LOCTEXT ( " OnPlayTriggerToolTip " , " Trigger executed when this source is played. " ) ;
2021-01-20 17:26:40 -04:00
OnPlayTrigger . PointIDs . Add ( FGuid : : NewGuid ( ) ) ;
2020-07-23 20:32:26 -04:00
2021-01-13 10:48:59 -04:00
Archetype . Interface . Inputs . Add ( OnPlayTrigger ) ;
2020-07-23 20:32:26 -04:00
2021-01-13 10:48:59 -04:00
FMetasoundFrontendClassVertex OnFinished ;
2020-12-14 15:48:27 -04:00
OnFinished . Name = UMetasoundSource : : GetIsFinishedOutputName ( ) ;
2021-01-13 10:48:59 -04:00
OnFinished . Metadata . DisplayName = FText : : FromString ( OnFinished . Name ) ;
2021-01-27 15:54:01 -04:00
OnFinished . TypeName = Metasound : : Frontend : : GetDataTypeName < Metasound : : FTrigger > ( ) ;
OnFinished . Metadata . Description = LOCTEXT ( " OnFinishedToolTip " , " Trigger executed to initiate stopping the source. " ) ;
2021-01-20 17:26:40 -04:00
OnFinished . PointIDs . Add ( FGuid : : NewGuid ( ) ) ;
2020-07-23 20:32:26 -04:00
2021-01-13 10:48:59 -04:00
Archetype . Interface . Outputs . Add ( OnFinished ) ;
2020-07-23 20:32:26 -04:00
2021-01-13 10:48:59 -04:00
FMetasoundFrontendEnvironmentVariable AudioDeviceHandle ;
2020-12-14 15:48:27 -04:00
AudioDeviceHandle . Name = UMetasoundSource : : GetAudioDeviceHandleVariableName ( ) ;
2021-01-13 10:48:59 -04:00
AudioDeviceHandle . Metadata . DisplayName = FText : : FromString ( AudioDeviceHandle . Name ) ;
AudioDeviceHandle . Metadata . Description = LOCTEXT ( " AudioDeviceHandleToolTip " , " Audio device handle " ) ;
2020-07-23 20:32:26 -04:00
2021-01-13 10:48:59 -04:00
Archetype . Interface . Environment . Add ( AudioDeviceHandle ) ;
2020-11-17 17:52:08 -04:00
2020-12-14 15:48:27 -04:00
return Archetype ;
} ;
2021-01-13 10:48:59 -04:00
static const FMetasoundFrontendArchetype BaseArchetype = CreateBaseArchetype ( ) ;
2020-12-14 15:48:27 -04:00
return BaseArchetype ;
}
2021-01-13 10:48:59 -04:00
const FMetasoundFrontendArchetype & UMetasoundSource : : GetMonoSourceArchetype ( )
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
auto CreateMonoArchetype = [ ] ( ) - > FMetasoundFrontendArchetype
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
FMetasoundFrontendArchetype Archetype = GetBaseArchetype ( ) ;
Archetype . Name = FName ( TEXT ( " MonoSource " ) ) ;
2020-12-14 15:48:27 -04:00
2021-01-13 10:48:59 -04:00
FMetasoundFrontendClassVertex GeneratedAudio ;
2020-12-14 15:48:27 -04:00
GeneratedAudio . Name = UMetasoundSource : : GetAudioOutputName ( ) ;
GeneratedAudio . TypeName = Metasound : : Frontend : : GetDataTypeName < Metasound : : FMonoAudioFormat > ( ) ;
2021-01-13 10:48:59 -04:00
GeneratedAudio . Metadata . DisplayName = LOCTEXT ( " GeneratedMono " , " Mono " ) ;
GeneratedAudio . Metadata . Description = LOCTEXT ( " GeneratedAudioToolTip " , " The resulting output audio from this source. " ) ;
2021-01-20 17:26:40 -04:00
GeneratedAudio . PointIDs . Add ( FGuid : : NewGuid ( ) ) ;
2020-12-14 15:48:27 -04:00
2021-01-13 10:48:59 -04:00
Archetype . Interface . Outputs . Add ( GeneratedAudio ) ;
2020-12-14 15:48:27 -04:00
return Archetype ;
} ;
2021-01-13 10:48:59 -04:00
static const FMetasoundFrontendArchetype MonoArchetype = CreateMonoArchetype ( ) ;
2020-12-14 15:48:27 -04:00
return MonoArchetype ;
}
2021-01-13 10:48:59 -04:00
const FMetasoundFrontendArchetype & UMetasoundSource : : GetStereoSourceArchetype ( )
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
auto CreateStereoArchetype = [ ] ( ) - > FMetasoundFrontendArchetype
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
FMetasoundFrontendArchetype Archetype = GetBaseArchetype ( ) ;
Archetype . Name = FName ( TEXT ( " StereoSource " ) ) ;
2020-12-14 15:48:27 -04:00
2021-01-13 10:48:59 -04:00
FMetasoundFrontendClassVertex GeneratedAudio ;
2020-12-14 15:48:27 -04:00
GeneratedAudio . Name = UMetasoundSource : : GetAudioOutputName ( ) ;
GeneratedAudio . TypeName = Metasound : : Frontend : : GetDataTypeName < Metasound : : FStereoAudioFormat > ( ) ;
2021-01-13 10:48:59 -04:00
GeneratedAudio . Metadata . DisplayName = LOCTEXT ( " GeneratedStereo " , " Stereo " ) ;
GeneratedAudio . Metadata . Description = LOCTEXT ( " GeneratedAudioToolTip " , " The resulting output audio from this source. " ) ;
2021-01-20 17:26:40 -04:00
GeneratedAudio . PointIDs . Add ( FGuid : : NewGuid ( ) ) ;
2020-12-14 15:48:27 -04:00
2021-01-13 10:48:59 -04:00
Archetype . Interface . Outputs . Add ( GeneratedAudio ) ;
2020-12-14 15:48:27 -04:00
return Archetype ;
} ;
2021-01-13 10:48:59 -04:00
static const FMetasoundFrontendArchetype StereoArchetype = CreateStereoArchetype ( ) ;
2020-12-14 15:48:27 -04:00
return StereoArchetype ;
2020-07-23 20:32:26 -04:00
}
# undef LOCTEXT_NAMESPACE