2021-12-10 20:37:31 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-08-19 12:14:31 -04:00
# include "Interfaces/MetasoundFrontendSourceInterface.h"
2021-12-10 20:37:31 -05:00
2022-08-19 12:14:31 -04:00
# include "AudioParameter.h"
2021-12-10 20:37:31 -05:00
# include "MetasoundDataReference.h"
# include "MetasoundPrimitives.h"
# include "MetasoundTrigger.h"
# include "Templates/SharedPointer.h"
2022-08-19 12:14:31 -04:00
# include "UObject/Class.h"
2021-12-10 20:37:31 -05:00
# define LOCTEXT_NAMESPACE "Metasound"
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
namespace Metasound : : Frontend
2021-12-10 20:37:31 -05:00
{
2023-04-04 19:14:26 -04:00
namespace SourceInterfacePrivate
2021-12-10 20:37:31 -05:00
{
2023-04-05 20:15:22 -04:00
TArray < Audio : : FParameterInterface : : FClassOptions > GetDefaultSourceClassOptions ( const FTopLevelAssetPath & InClassPath , bool bIsModifiable )
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
constexpr bool bIsDefault = true ;
return TArray < Audio : : FParameterInterface : : FClassOptions >
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
{ InClassPath , bIsModifiable , bIsDefault }
} ;
}
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
# define AUDIO_PARAMETER_INTERFACE_NAMESPACE "UE.Source.OneShot"
namespace SourceOneShotInterface
{
const FMetasoundFrontendVersion & GetVersion ( )
{
static const FMetasoundFrontendVersion Version = { AUDIO_PARAMETER_INTERFACE_NAMESPACE , { 1 , 0 } } ;
return Version ;
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
namespace Outputs
{
const FName OnFinished = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " OnFinished " ) ;
}
2023-03-07 17:01:52 -05:00
2023-04-04 19:14:26 -04:00
Audio : : FParameterInterfacePtr CreateInterface ( const UClass & InClass )
{
struct FInterface : public Audio : : FParameterInterface
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
FInterface ( const FTopLevelAssetPath & InClassPath )
: FParameterInterface ( SourceOneShotInterface : : GetVersion ( ) . Name , SourceOneShotInterface : : GetVersion ( ) . Number . ToInterfaceVersion ( ) )
2021-12-15 23:11:10 -05:00
{
2023-04-05 20:15:22 -04:00
constexpr bool bIsModifiable = true ;
UClassOptions = SourceInterfacePrivate : : GetDefaultSourceClassOptions ( InClassPath , bIsModifiable ) ;
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
Outputs =
{
{
LOCTEXT ( " OnFinished " , " On Finished " ) ,
LOCTEXT ( " OnFinishedDescription " , " Trigger executed to initiate stopping the source. " ) ,
GetMetasoundDataTypeName < FTrigger > ( ) ,
Outputs : : OnFinished ,
LOCTEXT ( " OnFinishedWarning " , " \" On Finished \" should be connected for OneShot MetaSound sources. For sources with undefined duration (e.g. looping), remove the OneShot interface and use an audio component to avoid leaking the source. " ) ,
}
} ;
}
} ;
return MakeShared < FInterface > ( InClass . GetClassPathName ( ) ) ;
}
} // namespace SourceOneShotInterface
2021-12-15 23:11:10 -05:00
# undef AUDIO_PARAMETER_INTERFACE_NAMESPACE
# define AUDIO_PARAMETER_INTERFACE_NAMESPACE "UE.Source"
2023-04-04 19:14:26 -04:00
namespace SourceInterfaceV1_0
{
const FMetasoundFrontendVersion & GetVersion ( )
2021-12-10 20:37:31 -05:00
{
2023-04-04 19:14:26 -04:00
static const FMetasoundFrontendVersion Version = { AUDIO_PARAMETER_INTERFACE_NAMESPACE , { 1 , 0 } } ;
return Version ;
}
2021-12-10 20:37:31 -05:00
2023-04-04 19:14:26 -04:00
namespace Inputs
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
const FName OnPlay = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " OnPlay " ) ;
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
namespace Outputs
{
const FName OnFinished = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " OnFinished " ) ;
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
namespace Environment
{
const FName DeviceID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " AudioDeviceID " ) ;
const FName GraphName = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " GraphName " ) ;
const FName IsPreview = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " IsPreviewSound " ) ;
const FName SoundUniqueID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " SoundUniqueID " ) ;
const FName TransmitterID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " TransmitterID " ) ;
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
Audio : : FParameterInterfacePtr CreateInterface ( const UClass & InClass )
{
struct FInterface : public Audio : : FParameterInterface
2023-03-07 17:01:52 -05:00
{
2023-04-04 19:14:26 -04:00
FInterface ( const FTopLevelAssetPath & InClassPath )
: FParameterInterface ( SourceInterfaceV1_0 : : GetVersion ( ) . Name , SourceInterfaceV1_0 : : GetVersion ( ) . Number . ToInterfaceVersion ( ) )
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
constexpr bool bIsModifiable = false ;
constexpr bool bIsDefault = false ;
UClassOptions = TArray < FClassOptions >
2021-12-15 23:11:10 -05:00
{
2023-04-04 19:14:26 -04:00
{ InClassPath , bIsModifiable , bIsDefault }
} ;
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
Inputs =
2021-12-15 23:11:10 -05:00
{
{
2023-04-04 19:14:26 -04:00
LOCTEXT ( " OnPlay " , " On Play " ) ,
LOCTEXT ( " OnPlayDescription " , " Trigger executed when the source is played. " ) ,
GetMetasoundDataTypeName < FTrigger > ( ) ,
{ Inputs : : OnPlay , false }
2021-12-15 23:11:10 -05:00
}
2023-04-04 19:14:26 -04:00
} ;
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
Outputs =
{
{
LOCTEXT ( " OnFinished " , " On Finished " ) ,
LOCTEXT ( " OnFinishedDescription " , " Trigger executed to initiate stopping the source. " ) ,
GetMetasoundDataTypeName < FTrigger > ( ) ,
Outputs : : OnFinished
}
} ;
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
Environment =
{
{
LOCTEXT ( " AudioDeviceIDDisplayName " , " Audio Device ID " ) ,
LOCTEXT ( " AudioDeviceIDDescription " , " ID of AudioDevice source is played from. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint32)
Environment : : DeviceID
} ,
{
LOCTEXT ( " GraphNameDisplayName " , " Graph Name " ) ,
LOCTEXT ( " GraphNameDescription " , " Name of source graph (for debugging/logging). " ) ,
GetMetasoundDataTypeName < FString > ( ) ,
Environment : : GraphName
} ,
{
LOCTEXT ( " IsPreviewSoundDisplayName " , " Is Preview Sound " ) ,
LOCTEXT ( " IsPreviewSoundDescription " , " Whether source is being played as a previewed sound. " ) ,
GetMetasoundDataTypeName < bool > ( ) ,
Environment : : IsPreview
} ,
{
LOCTEXT ( " TransmitterIDDisplayName " , " Transmitter ID " ) ,
LOCTEXT ( " TransmitterIDDescription " , " ID used by Transmission System to generate a unique send address for each source instance. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint64)
Environment : : TransmitterID
} ,
{
LOCTEXT ( " SoundUniqueIdDisplayName " , " Sound Unique ID " ) ,
LOCTEXT ( " SoundUniqueIdDescription " , " ID of unique source instance. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint32)
Environment : : SoundUniqueID
}
} ;
2021-12-15 23:11:10 -05:00
}
2023-04-04 19:14:26 -04:00
} ;
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
return MakeShared < FInterface > ( InClass . GetClassPathName ( ) ) ;
}
} // namespace SourceInterfaceV1_0
namespace SourceInterface
{
const FMetasoundFrontendVersion & GetVersion ( )
{
static const FMetasoundFrontendVersion Version = { AUDIO_PARAMETER_INTERFACE_NAMESPACE , { 1 , 1 } } ;
return Version ;
}
namespace Inputs
{
const FName OnPlay = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " OnPlay " ) ;
}
namespace Environment
{
const FName DeviceID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " AudioDeviceID " ) ;
const FName GraphName = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " GraphName " ) ;
const FName IsPreview = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " IsPreviewSound " ) ;
const FName SoundUniqueID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " SoundUniqueID " ) ;
const FName TransmitterID = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " TransmitterID " ) ;
const FName AudioMixerNumOutputFrames = AUDIO_PARAMETER_INTERFACE_MEMBER_DEFINE ( " AudioMixerNumOutputFrames " ) ;
}
Audio : : FParameterInterfacePtr CreateInterface ( const UClass & InClass )
{
struct FInterface : public Audio : : FParameterInterface
{
FInterface ( const FTopLevelAssetPath & InClassPath )
: FParameterInterface ( SourceInterface : : GetVersion ( ) . Name , SourceInterface : : GetVersion ( ) . Number . ToInterfaceVersion ( ) )
{
2023-04-05 20:15:22 -04:00
constexpr bool bIsModifiable = false ;
UClassOptions = SourceInterfacePrivate : : GetDefaultSourceClassOptions ( InClassPath , bIsModifiable ) ;
2023-04-04 19:14:26 -04:00
Inputs =
{
{
LOCTEXT ( " OnPlay " , " On Play " ) ,
LOCTEXT ( " OnPlayDescription " , " Trigger executed when the source is played. " ) ,
GetMetasoundDataTypeName < FTrigger > ( ) ,
{ Inputs : : OnPlay , false }
}
} ;
Environment =
{
{
LOCTEXT ( " AudioDeviceIDDisplayName1 " , " Audio Device ID " ) ,
LOCTEXT ( " AudioDeviceIDDescription2 " , " ID of AudioDevice source is played from. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint32)
Environment : : DeviceID
} ,
{
LOCTEXT ( " GraphNameDisplayName " , " Graph Name " ) ,
LOCTEXT ( " AudioDeviceIDDescription3 " , " Name of source graph (for debugging/logging). " ) ,
GetMetasoundDataTypeName < FString > ( ) ,
Environment : : GraphName
} ,
{
LOCTEXT ( " IsPreviewSoundDisplayName " , " Is Preview Sound " ) ,
LOCTEXT ( " IsPreviewSoundDescription4 " , " Whether source is being played as a previewed sound. " ) ,
GetMetasoundDataTypeName < bool > ( ) ,
Environment : : IsPreview
} ,
{
LOCTEXT ( " TransmitterIDDisplayName " , " Transmitter ID " ) ,
LOCTEXT ( " TransmitterIDDescription " , " ID used by Transmission System to generate a unique send address for each source instance. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint64)
Environment : : TransmitterID
} ,
{
LOCTEXT ( " SoundUniqueDisplayName " , " Sound Unique ID " ) ,
LOCTEXT ( " SoundUniqueDescription " , " ID of unique source instance. " ) ,
FName ( ) , // TODO: Align environment data types with environment (ex. this is actually set/get as a uint32)
Environment : : SoundUniqueID
} ,
{
LOCTEXT ( " AudioMixerOutputFramesDisplayName " , " Audio Mixer Output Frames " ) ,
LOCTEXT ( " AudioMixerOutputFramesDescription " , " The number of output frames rendered per buffer in the audio mixer. " ) ,
FName ( ) ,
Environment : : AudioMixerNumOutputFrames
}
} ;
}
} ;
return MakeShared < FInterface > ( InClass . GetClassPathName ( ) ) ;
}
bool FUpdateInterface : : Transform ( Frontend : : FDocumentHandle InDocument ) const
{
using namespace Frontend ;
// When upgrading, we only want to add the one-shot interface if the MetaSound actually has the OnFinished trigger connected.
bool bIsOnFinishedConnected = false ;
InDocument - > GetRootGraph ( ) - > IterateConstNodes ( [ & ] ( Frontend : : FConstNodeHandle NodeHandle )
{
NodeHandle - > IterateConstInputs ( [ & ] ( Frontend : : FConstInputHandle InputHandle )
{
if ( InputHandle - > GetName ( ) = = SourceInterfaceV1_0 : : Outputs : : OnFinished )
{
bIsOnFinishedConnected = InputHandle - > IsConnected ( ) ;
}
} ) ;
} , EMetasoundFrontendClassType : : Output ) ;
const TArray < FMetasoundFrontendVersion > InterfacesToRemove
{
SourceInterfaceV1_0 : : GetVersion ( )
} ;
TArray < FMetasoundFrontendVersion > InterfacesToAdd
{
SourceInterface : : GetVersion ( )
} ;
if ( bIsOnFinishedConnected )
{
InterfacesToAdd . Add ( SourceOneShotInterface : : GetVersion ( ) ) ;
2021-12-15 23:11:10 -05:00
}
2023-04-04 19:14:26 -04:00
Frontend : : FModifyRootGraphInterfaces InterfaceTransform ( InterfacesToRemove , InterfacesToAdd ) ;
return InterfaceTransform . Transform ( InDocument ) ;
}
2021-12-15 23:11:10 -05:00
2023-04-04 19:14:26 -04:00
} // namespace SourceInterface
2021-12-15 23:11:10 -05:00
# undef AUDIO_PARAMETER_INTERFACE_NAMESPACE
2023-04-04 19:14:26 -04:00
} // namespace Metasound::Frontend
2022-02-24 23:16:52 -05:00
# undef LOCTEXT_NAMESPACE