2021-08-30 14:08:45 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundParameterTransmitter.h"
2022-11-03 14:18:47 -04:00
# include "HAL/IConsoleManager.h"
2021-12-10 20:37:31 -05:00
# include "IAudioParameterInterfaceRegistry.h"
2022-08-19 12:14:31 -04:00
# include "Interfaces/MetasoundFrontendSourceInterface.h"
2021-08-30 14:08:45 -04:00
# include "MetasoundLog.h"
namespace Metasound
{
2022-09-21 15:42:38 -04:00
int32 MetaSoundParameterEnableWarningOnIgnoredParameterCVar = 0 ;
FAutoConsoleVariableRef CVarMetaSoundParameterEnableWarningOnIgnoredParameter (
TEXT ( " au.MetaSound.Parameter.EnableWarningOnIgnoredParameter " ) ,
MetaSoundParameterEnableWarningOnIgnoredParameterCVar ,
TEXT ( " If enabled, a warning will be logged when a parameters sent to a MetaSound is ignored. \n " )
TEXT ( " 0: Disabled (default), !0: Enabled " ) ,
ECVF_Default ) ;
2023-04-05 17:38:47 -04:00
2021-11-22 15:55:50 -05:00
namespace Frontend
{
FLiteral ConvertParameterToLiteral ( FAudioParameter & & InValue )
{
switch ( InValue . ParamType )
{
2023-01-17 18:39:44 -05:00
case EAudioParameterType : : Trigger :
2021-11-22 15:55:50 -05:00
case EAudioParameterType : : Boolean :
{
return FLiteral ( InValue . BoolParam ) ;
}
case EAudioParameterType : : BooleanArray :
{
return FLiteral ( MoveTemp ( InValue . ArrayBoolParam ) ) ;
}
case EAudioParameterType : : Float :
{
return FLiteral ( InValue . FloatParam ) ;
}
case EAudioParameterType : : FloatArray :
{
return FLiteral ( MoveTemp ( InValue . ArrayFloatParam ) ) ;
}
case EAudioParameterType : : Integer :
{
return FLiteral ( InValue . IntParam ) ;
}
case EAudioParameterType : : IntegerArray :
{
return FLiteral ( MoveTemp ( InValue . ArrayIntParam ) ) ;
}
case EAudioParameterType : : None :
{
return FLiteral ( ) ;
}
case EAudioParameterType : : NoneArray :
{
TArray < FLiteral : : FNone > InitArray ;
InitArray . Init ( FLiteral : : FNone ( ) , InValue . IntParam ) ;
return FLiteral ( MoveTemp ( InitArray ) ) ;
}
case EAudioParameterType : : Object :
{
if ( InValue . ObjectProxies . IsEmpty ( ) )
{
return FLiteral ( ) ;
}
return FLiteral ( MoveTemp ( InValue . ObjectProxies [ 0 ] ) ) ;
}
case EAudioParameterType : : ObjectArray :
{
return FLiteral ( MoveTemp ( InValue . ObjectProxies ) ) ;
}
case EAudioParameterType : : String :
{
return FLiteral ( MoveTemp ( InValue . StringParam ) ) ;
}
case EAudioParameterType : : StringArray :
{
return FLiteral ( MoveTemp ( InValue . ArrayStringParam ) ) ;
}
default :
{
2023-01-17 18:39:44 -05:00
static_assert ( static_cast < int32 > ( EAudioParameterType : : COUNT ) = = 13 , " Possible missing switch case coverage " ) ;
2021-11-22 15:55:50 -05:00
checkNoEntry ( ) ;
}
}
return FLiteral ( ) ;
}
2022-09-28 22:19:31 -04:00
FLiteral ConvertParameterToLiteral ( const FAudioParameter & InValue )
{
switch ( InValue . ParamType )
{
2023-01-17 18:39:44 -05:00
case EAudioParameterType : : Trigger :
2022-09-28 22:19:31 -04:00
case EAudioParameterType : : Boolean :
{
return FLiteral ( InValue . BoolParam ) ;
}
case EAudioParameterType : : BooleanArray :
{
return FLiteral ( InValue . ArrayBoolParam ) ;
}
case EAudioParameterType : : Float :
{
return FLiteral ( InValue . FloatParam ) ;
}
case EAudioParameterType : : FloatArray :
{
return FLiteral ( InValue . ArrayFloatParam ) ;
}
case EAudioParameterType : : Integer :
{
return FLiteral ( InValue . IntParam ) ;
}
case EAudioParameterType : : IntegerArray :
{
return FLiteral ( InValue . ArrayIntParam ) ;
}
case EAudioParameterType : : None :
{
return FLiteral ( ) ;
}
case EAudioParameterType : : NoneArray :
{
TArray < FLiteral : : FNone > InitArray ;
InitArray . Init ( FLiteral : : FNone ( ) , InValue . IntParam ) ;
return FLiteral ( InitArray ) ;
}
case EAudioParameterType : : Object :
{
if ( InValue . ObjectProxies . IsEmpty ( ) )
{
return FLiteral ( ) ;
}
2022-12-14 13:56:22 -05:00
return FLiteral ( InValue . ObjectProxies . Last ( ) ) ;
2022-09-28 22:19:31 -04:00
}
case EAudioParameterType : : ObjectArray :
{
2022-12-14 13:56:22 -05:00
return FLiteral ( InValue . ObjectProxies ) ;
2022-09-28 22:19:31 -04:00
}
case EAudioParameterType : : String :
{
return FLiteral ( InValue . StringParam ) ;
}
case EAudioParameterType : : StringArray :
{
return FLiteral ( InValue . ArrayStringParam ) ;
}
default :
{
2023-01-17 18:39:44 -05:00
static_assert ( static_cast < int32 > ( EAudioParameterType : : COUNT ) = = 13 , " Possible missing switch case coverage " ) ;
2022-09-28 22:19:31 -04:00
checkNoEntry ( ) ;
}
}
return FLiteral ( ) ;
}
2021-11-22 15:55:50 -05:00
FName ConvertParameterToDataType ( EAudioParameterType InParameterType )
{
switch ( InParameterType )
{
2023-01-17 18:39:44 -05:00
case EAudioParameterType : : Trigger :
2021-11-22 15:55:50 -05:00
case EAudioParameterType : : Boolean :
return GetMetasoundDataTypeName < bool > ( ) ;
case EAudioParameterType : : BooleanArray :
return GetMetasoundDataTypeName < TArray < bool > > ( ) ;
case EAudioParameterType : : Float :
return GetMetasoundDataTypeName < float > ( ) ;
case EAudioParameterType : : FloatArray :
return GetMetasoundDataTypeName < TArray < float > > ( ) ;
case EAudioParameterType : : Integer :
return GetMetasoundDataTypeName < int32 > ( ) ;
case EAudioParameterType : : IntegerArray :
return GetMetasoundDataTypeName < TArray < int32 > > ( ) ;
case EAudioParameterType : : String :
return GetMetasoundDataTypeName < FString > ( ) ;
case EAudioParameterType : : StringArray :
return GetMetasoundDataTypeName < TArray < FString > > ( ) ;
case EAudioParameterType : : Object :
case EAudioParameterType : : ObjectArray :
// TODO: Add support for objects
case EAudioParameterType : : None :
case EAudioParameterType : : NoneArray :
default :
ensureAlwaysMsgf ( false , TEXT ( " Failed to convert AudioParameterType to POD MetaSound DataType " ) ) ;
2023-01-17 18:39:44 -05:00
static_assert ( static_cast < int32 > ( EAudioParameterType : : COUNT ) = = 13 , " Possible missing case coverage " ) ;
2021-11-22 15:55:50 -05:00
return FName ( ) ;
}
}
2021-12-10 20:37:31 -05:00
} // namespace Frontend
2021-08-30 14:08:45 -04:00
2021-09-13 14:14:37 -04:00
FSendAddress FMetaSoundParameterTransmitter : : CreateSendAddressFromEnvironment ( const FMetasoundEnvironment & InEnvironment , const FVertexName & InVertexName , const FName & InTypeName )
2021-08-30 14:08:45 -04:00
{
2021-12-10 20:37:31 -05:00
using namespace Frontend ;
2021-12-10 19:13:22 -05:00
2021-12-10 20:37:31 -05:00
uint64 InstanceID = - 1 ;
2024-05-30 19:36:18 -04:00
if ( ensure ( InEnvironment . Contains < uint64 > ( CoreInterface : : Environment : : InstanceID ) ) )
2021-08-30 14:08:45 -04:00
{
2024-05-30 19:36:18 -04:00
InstanceID = InEnvironment . GetValue < uint64 > ( CoreInterface : : Environment : : InstanceID ) ;
2021-08-30 14:08:45 -04:00
}
2023-04-05 17:38:47 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2021-09-13 14:14:37 -04:00
return CreateSendAddressFromInstanceID ( InstanceID , InVertexName , InTypeName ) ;
2023-04-05 17:38:47 -04:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2021-08-30 14:08:45 -04:00
}
2021-09-13 14:14:37 -04:00
FSendAddress FMetaSoundParameterTransmitter : : CreateSendAddressFromInstanceID ( uint64 InInstanceID , const FVertexName & InVertexName , const FName & InTypeName )
2021-08-30 14:08:45 -04:00
{
2021-10-12 21:21:22 -04:00
return FSendAddress ( InVertexName , InTypeName , InInstanceID ) ;
2021-08-30 14:08:45 -04:00
}
2022-09-28 22:19:31 -04:00
FMetaSoundParameterTransmitter : : FMetaSoundParameterTransmitter ( FMetaSoundParameterTransmitter : : FInitParams & & InInitParams )
: Audio : : FParameterTransmitterBase ( MoveTemp ( InInitParams . DefaultParams ) )
, InstanceID ( InInitParams . InstanceID )
, DebugMetaSoundName ( InInitParams . DebugMetaSoundName )
2023-04-05 17:38:47 -04:00
, AvailableParameterNames ( MoveTemp ( InInitParams . ValidParameterNames ) )
, DataChannel ( MoveTemp ( InInitParams . DataChannel ) )
2021-08-30 14:08:45 -04:00
{
}
2023-04-03 16:20:21 -04:00
bool FMetaSoundParameterTransmitter : : Reset ( )
{
OnDeleteActiveSound ( ) ;
return true ;
2021-08-30 14:08:45 -04:00
}
2023-12-01 12:57:59 -05:00
void FMetaSoundParameterTransmitter : : AddAvailableParameter ( FName InName )
{
AvailableParameterNames . Add ( InName ) ;
}
void FMetaSoundParameterTransmitter : : RemoveAvailableParameter ( FName InName )
{
AvailableParameterNames . Remove ( InName ) ;
}
2024-02-16 19:32:08 -05:00
bool FMetaSoundParameterTransmitter : : SetVirtualizedParameters ( TArray < FAudioParameter > & & InParameters )
{
bool bSuccess = true ;
// Remove triggers
for ( int32 ParamIndex = InParameters . Num ( ) - 1 ; ParamIndex > = 0 ; - - ParamIndex )
{
// Triggers are transient and are not applied for virtualized sounds.
// If a cached value is desired, use SetBoolParameter
// (see comment for IAudioParameterControllerInterface::SetTriggerParameter)
FAudioParameter & Param = InParameters [ ParamIndex ] ;
if ( Param . ParamType = = EAudioParameterType : : Trigger )
{
InParameters . RemoveAtSwap ( ParamIndex , 1 , EAllowShrinking : : No ) ;
}
}
if ( ! InParameters . IsEmpty ( ) )
{
bSuccess & = FParameterTransmitterBase : : SetParameters ( MoveTemp ( InParameters ) ) ;
}
InParameters . Reset ( ) ;
return bSuccess ;
}
2022-03-10 22:07:08 -05:00
bool FMetaSoundParameterTransmitter : : SetParameters ( TArray < FAudioParameter > & & InParameters )
2021-08-30 14:08:45 -04:00
{
2024-02-16 19:32:08 -05:00
// Don't set parameters directly if the active sound
// is currently virtualized (to prevent accumulation of unneeded updates)
if ( bIsVirtualized )
{
return SetVirtualizedParameters ( MoveTemp ( InParameters ) ) ;
}
2022-03-10 22:07:08 -05:00
bool bSuccess = true ;
2023-12-06 11:14:23 -05:00
for ( int32 ParamIndex = InParameters . Num ( ) - 1 ; ParamIndex > = 0 ; - - ParamIndex )
2022-03-10 22:07:08 -05:00
{
2023-12-06 11:14:23 -05:00
FAudioParameter & Param = InParameters [ ParamIndex ] ;
2022-09-28 22:19:31 -04:00
const FName ParamName = Param . ParamName ;
2023-12-06 11:14:23 -05:00
if ( ! SetParameterWithLiteral ( ParamName , Frontend : : ConvertParameterToLiteral ( Param ) ) )
2022-09-28 22:19:31 -04:00
{
2024-02-19 16:51:58 -05:00
InParameters . RemoveAtSwap ( ParamIndex , EAllowShrinking : : No ) ;
2022-09-28 22:19:31 -04:00
bSuccess = false ;
}
}
2023-12-06 11:14:23 -05:00
if ( ! InParameters . IsEmpty ( ) )
2022-09-28 22:19:31 -04:00
{
2023-12-06 11:14:23 -05:00
bSuccess & = FParameterTransmitterBase : : SetParameters ( MoveTemp ( InParameters ) ) ;
2022-03-10 22:07:08 -05:00
}
InParameters . Reset ( ) ;
return bSuccess ;
2021-11-22 15:55:50 -05:00
}
2021-08-30 14:08:45 -04:00
bool FMetaSoundParameterTransmitter : : SetParameterWithLiteral ( FName InParameterName , const FLiteral & InLiteral )
{
2023-04-05 17:38:47 -04:00
if ( AvailableParameterNames . Contains ( InParameterName ) )
2021-08-30 14:08:45 -04:00
{
2023-04-05 17:38:47 -04:00
if ( DataChannel . IsValid ( ) )
2021-08-30 14:08:45 -04:00
{
2023-04-05 17:38:47 -04:00
DataChannel - > Enqueue ( FParameter { InParameterName , InLiteral } ) ;
2021-08-30 14:08:45 -04:00
}
2023-04-05 17:38:47 -04:00
return true ;
2021-08-30 14:08:45 -04:00
}
2022-09-21 15:42:38 -04:00
// Enable / disable via CVAR to avoid log spam.
if ( MetaSoundParameterEnableWarningOnIgnoredParameterCVar )
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to set parameter %s in asset %s on instance %d with value %s. No runtime modifiable input with that name exists on instance. " ) , * InParameterName . ToString ( ) , * DebugMetaSoundName . ToString ( ) , InstanceID , * LexToString ( InLiteral ) ) ;
}
2021-08-30 14:08:45 -04:00
return false ;
}
}