2021-09-08 12:59:26 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "AudioDevice.h"
# include "Components/AudioComponent.h"
2023-06-22 14:51:42 -04:00
# include "EngineTestMetaSoundBuilder.h"
2021-12-10 20:37:43 -05:00
# include "IAudioParameterInterfaceRegistry.h"
2021-09-08 12:59:26 -04:00
# include "Interfaces/IPluginManager.h"
2023-03-07 17:01:52 -05:00
# include "Interfaces/MetasoundOutputFormatInterfaces.h"
2022-08-19 12:14:31 -04:00
# include "Interfaces/MetasoundFrontendSourceInterface.h"
2023-07-19 17:25:21 -04:00
# include "MetasoundLog.h"
2021-09-08 12:59:26 -04:00
# include "MetasoundSource.h"
# include "Misc/AutomationTest.h"
2023-02-11 12:39:56 -05:00
# include "Misc/Paths.h"
2023-06-22 14:51:42 -04:00
# include "Templates/SharedPointer.h"
2021-09-08 12:59:26 -04:00
# include "Tests/AutomationCommon.h"
2023-07-18 15:24:34 -04:00
# include "Sound/SoundAttenuation.h"
2023-06-20 14:03:55 -04:00
2021-09-08 12:59:26 -04:00
# if WITH_DEV_AUTOMATION_TESTS
2023-06-22 14:51:42 -04:00
namespace EngineTestMetaSoundSourcePrivate
2021-09-08 12:59:26 -04:00
{
2023-06-22 14:51:42 -04:00
struct FInitTestBuilderSourceOutput
2023-06-16 17:48:20 -04:00
{
FMetaSoundBuilderNodeOutputHandle OnPlayOutput ;
FMetaSoundBuilderNodeInputHandle OnFinishedInput ;
TArray < FMetaSoundBuilderNodeInputHandle > AudioOutNodeInputs ;
} ;
2023-07-25 12:40:57 -04:00
FString GetPluginContentDirectory ( )
2021-09-08 12:59:26 -04:00
{
TSharedPtr < IPlugin > Plugin = IPluginManager : : Get ( ) . FindPlugin ( TEXT ( " Metasound " ) ) ;
if ( ensure ( Plugin . IsValid ( ) ) )
{
return Plugin - > GetContentDir ( ) ;
}
return FString ( ) ;
}
2023-07-25 12:40:57 -04:00
FString GetPathToTestFilesDir ( )
2021-09-08 12:59:26 -04:00
{
FString OutPath = FPaths : : Combine ( GetPluginContentDirectory ( ) , TEXT ( " Test " ) ) ;
OutPath = FPaths : : ConvertRelativePathToFull ( OutPath ) ;
FPaths : : NormalizeDirectoryName ( OutPath ) ;
return OutPath ;
}
2023-07-25 12:40:57 -04:00
FString GetPathToGeneratedFilesDir ( )
2021-09-08 12:59:26 -04:00
{
FString OutPath = FPaths : : Combine ( FPaths : : ProjectSavedDir ( ) , TEXT ( " Metasounds " ) ) ;
OutPath = FPaths : : ConvertRelativePathToFull ( OutPath ) ;
FPaths : : NormalizeDirectoryName ( OutPath ) ;
return OutPath ;
}
2023-07-25 12:40:57 -04:00
FString GetPathToGeneratedAssetsDir ( )
2021-09-08 12:59:26 -04:00
{
FString OutPath = TEXT ( " /Game/Metasound/Generated/ " ) ;
FPaths : : NormalizeDirectoryName ( OutPath ) ;
return OutPath ;
}
2022-04-27 19:04:31 -04:00
Metasound : : Frontend : : FNodeHandle AddNode ( Metasound : : Frontend : : IGraphController & InGraph , const Metasound : : FNodeClassName & InClassName , int32 InMajorVersion )
2021-09-08 12:59:26 -04:00
{
2022-04-27 19:04:31 -04:00
Metasound : : Frontend : : FNodeHandle Node = Metasound : : Frontend : : INodeController : : GetInvalidHandle ( ) ;
2021-09-08 12:59:26 -04:00
FMetasoundFrontendClass NodeClass ;
2022-04-27 19:04:31 -04:00
if ( ensure ( Metasound : : Frontend : : ISearchEngine : : Get ( ) . FindClassWithHighestMinorVersion ( InClassName , InMajorVersion , NodeClass ) ) )
{
Node = InGraph . AddNode ( NodeClass . Metadata ) ;
check ( Node - > IsValid ( ) ) ;
}
2021-09-08 12:59:26 -04:00
return Node ;
}
2023-06-26 15:42:30 -04:00
UMetaSoundSourceBuilder & CreateSourceBuilder (
FAutomationTestBase & Test ,
EMetaSoundOutputAudioFormat OutputFormat ,
bool bIsOneShot ,
EngineTestMetaSoundSourcePrivate : : FInitTestBuilderSourceOutput & Output )
2023-06-16 17:48:20 -04:00
{
using namespace Audio ;
using namespace Metasound ;
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
EMetaSoundBuilderResult Result ;
UMetaSoundSourceBuilder * Builder = UMetaSoundBuilderSubsystem : : GetChecked ( ) . CreateSourceBuilder (
" Unit Test Graph Builder " ,
Output . OnPlayOutput ,
Output . OnFinishedInput ,
Output . AudioOutNodeInputs ,
Result ,
OutputFormat ,
bIsOneShot ) ;
2023-06-26 15:42:30 -04:00
checkf ( Builder , TEXT ( " Failed to create MetaSoundSourceBuilder " ) ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , TEXT ( " Builder created but CreateSourceBuilder did not result in 'Succeeded' state " ) ) ;
2023-06-16 17:48:20 -04:00
return * Builder ;
}
2023-06-26 15:42:30 -04:00
UMetaSoundSourceBuilder & CreateMonoSourceSinGenBuilder (
2023-06-16 17:48:20 -04:00
FAutomationTestBase & Test ,
FMetaSoundBuilderNodeInputHandle * GenInputNodeFreq = nullptr ,
FMetaSoundBuilderNodeInputHandle * MonoOutNodeInput = nullptr ,
float InDefaultFreq = 100.f )
{
2023-06-22 14:51:42 -04:00
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
2023-06-16 17:48:20 -04:00
using namespace Metasound ;
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
constexpr EMetaSoundOutputAudioFormat OutputFormat = EMetaSoundOutputAudioFormat : : Mono ;
constexpr bool bIsOneShot = false ;
2023-06-22 14:51:42 -04:00
FInitTestBuilderSourceOutput Output ;
2023-09-13 20:11:49 -04:00
UMetaSoundSourceBuilder & Builder = CreateSourceBuilder ( Test , OutputFormat , bIsOneShot , Output ) ;
2023-06-16 17:48:20 -04:00
EMetaSoundBuilderResult Result = EMetaSoundBuilderResult : : Failed ;
if ( MonoOutNodeInput )
{
* MonoOutNodeInput = { } ;
}
// Input on Play
const FMetaSoundNodeHandle OnPlayOutputNode = Builder . FindGraphInputNode ( SourceInterface : : Inputs : : OnPlay , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded & & OnPlayOutputNode . IsSet ( ) , TEXT ( " Failed to create MetaSound OnPlay input " ) ) ;
// Input Frequency
FMetasoundFrontendLiteral DefaultFreq ;
DefaultFreq . Set ( InDefaultFreq ) ;
const FMetaSoundBuilderNodeOutputHandle FrequencyNodeOutput = Builder . AddGraphInputNode ( " Frequency " , GetMetasoundDataTypeName < float > ( ) , DefaultFreq , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded & & FrequencyNodeOutput . IsSet ( ) , TEXT ( " Failed to create new MetaSound graph input " ) ) ;
// Sine Oscillator Node
2023-09-01 13:19:23 -04:00
const FMetaSoundNodeHandle OscNode = Builder . AddNodeByClassName ( { " UE " , " Sine " , " Audio " } , Result , 1 ) ;
2023-06-16 17:48:20 -04:00
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded & & OscNode . IsSet ( ) , TEXT ( " Failed to create new MetaSound node by class name " ) ) ;
// Make connections:
const FMetaSoundBuilderNodeInputHandle OscNodeFrequencyInput = Builder . FindNodeInputByName ( OscNode , " Frequency " , Result ) ;
if ( GenInputNodeFreq )
{
* GenInputNodeFreq = OscNodeFrequencyInput ;
}
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded & & OscNodeFrequencyInput . IsSet ( ) , TEXT ( " Failed to find Sine Oscillator node input 'Frequency' " ) ) ;
const FMetaSoundBuilderNodeOutputHandle OscNodeAudioOutput = Builder . FindNodeOutputByName ( OscNode , " Audio " , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded & & OscNodeAudioOutput . IsSet ( ) , TEXT ( " Failed to find Sine Oscillator node output 'Audio' " ) ) ;
// Frequency input "Frequency" -> oscillator "Frequency"
Builder . ConnectNodes ( FrequencyNodeOutput , OscNodeFrequencyInput , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , TEXT ( " Failed to connect 'Frequency' input to node input 'Frequency' " ) ) ;
// Oscillator to Output Node
Test . AddErrorIfFalse ( Output . AudioOutNodeInputs . Num ( ) = = 1 , TEXT ( " Should only ever have one output node for mono " ) ) ;
if ( MonoOutNodeInput )
{
* MonoOutNodeInput = Output . AudioOutNodeInputs . Last ( ) ;
}
Builder . ConnectNodes ( OscNodeAudioOutput , Output . AudioOutNodeInputs . Last ( ) , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , TEXT ( " Failed to connect 'Audio' Sine Oscillator output to MetaSound graph's 'Mono Output' " ) ) ;
return Builder ;
}
2023-07-25 12:40:57 -04:00
FMetasoundFrontendDocument CreateMonoSourceDocument ( )
2021-09-08 12:59:26 -04:00
{
2021-12-10 20:37:43 -05:00
using namespace Audio ;
2021-09-08 12:59:26 -04:00
using namespace Metasound ;
2023-03-07 17:01:52 -05:00
using namespace Metasound : : Engine ;
2021-09-08 12:59:26 -04:00
using namespace Metasound : : Frontend ;
FMetasoundFrontendDocument Document ;
Document . RootGraph . Metadata . SetClassName ( FMetasoundFrontendClassName { " Namespace " , " Unit Test Node " , * LexToString ( FGuid : : NewGuid ( ) ) } ) ;
Document . RootGraph . Metadata . SetType ( EMetasoundFrontendClassType : : Graph ) ;
FDocumentHandle DocumentHandle = IDocumentController : : CreateDocumentHandle ( Document ) ;
2021-12-10 20:37:43 -05:00
FGraphHandle RootGraph = DocumentHandle - > GetRootGraph ( ) ;
2021-09-08 12:59:26 -04:00
check ( RootGraph - > IsValid ( ) ) ;
2021-12-10 20:37:43 -05:00
// Add default source & mono interface members (OnPlay, OnFinished & Mono Out)
2021-12-15 23:11:10 -05:00
FModifyRootGraphInterfaces InterfaceTransform (
2022-01-06 16:44:09 +00:00
{ } ,
2023-03-07 17:01:52 -05:00
{
SourceInterface : : GetVersion ( ) ,
2021-12-15 23:11:10 -05:00
SourceOneShotInterface : : GetVersion ( ) ,
2023-03-07 17:01:52 -05:00
OutputFormatMonoInterface : : GetVersion ( )
2022-01-06 16:44:09 +00:00
} ) ;
2021-12-10 20:37:43 -05:00
InterfaceTransform . Transform ( DocumentHandle ) ;
2021-09-08 12:59:26 -04:00
2021-12-10 20:37:43 -05:00
// Input on Play
2022-01-06 16:44:09 +00:00
FNodeHandle OnPlayOutputNode = RootGraph - > GetInputNodeWithName ( SourceInterface : : Inputs : : OnPlay ) ;
2021-12-10 20:37:43 -05:00
check ( OnPlayOutputNode - > IsValid ( ) ) ;
2021-09-08 12:59:26 -04:00
// Input Frequency
FMetasoundFrontendClassInput FrequencyInput ;
2021-12-10 20:37:43 -05:00
FrequencyInput . Name = " Frequency " ;
2021-09-08 12:59:26 -04:00
FrequencyInput . TypeName = GetMetasoundDataTypeName < float > ( ) ;
FrequencyInput . VertexID = FGuid : : NewGuid ( ) ;
FrequencyInput . DefaultLiteral . Set ( 100.f ) ;
FNodeHandle FrequencyInputNode = RootGraph - > AddInputVertex ( FrequencyInput ) ;
check ( FrequencyInputNode - > IsValid ( ) ) ;
2021-12-10 20:37:43 -05:00
// Output On Finished
2021-12-15 23:11:10 -05:00
FNodeHandle OnFinishedOutputNode = RootGraph - > GetOutputNodeWithName ( SourceOneShotInterface : : Outputs : : OnFinished ) ;
2021-12-10 20:37:43 -05:00
check ( OnFinishedOutputNode - > IsValid ( ) ) ;
2021-09-08 12:59:26 -04:00
// Output Audio
2021-12-10 20:37:43 -05:00
FNodeHandle AudioOutputNode = RootGraph - > GetOutputNodeWithName ( OutputFormatMonoInterface : : Outputs : : MonoOut ) ;
check ( AudioOutputNode - > IsValid ( ) ) ;
2021-09-08 12:59:26 -04:00
2021-12-10 20:37:43 -05:00
// osc node
2022-04-27 19:04:31 -04:00
FNodeHandle OscNode = AddNode ( * RootGraph , { " UE " , " Sine " , " Audio " } , 1 ) ;
2021-09-08 12:59:26 -04:00
// Make connections:
// frequency input "Frequency" -> oscillator "Frequency"
2021-10-12 21:21:22 -04:00
FOutputHandle OutputToConnect = FrequencyInputNode - > GetOutputWithVertexName ( " Frequency " ) ;
FInputHandle InputToConnect = OscNode - > GetInputWithVertexName ( " Frequency " ) ;
2021-09-08 12:59:26 -04:00
ensure ( InputToConnect - > Connect ( * OutputToConnect ) ) ;
// oscillator to output
2021-10-12 21:21:22 -04:00
OutputToConnect = OscNode - > GetOutputWithVertexName ( " Audio " ) ;
2021-12-10 20:37:43 -05:00
InputToConnect = AudioOutputNode - > GetInputWithVertexName ( OutputFormatMonoInterface : : Outputs : : MonoOut ) ;
2021-09-08 12:59:26 -04:00
ensure ( InputToConnect - > Connect ( * OutputToConnect ) ) ;
return Document ;
}
2023-07-25 12:40:57 -04:00
UAudioComponent * CreateTestComponent ( FAutomationTestBase & Test , USoundBase * Sound = nullptr , bool bAddToRoot = true )
{
if ( FAudioDevice * AudioDevice = GEngine - > GetMainAudioDeviceRaw ( ) )
{
UAudioComponent * AudioComponent = NewObject < UAudioComponent > ( ) ;
Test . AddErrorIfFalse ( AudioComponent ! = nullptr , " Failed to create test audio component " ) ;
if ( AudioComponent )
{
AudioComponent - > bAutoActivate = false ;
AudioComponent - > bIsUISound = true ; // play while "paused"
AudioComponent - > AudioDeviceID = AudioDevice - > DeviceID ;
AudioComponent - > bAllowSpatialization = false ;
AudioComponent - > SetVolumeMultiplier ( 1.0f ) ;
if ( bAddToRoot )
{
AudioComponent - > AddToRoot ( ) ;
}
AudioComponent - > SetSound ( Sound ) ;
}
return AudioComponent ;
}
return nullptr ;
}
2023-06-22 14:51:42 -04:00
} // EngineTestMetaSoundSourcePrivate
2021-09-08 12:59:26 -04:00
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER ( FAudioComponentPlayLatentCommand , UAudioComponent * , AudioComponent ) ;
bool FAudioComponentPlayLatentCommand : : Update ( )
{
if ( AudioComponent )
{
AudioComponent - > Play ( ) ;
return true ;
}
return false ;
}
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER ( FAudioComponentStopLatentCommand , UAudioComponent * , AudioComponent ) ;
bool FAudioComponentStopLatentCommand : : Update ( )
{
if ( AudioComponent )
{
AudioComponent - > Stop ( ) ;
return true ;
}
return false ;
}
2023-08-09 16:45:21 -04:00
DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER ( FMetaSoundSourceLatentSetParamsCommand , UAudioComponent * , AudioComponent , TArray < FAudioParameter > , Params ) ;
bool FMetaSoundSourceLatentSetParamsCommand : : Update ( )
{
if ( AudioComponent )
{
AudioComponent - > SetParameters ( MoveTemp ( Params ) ) ;
return true ;
}
return false ;
}
2023-06-16 17:48:20 -04:00
DEFINE_LATENT_AUTOMATION_COMMAND_THREE_PARAMETER ( FMetaSoundSourceBuilderAuditionLatentCommand , UMetaSoundSourceBuilder * , Builder , UAudioComponent * , AudioComponent , bool , bEnableLiveUpdates ) ;
bool FMetaSoundSourceBuilderAuditionLatentCommand : : Update ( )
{
if ( Builder & & AudioComponent )
{
2023-07-19 17:25:21 -04:00
auto GetComponentSoundClassName = [ this ] ( ) - > FName
{
if ( const USoundBase * InitSound = AudioComponent - > GetSound ( ) )
{
const UMetaSoundSource * InitMetaSound = CastChecked < UMetaSoundSource > ( InitSound ) ;
return InitMetaSound - > GetDocumentChecked ( ) . RootGraph . Metadata . GetClassName ( ) . GetFullName ( ) ;
}
return { } ;
} ;
// This is an inline test to ensure that the first time a builder is auditioned, its generating a new unique MetaSound Class Name.
// Each subsequent call should maintain that name to avoid bloating the FName table/breaking references should this auditioned sound
// be in anyway referenced.
const FName InitClassName = GetComponentSoundClassName ( ) ;
2023-07-27 19:43:47 -04:00
Builder - > Audition ( nullptr , AudioComponent , { } , bEnableLiveUpdates ) ;
2023-07-19 17:25:21 -04:00
const FName BuiltClassName = GetComponentSoundClassName ( ) ;
const bool bInitNameGenerated = InitClassName . IsNone ( ) & & ! BuiltClassName . IsNone ( ) ;
const bool bClassNameMaintained = InitClassName = = BuiltClassName ;
if ( bInitNameGenerated | | bClassNameMaintained )
{
return true ;
}
UE_LOG ( LogMetaSound , Error , TEXT ( " Latent test audition call resulted in generation of a new MetaSound class instead of re-using the existing class name " ) ) ;
2023-06-16 17:48:20 -04:00
}
return false ;
}
2021-09-08 12:59:26 -04:00
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER ( FAudioComponentRemoveFromRootLatentCommand , UAudioComponent * , AudioComponent ) ;
bool FAudioComponentRemoveFromRootLatentCommand : : Update ( )
{
if ( AudioComponent )
{
AudioComponent - > RemoveFromRoot ( ) ;
return true ;
}
return false ;
}
2023-08-07 13:38:36 -04:00
DEFINE_LATENT_AUTOMATION_COMMAND_THREE_PARAMETER ( FMetaSoundSourceBuilderRemoveNodesLatentCommand , FAutomationTestBase & , Test , UMetaSoundSourceBuilder * , Builder , FMetaSoundNodeHandle , Node ) ;
bool FMetaSoundSourceBuilderRemoveNodesLatentCommand : : Update ( )
{
if ( Builder )
{
EMetaSoundBuilderResult Result ;
Builder - > RemoveNode ( Node , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Failed to remove node from MetaSound graph " ) ;
}
return true ;
}
DEFINE_LATENT_AUTOMATION_COMMAND_FOUR_PARAMETER ( FMetaSoundSourceBuilderConnectNodesLatentCommand , FAutomationTestBase & , Test , UMetaSoundSourceBuilder * , Builder , FMetaSoundBuilderNodeOutputHandle , Output , FMetaSoundBuilderNodeInputHandle , Input ) ;
bool FMetaSoundSourceBuilderConnectNodesLatentCommand : : Update ( )
{
if ( Builder )
{
EMetaSoundBuilderResult Result ;
Builder - > ConnectNodes ( Output , Input , Result ) ;
Test . AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , TEXT ( " Failed to connect MetaSound nodes " ) ) ;
}
return true ;
}
2023-06-16 17:48:20 -04:00
// This test creates a MetaSound from the legacy controller document editing system and attempts to play it directly.
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceTest , " Audio.Metasound.PlayMetasoundSource " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2021-09-08 12:59:26 -04:00
bool FAudioMetasoundSourceTest : : RunTest ( const FString & Parameters )
{
2023-07-25 12:40:57 -04:00
using namespace EngineTestMetaSoundSourcePrivate ;
2021-09-08 12:59:26 -04:00
UMetaSoundSource * MetaSoundSource = NewObject < UMetaSoundSource > ( GetTransientPackage ( ) , FName ( * LexToString ( FGuid : : NewGuid ( ) ) ) ) ; ;
if ( ensure ( nullptr ! = MetaSoundSource ) )
{
2023-07-25 12:40:57 -04:00
MetaSoundSource - > SetDocument ( CreateMonoSourceDocument ( ) ) ;
2021-09-08 12:59:26 -04:00
2023-07-25 12:40:57 -04:00
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this , MetaSoundSource ) )
2021-09-08 12:59:26 -04:00
{
2023-07-25 12:40:57 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentPlayLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 2.f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
2021-09-08 12:59:26 -04:00
}
}
return true ;
}
2023-06-16 17:48:20 -04:00
// This test creates a MetaSound source from a SourceBuilder, adds a simple sine tone generator with a connected graph input frequency, and attempts to audition it.
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderTest , " Audio.Metasound.Builder.AuditionMetasoundSource " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-06-16 17:48:20 -04:00
bool FAudioMetasoundSourceBuilderTest : : RunTest ( const FString & Parameters )
{
2023-06-22 14:51:42 -04:00
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
2021-09-08 12:59:26 -04:00
2023-06-16 17:48:20 -04:00
FMetaSoundBuilderNodeInputHandle MonoOutNodeInput ;
2023-06-26 15:42:30 -04:00
UMetaSoundSourceBuilder & Builder = CreateMonoSourceSinGenBuilder ( * this , nullptr , & MonoOutNodeInput ) ;
2023-06-16 17:48:20 -04:00
Builder . AddToRoot ( ) ;
2021-09-08 12:59:26 -04:00
2023-07-25 12:40:57 -04:00
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this ) )
2023-06-16 17:48:20 -04:00
{
2023-07-25 12:40:57 -04:00
constexpr bool bEnableLiveUpdate = false ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 2.f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FBuilderRemoveFromRootLatentCommand ( & Builder ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
return true ;
2023-06-16 17:48:20 -04:00
}
2023-07-25 12:40:57 -04:00
return false ;
2023-06-16 17:48:20 -04:00
}
2023-07-19 17:25:21 -04:00
// This test creates a MetaSound source from a SourceBuilder, adds a simple sine tone generator with a connected graph input frequency, and attempts to change the frequency and audition it rapidly 100 times.
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderTestSpamAudition , " Audio.Metasound.Builder.SpamAuditionMetasoundSource " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-07-19 17:25:21 -04:00
bool FAudioMetasoundSourceBuilderTestSpamAudition : : RunTest ( const FString & Parameters )
{
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
FMetaSoundBuilderNodeInputHandle MonoOutNodeInput ;
FMetaSoundBuilderNodeInputHandle GenInputNodeFreq ;
UMetaSoundSourceBuilder & Builder = CreateMonoSourceSinGenBuilder ( * this , & GenInputNodeFreq , & MonoOutNodeInput ) ;
Builder . AddToRoot ( ) ;
2023-07-25 12:40:57 -04:00
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this ) )
2023-07-19 17:25:21 -04:00
{
2023-07-25 12:40:57 -04:00
constexpr bool bEnableLiveUpdate = false ;
constexpr int32 NumTrials = 100 ;
for ( int32 Index = 0 ; Index < NumTrials ; + + Index )
2023-07-19 17:25:21 -04:00
{
2023-07-25 12:40:57 -04:00
FMetasoundFrontendLiteral NewValue ;
NewValue . Set ( FMath : : RandRange ( 220.f , 2200.f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderSetLiteralLatentCommand ( * this , & Builder , GenInputNodeFreq , NewValue ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
2023-07-27 19:43:47 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.05f ) ) ;
2023-07-19 17:25:21 -04:00
}
2023-07-25 12:40:57 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FBuilderRemoveFromRootLatentCommand ( & Builder ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
return true ;
2023-07-19 17:25:21 -04:00
}
2023-07-25 12:40:57 -04:00
return false ;
2023-07-19 17:25:21 -04:00
}
2023-08-09 16:45:21 -04:00
// This test exercises auditioning multiple sources, both at the same time and attempting to audition live changes after stopping and restarting an audio component by:
// 1. Creates a MetaSound source from a SourceBuilder
// 2. Adds a simple sine tone generator with a connected graph input frequency
// 3. Auditions the builder via two AudioComponents
// 4. Sets the parameter input for frequency to a different value for the second component
// 5. Disconnects the parameter/graph input and sets the literal on the builder to a new frequency, which is observed on both components
// 6. Stops first the second component then the first.
// 7. Restarts audition of the original AudioComponent (which should continue after all the prior changes)
// 8. Swaps to use a tri tone generator
// 9. Stops original component, completing the test
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderLiveUpdateNode , " Audio.Metasound.Builder.LiveUpdateMultipleMetaSoundSources " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-06-16 17:48:20 -04:00
bool FAudioMetasoundSourceBuilderLiveUpdateNode : : RunTest ( const FString & Parameters )
{
2023-06-22 14:51:42 -04:00
using namespace EngineTestMetaSoundSourcePrivate ;
2023-06-16 17:48:20 -04:00
using namespace Metasound ;
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
2023-08-09 16:45:21 -04:00
FMetaSoundBuilderNodeInputHandle GenInputNodeFreq ;
2023-06-16 17:48:20 -04:00
FMetaSoundBuilderNodeInputHandle MonoOutNodeInput ;
2023-08-09 16:45:21 -04:00
UMetaSoundSourceBuilder & Builder = CreateMonoSourceSinGenBuilder ( * this , & GenInputNodeFreq , & MonoOutNodeInput , 440.f ) ;
2023-06-16 17:48:20 -04:00
Builder . AddToRoot ( ) ;
2023-07-25 12:40:57 -04:00
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this ) )
2023-06-16 17:48:20 -04:00
{
2023-07-25 12:40:57 -04:00
constexpr bool bEnableLiveUpdate = true ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
2023-08-09 16:45:21 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
// Send commands to more than one component. By setting param to 220.f on the second, listener can hear two
// operators function on separate runtime graphs/generators
if ( UAudioComponent * AudioComponent2 = CreateTestComponent ( * this ) )
{
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent2 , bEnableLiveUpdate ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
TArray < FAudioParameter > Params { FAudioParameter { " Frequency " , 220.0f } } ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceLatentSetParamsCommand ( AudioComponent2 , Params ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 2.f ) ) ;
// Set a literal to ensure live updates still update as expected (nothing should happen until the next step when the edge
// is disconnected, at which point we should hear 880Hz)
FMetasoundFrontendLiteral NewFreq ;
NewFreq . Set ( 880.f ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderSetLiteralLatentCommand ( * this , & Builder , GenInputNodeFreq , NewFreq ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.5f ) ) ;
// Remove the edge to the graph input, at which point listener should hear the literal value of 880 via both test components.
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderDisconnectInputLatentCommand ( * this , & Builder , GenInputNodeFreq ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 1.f ) ) ;
2023-08-09 17:40:47 -04:00
// Remove the second component, as the rest of the test is working with just the OG component.
2023-08-09 16:45:21 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent2 ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent2 ) ) ;
}
else
{
return false ;
}
// Stop and hear silence
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 1.f ) ) ;
// Restart audition to ensure it restarts as expected
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 1.f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
// Disconnect graph audio output from existing sinosc output and connect to added triosc
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderCreateAndConnectTriGeneratorNodeLatentCommand ( * this , & Builder , MonoOutNodeInput ) ) ;
2023-08-09 16:45:21 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 1.f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FBuilderRemoveFromRootLatentCommand ( & Builder ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
return true ;
2023-06-16 17:48:20 -04:00
}
2023-07-25 12:40:57 -04:00
return false ;
2023-06-16 17:48:20 -04:00
}
// This test creates a MetaSound source from a SourceBuilder, adds a simple sine tone generator with a connected graph input frequency, attempts to audition it,
// disconnects frequency input, sets the sinosc frequency literal value to a new value, and finally removes the literal value default to have it return to the
// class default.
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderLiveUpdateLiteral , " Audio.Metasound.Builder.LiveUpdateLiteralMetaSoundSource " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-06-16 17:48:20 -04:00
bool FAudioMetasoundSourceBuilderLiveUpdateLiteral : : RunTest ( const FString & Parameters )
{
2023-06-22 14:51:42 -04:00
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
2023-06-16 17:48:20 -04:00
FMetaSoundBuilderNodeInputHandle MonoOutNodeInput ;
FMetaSoundBuilderNodeInputHandle GenNodeFreqInput ;
2023-06-26 15:42:30 -04:00
UMetaSoundSourceBuilder & Builder = CreateMonoSourceSinGenBuilder ( * this , & GenNodeFreqInput , & MonoOutNodeInput , 220.f ) ;
2023-06-16 17:48:20 -04:00
Builder . AddToRoot ( ) ;
2023-07-25 12:40:57 -04:00
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this ) )
2023-06-16 17:48:20 -04:00
{
2023-07-25 12:40:57 -04:00
constexpr bool bEnableLiveUpdate = true ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.25f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
// Disconnects freq input node output from sinosc freq input. Initially was set to 220Hz above, and node's default is 440Hz,
// resulting in an octive pitch up.
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderDisconnectInputLatentCommand ( * this , & Builder , GenNodeFreqInput ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.25f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
// Sets literal value on the sinosc freq input to 880Hz, pitching an octive yet again from previous.
FName DataTypeName ;
FMetasoundFrontendLiteral NewValue = UMetaSoundBuilderSubsystem : : GetChecked ( ) . CreateFloatMetaSoundLiteral ( 880.f , DataTypeName ) ;
AddErrorIfFalse ( DataTypeName = = Metasound : : GetMetasoundDataTypeName < float > ( ) ,
" Setting MetaSound Float literal returns non-float DataTypeName. " ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderSetLiteralLatentCommand ( * this , & Builder , GenNodeFreqInput , NewValue ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.25f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
// Removes the literal value on the sinosc freq input set to 880Hz, reverting back to the class literal of 440Hz.
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderRemoveNodeDefaultLiteralLatentCommand ( * this , & Builder , GenNodeFreqInput ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.25f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.25f ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FBuilderRemoveFromRootLatentCommand ( & Builder ) ) ;
2023-06-16 17:48:20 -04:00
2023-07-25 12:40:57 -04:00
return true ;
2023-06-16 17:48:20 -04:00
}
2023-07-25 12:40:57 -04:00
return false ;
2023-06-16 17:48:20 -04:00
}
2023-07-18 15:24:34 -04:00
// This test creates a MetaSound source from a SourceBuilder, then adds and finally removes an interface using the builder API, and verifies it as well as its members were added to the document.
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderMutateInterface , " Audio.Metasound.Builder.MutateInterface " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-07-18 15:24:34 -04:00
bool FAudioMetasoundSourceBuilderMutateInterface : : RunTest ( const FString & Parameters )
{
using namespace Audio ;
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
using namespace Metasound : : Frontend ;
constexpr EMetaSoundOutputAudioFormat OutputFormat = EMetaSoundOutputAudioFormat : : Mono ;
constexpr bool bIsOneShot = false ;
FInitTestBuilderSourceOutput Output ;
UMetaSoundSourceBuilder & Builder = CreateSourceBuilder ( * this , EMetaSoundOutputAudioFormat : : Mono , bIsOneShot , Output ) ;
Builder . AddToRoot ( ) ;
EMetaSoundBuilderResult Result ;
// Test interface output mutation with oneshot interface
Builder . AddInterface ( SourceOneShotInterface : : GetVersion ( ) . Name , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Returned failed state when adding 'OneShot' Interface to MetaSound using AddInterface Builder API call " ) ;
Builder . FindGraphOutputNode ( SourceOneShotInterface : : Outputs : : OnFinished , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Failed to add 'OnFinished' output to MetaSound using AddInterface Builder API call " ) ;
bool bIsDeclared = Builder . InterfaceIsDeclared ( SourceOneShotInterface : : GetVersion ( ) . Name ) ;
AddErrorIfFalse ( bIsDeclared , " 'OneShot' Interface added but is not member of declaration list on MetaSound asset. " ) ;
Builder . RemoveInterface ( SourceOneShotInterface : : GetVersion ( ) . Name , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Returned failed state when removing 'OneShot' Interface from MetaSound using RemoveInterface Builder API call " ) ;
Builder . FindGraphOutputNode ( SourceOneShotInterface : : Outputs : : OnFinished , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Failed , " Failed to remove 'OnFinished' output to MetaSound using RemoveInterface Builder API call " ) ;
bIsDeclared = Builder . InterfaceIsDeclared ( SourceOneShotInterface : : GetVersion ( ) . Name ) ;
AddErrorIfFalse ( ! bIsDeclared , " 'OneShot' Interface removed but remains member of declaration list on MetaSound asset. " ) ;
// Test input mutation with attenuation interface
Builder . AddInterface ( AttenuationInterface : : Name , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Returned failed state when adding 'Attenuation' Interface to MetaSound using AddInterface Builder API call " ) ;
Builder . FindGraphInputNode ( AttenuationInterface : : Inputs : : Distance , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Failed to add 'Distance' input to MetaSound using AddInterface Builder API call " ) ;
bIsDeclared = Builder . InterfaceIsDeclared ( AttenuationInterface : : Name ) ;
AddErrorIfFalse ( bIsDeclared , " 'Attenuation' Interface added but is not member of declaration list on MetaSound asset. " ) ;
Builder . RemoveInterface ( AttenuationInterface : : Name , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Returned failed state when removing 'Attenuation' Interface from MetaSound using RemoveInterface Builder API call " ) ;
Builder . FindGraphInputNode ( AttenuationInterface : : Inputs : : Distance , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Failed , " Failed to remove 'Distance' input to MetaSound using RemoveInterface Builder API call " ) ;
bIsDeclared = Builder . InterfaceIsDeclared ( AttenuationInterface : : Name ) ;
AddErrorIfFalse ( ! bIsDeclared , " 'Attenuation' Interface removed but remains member of declaration list on MetaSound asset. " ) ;
return true ;
}
2023-08-07 13:38:36 -04:00
// This test creates a MetaSound source from a SourceBuilder, then adds and connects saw oscillator nodes setting their input freq to a new chromatic tone which cascades up, and finally removes all of the added nodes.
2023-09-11 17:33:43 -04:00
IMPLEMENT_SIMPLE_AUTOMATION_TEST ( FAudioMetasoundSourceBuilderAddRemoveNodes , " Audio.Metasound.Builder.AddRemoveNodes " , EAutomationTestFlags : : EditorContext | EAutomationTestFlags : : EngineFilter )
2023-08-07 13:38:36 -04:00
bool FAudioMetasoundSourceBuilderAddRemoveNodes : : RunTest ( const FString & Parameters )
{
using namespace Audio ;
using namespace EngineTestMetaSoundPatchBuilderPrivate ;
using namespace EngineTestMetaSoundSourcePrivate ;
using namespace Metasound : : Frontend ;
constexpr EMetaSoundOutputAudioFormat OutputFormat = EMetaSoundOutputAudioFormat : : Mono ;
constexpr bool bIsOneShot = false ;
FInitTestBuilderSourceOutput Output ;
UMetaSoundSourceBuilder & Builder = CreateSourceBuilder ( * this , EMetaSoundOutputAudioFormat : : Mono , bIsOneShot , Output ) ;
Builder . AddToRoot ( ) ;
EMetaSoundBuilderResult Result ;
if ( UAudioComponent * AudioComponent = CreateTestComponent ( * this ) )
{
constexpr bool bEnableLiveUpdate = true ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderAuditionLatentCommand ( & Builder , AudioComponent , bEnableLiveUpdate ) ) ;
const FName OscType = " Sine " ;
const TArray < float > ChromaticFreqs
{
293.66 ,
311.13 ,
329.63 ,
349.23 ,
369.99 ,
392.00 ,
415.30 ,
440.00
} ;
TArray < FMetaSoundNodeHandle > GenNodes ;
for ( int32 i = 0 ; i < 8 ; + + i )
{
2023-09-01 13:19:23 -04:00
FMetaSoundNodeHandle OscNode = Builder . AddNodeByClassName ( { " UE " , OscType , " Audio " } , Result , 1 ) ;
2023-08-07 13:38:36 -04:00
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Succeeded , " Failed to add osc node to graph " ) ;
if ( Result = = EMetaSoundBuilderResult : : Succeeded )
{
GenNodes . Add ( MoveTemp ( OscNode ) ) ;
}
}
for ( int32 i = 0 ; i < GenNodes . Num ( ) ; + + i )
{
FMetaSoundNodeHandle & OscNode = GenNodes [ i ] ;
EMetaSoundBuilderResult ConnectResult ;
const FMetaSoundBuilderNodeOutputHandle OscNodeAudioOutput = Builder . FindNodeOutputByName ( OscNode , " Audio " , ConnectResult ) ;
AddErrorIfFalse ( ConnectResult = = EMetaSoundBuilderResult : : Succeeded & & OscNodeAudioOutput . IsSet ( ) , TEXT ( " Failed to find oscillator node output 'Audio' " ) ) ;
FMetaSoundBuilderNodeInputHandle InputHandle = Builder . FindNodeInputByName ( OscNode , " Frequency " , ConnectResult ) ;
AddErrorIfFalse ( ConnectResult = = EMetaSoundBuilderResult : : Succeeded & & InputHandle . IsSet ( ) , TEXT ( " Failed to find oscillator node input 'Frequency' " ) ) ;
FMetasoundFrontendLiteral Literal ;
Literal . Set ( ChromaticFreqs [ i ] ) ;
Builder . SetNodeInputDefault ( InputHandle , Literal , ConnectResult ) ;
AddErrorIfFalse ( ConnectResult = = EMetaSoundBuilderResult : : Succeeded & & OscNodeAudioOutput . IsSet ( ) , TEXT ( " Failed to find oscillator node output 'Audio' " ) ) ;
Builder . FindGraphOutputNode ( SourceOneShotInterface : : Outputs : : OnFinished , Result ) ;
AddErrorIfFalse ( Result = = EMetaSoundBuilderResult : : Failed , " Failed to remove 'OnFinished' output to MetaSound using RemoveInterface Builder API call " ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderConnectNodesLatentCommand ( * this , & Builder , OscNodeAudioOutput , Output . AudioOutNodeInputs . Last ( ) ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.125f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FMetaSoundSourceBuilderRemoveNodesLatentCommand ( * this , & Builder , GenNodes [ i ] ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.125f ) ) ;
}
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 1.f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentStopLatentCommand ( AudioComponent ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FEngineWaitLatentCommand ( 0.1f ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FBuilderRemoveFromRootLatentCommand ( & Builder ) ) ;
ADD_LATENT_AUTOMATION_COMMAND ( FAudioComponentRemoveFromRootLatentCommand ( AudioComponent ) ) ;
}
return true ;
}
2023-06-16 17:48:20 -04:00
# endif // WITH_DEV_AUTOMATION_TESTS