2022-05-31 17:50:00 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "Internationalization/Text.h"
# include "MetasoundExecutableOperator.h"
# include "MetasoundNodeRegistrationMacro.h"
# include "MetasoundParamHelper.h"
# include "MetasoundPrimitives.h"
# include "MetasoundStandardNodesNames.h"
# include "MetasoundAudioBuffer.h"
# include "DSP/TapDelayPitchShifter.h"
# include "MetasoundStandardNodesCategories.h"
# include "MetasoundFacade.h"
# define LOCTEXT_NAMESPACE "MetasoundStandardNodesDopplerPitchShift"
namespace Metasound
{
namespace DopplerPitchShift
{
METASOUND_PARAM ( InParamAudioInput , " In " , " Input audio buffer. " )
METASOUND_PARAM ( InParamPitchShift , " Pitch Shift " , " The amount to pitch shift the audio signal, in semitones. " )
METASOUND_PARAM ( InParamDelayLength , " Delay Length " , " The delay length of the internal delay buffer in milliseconds (10 ms to 100 ms). Changing this can reduce artifacts in certain pitch shift regions. " )
METASOUND_PARAM ( OutParamAudio , " Out " , " Output audio buffer. " )
}
class FDopplerPitchShiftOperator : public TExecutableOperator < FDopplerPitchShiftOperator >
{
public :
static const FNodeClassMetadata & GetNodeInfo ( ) ;
static const FVertexInterface & GetVertexInterface ( ) ;
2023-10-13 19:29:51 -04:00
static TUniquePtr < IOperator > CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults ) ;
2022-05-31 17:50:00 -04:00
2023-10-13 19:29:51 -04:00
FDopplerPitchShiftOperator ( const FBuildOperatorParams & InParams , const FAudioBufferReadRef & InAudioInput , const FFloatReadRef & InPitchShift , const FFloatReadRef & InDelayLength ) ;
2022-05-31 17:50:00 -04:00
2023-06-27 19:07:52 -04:00
virtual void BindInputs ( FInputVertexInterfaceData & InOutVertexData ) override ;
virtual void BindOutputs ( FOutputVertexInterfaceData & InOutVertexData ) override ;
2022-05-31 17:50:00 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override ;
virtual FDataReferenceCollection GetOutputs ( ) const override ;
2023-03-02 14:40:35 -05:00
void Reset ( const IOperator : : FResetParams & InParams ) ;
2022-05-31 17:50:00 -04:00
void Execute ( ) ;
private :
FAudioBufferReadRef AudioInput ;
FFloatReadRef PitchShift ;
FFloatReadRef DelayLength ;
FAudioBufferWriteRef AudioOutput ;
Audio : : FDelay DelayBuffer ;
Audio : : FTapDelayPitchShifter DelayPitchShifter ;
} ;
2023-10-13 19:29:51 -04:00
FDopplerPitchShiftOperator : : FDopplerPitchShiftOperator ( const FBuildOperatorParams & InParams ,
2022-05-31 17:50:00 -04:00
const FAudioBufferReadRef & InAudioInput ,
const FFloatReadRef & InPitchShift ,
const FFloatReadRef & InDelayLength )
: AudioInput ( InAudioInput )
, PitchShift ( InPitchShift )
, DelayLength ( InDelayLength )
2023-03-02 14:40:35 -05:00
, AudioOutput ( FAudioBufferWriteRef : : CreateNew ( InParams . OperatorSettings ) )
2022-05-31 17:50:00 -04:00
{
2023-03-02 14:40:35 -05:00
Reset ( InParams ) ;
2022-05-31 17:50:00 -04:00
}
2023-06-27 19:07:52 -04:00
void FDopplerPitchShiftOperator : : BindInputs ( FInputVertexInterfaceData & InOutVertexData )
2022-05-31 17:50:00 -04:00
{
using namespace DopplerPitchShift ;
2023-06-27 19:07:52 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InParamAudioInput ) , AudioInput ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InParamPitchShift ) , PitchShift ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InParamDelayLength ) , DelayLength ) ;
}
2022-05-31 17:50:00 -04:00
2023-06-27 19:07:52 -04:00
void FDopplerPitchShiftOperator : : BindOutputs ( FOutputVertexInterfaceData & InOutVertexData )
{
using namespace DopplerPitchShift ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( OutParamAudio ) , AudioOutput ) ;
2023-05-22 13:28:27 -04:00
}
FDataReferenceCollection FDopplerPitchShiftOperator : : GetInputs ( ) const
{
// 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 { } ;
2022-05-31 17:50:00 -04:00
}
FDataReferenceCollection FDopplerPitchShiftOperator : : GetOutputs ( ) const
{
2023-05-22 13:28:27 -04:00
// 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 { } ;
2022-05-31 17:50:00 -04:00
}
2023-03-02 14:40:35 -05:00
void FDopplerPitchShiftOperator : : Reset ( const IOperator : : FResetParams & InParams )
{
AudioOutput - > Zero ( ) ;
DelayBuffer . Init ( InParams . OperatorSettings . GetSampleRate ( ) , 0.001f * Audio : : FTapDelayPitchShifter : : MaxDelayLength ) ;
DelayPitchShifter . Init ( InParams . OperatorSettings . GetSampleRate ( ) , * PitchShift , * DelayLength ) ;
}
2022-05-31 17:50:00 -04:00
void FDopplerPitchShiftOperator : : Execute ( )
{
DelayPitchShifter . SetDelayLength ( * DelayLength ) ;
DelayPitchShifter . SetPitchShift ( * PitchShift ) ;
DelayPitchShifter . ProcessAudio ( DelayBuffer , AudioInput - > GetData ( ) , AudioInput - > Num ( ) , AudioOutput - > GetData ( ) ) ;
}
const FVertexInterface & FDopplerPitchShiftOperator : : GetVertexInterface ( )
{
using namespace DopplerPitchShift ;
static const FVertexInterface Interface (
FInputVertexInterface (
TInputDataVertex < FAudioBuffer > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InParamAudioInput ) ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InParamPitchShift ) , 0.0f ) ,
TInputDataVertex < float > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InParamDelayLength ) , 30.0f )
) ,
FOutputVertexInterface (
TOutputDataVertex < FAudioBuffer > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( OutParamAudio ) )
)
) ;
return Interface ;
}
const FNodeClassMetadata & FDopplerPitchShiftOperator : : GetNodeInfo ( )
{
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
{
FNodeClassMetadata Info ;
Info . ClassName = { StandardNodes : : Namespace , " Delay Pitch Shift " , StandardNodes : : AudioVariant } ;
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
2022-05-31 19:00:48 -04:00
Info . DisplayName = METASOUND_LOCTEXT ( " DopperDelayPitchShift_DisplayName " , " Delay Pitch Shift " ) ;
Info . Description = METASOUND_LOCTEXT ( " DopperDelayPitchShift_Description " , " Pitch shifts the audio buffer using a delay-based doppler-shift method. " ) ;
2022-05-31 17:50:00 -04:00
Info . Author = PluginAuthor ;
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = GetVertexInterface ( ) ;
Info . CategoryHierarchy . Emplace ( NodeCategories : : Delays ) ;
return Info ;
} ;
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
return Info ;
}
2023-10-13 19:29:51 -04:00
TUniquePtr < IOperator > FDopplerPitchShiftOperator : : CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults )
2022-05-31 17:50:00 -04:00
{
using namespace DopplerPitchShift ;
2023-10-13 19:29:51 -04:00
const FInputVertexInterfaceData & InputData = InParams . InputData ;
2022-05-31 17:50:00 -04:00
2023-10-13 19:29:51 -04:00
FAudioBufferReadRef AudioIn = InputData . GetOrConstructDataReadReference < FAudioBuffer > ( METASOUND_GET_PARAM_NAME ( InParamAudioInput ) , InParams . OperatorSettings ) ;
FFloatReadRef PitchShift = InputData . GetOrCreateDefaultDataReadReference < float > ( METASOUND_GET_PARAM_NAME ( InParamPitchShift ) , InParams . OperatorSettings ) ;
FFloatReadRef DelayLength = InputData . GetOrCreateDefaultDataReadReference < float > ( METASOUND_GET_PARAM_NAME ( InParamDelayLength ) , InParams . OperatorSettings ) ;
2022-05-31 17:50:00 -04:00
2023-03-02 14:40:35 -05:00
return MakeUnique < FDopplerPitchShiftOperator > ( InParams , AudioIn , PitchShift , DelayLength ) ;
2022-05-31 17:50:00 -04:00
}
class FDopperPitchShiftNode : public FNodeFacade
{
public :
FDopperPitchShiftNode ( const FNodeInitData & InitData )
: FNodeFacade ( InitData . InstanceName , InitData . InstanceID , TFacadeOperatorClass < FDopplerPitchShiftOperator > ( ) )
{
}
} ;
METASOUND_REGISTER_NODE ( FDopperPitchShiftNode )
}
# undef LOCTEXT_NAMESPACE