2021-06-10 19:39:27 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "DSP/BufferVectorOperations.h"
# include "DSP/Flanger.h"
2023-08-02 14:38:51 -04:00
# include "Internationalization/Text.h"
# include "MetasoundExecutableOperator.h"
# include "MetasoundFacade.h"
# include "MetasoundNodeRegistrationMacro.h"
2021-06-10 19:39:27 -04:00
# include "MetasoundParamHelper.h"
2023-08-02 14:38:51 -04:00
# include "MetasoundPrimitives.h"
# include "MetasoundStandardNodesCategories.h"
# include "MetasoundStandardNodesNames.h"
2021-06-10 19:39:27 -04:00
# define LOCTEXT_NAMESPACE "MetasoundStandardNodes_FlangerNode"
2023-08-02 14:38:51 -04:00
2021-06-10 19:39:27 -04:00
namespace Metasound
{
namespace FlangerVertexNames
{
METASOUND_PARAM ( InputAudio , " In Audio " , " The audio input. " ) ;
METASOUND_PARAM ( InputModulationRate , " Modulation Rate " , " The LFO frequency (rate) that varies the delay time, in Hz. Clamped at blockrate. " ) ;
METASOUND_PARAM ( InputModulationDepth , " Modulation Depth " , " The LFO amplitude (strength) that scales the delay time. " ) ;
METASOUND_PARAM ( InputCenterDelay , " Center Delay " , " The center delay amount (in milliseconds). " ) ;
METASOUND_PARAM ( InputMixLevel , " Mix Level " , " Balance between original and delayed signal (Should be between 0 and 1.0; 0.5 is equal amounts of each and > 0.5 is more delayed signal than non-delayed signal). " ) ;
METASOUND_PARAM ( OutputAudio , " Out Audio " , " Output audio with flanger effect applied. " ) ;
}
class FFlangerOperator : public TExecutableOperator < FFlangerOperator >
{
public :
static const FNodeClassMetadata & GetNodeInfo ( )
{
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
{
const FName OperatorName = TEXT ( " Flanger " ) ;
2022-02-10 18:36:47 -05:00
const FText NodeDisplayName = METASOUND_LOCTEXT ( " Metasound_FlangerNodeDisplayName " , " Flanger " ) ;
const FText NodeDescription = METASOUND_LOCTEXT ( " Metasound_FlangerNodeDescription " , " Applies a flanger effect to input audio. " ) ;
2021-06-10 19:39:27 -04:00
FNodeClassMetadata Info ;
2021-08-09 15:08:37 -04:00
Info . ClassName = { StandardNodes : : Namespace , OperatorName , TEXT ( " " ) } ;
2021-06-10 19:39:27 -04:00
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
Info . DisplayName = NodeDisplayName ;
Info . Description = NodeDescription ;
Info . Author = PluginAuthor ;
2023-08-02 14:38:51 -04:00
Info . CategoryHierarchy = { NodeCategories : : Filters } ;
2021-06-10 19:39:27 -04:00
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = GetVertexInterface ( ) ;
return Info ;
} ;
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
return Info ;
}
static const FVertexInterface & GetVertexInterface ( )
{
using namespace FlangerVertexNames ;
static const FVertexInterface Interface (
FInputVertexInterface (
2022-03-31 16:49:59 -04:00
TInputDataVertex < FAudioBuffer > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputAudio ) ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputModulationRate ) , 0.5f ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputModulationDepth ) , 0.5f ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputCenterDelay ) , 0.5f ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputMixLevel ) , 0.5f )
2021-06-10 19:39:27 -04:00
) ,
FOutputVertexInterface (
2022-03-31 16:49:59 -04:00
TOutputDataVertex < FAudioBuffer > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( OutputAudio ) )
2021-06-10 19:39:27 -04:00
)
) ;
return Interface ;
}
static TUniquePtr < IOperator > CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors )
{
using namespace FlangerVertexNames ;
const FDataReferenceCollection & InputCollection = InParams . InputDataReferences ;
const FInputVertexInterface & InputInterface = GetVertexInterface ( ) . GetInputInterface ( ) ;
FAudioBufferReadRef AudioInput = InputCollection . GetDataReadReferenceOrConstruct < FAudioBuffer > ( METASOUND_GET_PARAM_NAME ( InputAudio ) , InParams . OperatorSettings ) ;
FFloatReadRef ModulationRate = InParams . InputDataReferences . GetDataReadReferenceOrConstructWithVertexDefault < float > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputModulationRate ) , InParams . OperatorSettings ) ;
FFloatReadRef ModulationDepth = InParams . InputDataReferences . GetDataReadReferenceOrConstructWithVertexDefault < float > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputModulationDepth ) , InParams . OperatorSettings ) ;
FFloatReadRef CenterDelay = InParams . InputDataReferences . GetDataReadReferenceOrConstructWithVertexDefault < float > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputCenterDelay ) , InParams . OperatorSettings ) ;
FFloatReadRef MixLevel = InParams . InputDataReferences . GetDataReadReferenceOrConstructWithVertexDefault < float > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputMixLevel ) , InParams . OperatorSettings ) ;
2023-03-02 14:40:35 -05:00
return MakeUnique < FFlangerOperator > ( InParams , AudioInput , ModulationRate , ModulationDepth , CenterDelay , MixLevel ) ;
2021-06-10 19:39:27 -04:00
}
2023-03-02 14:40:35 -05:00
FFlangerOperator ( const FCreateOperatorParams & InParams ,
2021-06-10 19:39:27 -04:00
const FAudioBufferReadRef & InAudioInput ,
const FFloatReadRef & InputModulationRate ,
const FFloatReadRef & InputModulationDepth ,
const FFloatReadRef & InputCenterDelay ,
const FFloatReadRef & InMixLevel )
: AudioIn ( InAudioInput )
, ModulationRate ( InputModulationRate )
, ModulationDepth ( InputModulationDepth )
, CenterDelay ( InputCenterDelay )
, MixLevel ( InMixLevel )
2023-03-02 14:40:35 -05:00
, AudioOut ( FAudioBufferWriteRef : : CreateNew ( InParams . OperatorSettings ) )
2021-06-10 19:39:27 -04:00
, Flanger ( )
{
2023-03-02 14:40:35 -05:00
Reset ( InParams ) ;
2021-06-10 19:39:27 -04:00
}
2023-05-22 13:28:27 -04:00
virtual void BindInputs ( FInputVertexInterfaceData & InOutVertexData ) override
2021-06-10 19:39:27 -04:00
{
using namespace FlangerVertexNames ;
2023-05-22 13:28:27 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputAudio ) , AudioIn ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputModulationRate ) , ModulationRate ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputModulationDepth ) , ModulationDepth ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputCenterDelay ) , CenterDelay ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputMixLevel ) , MixLevel ) ;
2021-06-10 19:39:27 -04:00
}
2023-05-22 13:28:27 -04:00
virtual void BindOutputs ( FOutputVertexInterfaceData & InOutVertexData ) override
2021-06-10 19:39:27 -04:00
{
using namespace FlangerVertexNames ;
2023-05-22 13:28:27 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( OutputAudio ) , AudioOut ) ;
}
2021-06-10 19:39:27 -04:00
2023-05-22 13:28:27 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override
{
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
}
virtual FDataReferenceCollection GetOutputs ( ) const override
{
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
2021-06-10 19:39:27 -04:00
}
2023-03-02 14:40:35 -05:00
void Reset ( const IOperator : : FResetParams & InParams )
{
AudioOut - > Zero ( ) ;
Flanger . Init ( InParams . OperatorSettings . GetSampleRate ( ) ) ;
}
2021-06-10 19:39:27 -04:00
void Execute ( )
{
// Update flanger parameters if necessary
Flanger . SetModulationRate ( * ModulationRate ) ;
Flanger . SetCenterDelay ( * CenterDelay ) ;
Flanger . SetModulationDepth ( * ModulationDepth ) ;
Flanger . SetMixLevel ( * MixLevel ) ;
int32 NumFrames = AudioIn - > Num ( ) ;
2023-03-02 14:40:35 -05:00
Flanger . ProcessAudio ( * AudioIn , NumFrames , * AudioOut ) ;
2021-06-10 19:39:27 -04:00
}
private :
// The input audio buffer
FAudioBufferReadRef AudioIn ;
// LFO parameters
FFloatReadRef ModulationRate ;
FFloatReadRef ModulationDepth ;
FFloatReadRef CenterDelay ;
// Balance between original and delayed signal
// (Should be between 0 and 1.0;
// 0.5 is equal amounts of each and
// > 0.5 is more delayed signal than non-delayed signal)
FFloatReadRef MixLevel ;
// Audio output
FAudioBufferWriteRef AudioOut ;
// Flanger DSP object
Audio : : FFlanger Flanger ;
} ;
class METASOUNDSTANDARDNODES_API FFlangerNode : public FNodeFacade
{
public :
/**
* Constructor used by the Metasound Frontend .
*/
FFlangerNode ( const FNodeInitData & InitData )
: FNodeFacade ( InitData . InstanceName , InitData . InstanceID , TFacadeOperatorClass < FFlangerOperator > ( ) )
{
}
} ;
METASOUND_REGISTER_NODE ( FFlangerNode )
}
# undef LOCTEXT_NAMESPACE