2021-02-16 20:07:50 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "Internationalization/Text.h"
2021-03-25 00:13:33 -04:00
# include "MetasoundFacade.h"
2021-02-16 20:07:50 -04:00
# include "MetasoundExecutableOperator.h"
# include "MetasoundNodeRegistrationMacro.h"
# include "MetasoundPrimitives.h"
# include "MetasoundStandardNodesNames.h"
2021-04-01 18:38:40 -04:00
# include "MetasoundStandardNodesCategories.h"
2021-02-16 20:07:50 -04:00
# include "DSP/Dsp.h"
2021-03-25 00:13:33 -04:00
# include "MetasoundParamHelper.h"
2021-02-16 20:07:50 -04:00
2021-04-07 02:57:54 -04:00
# define LOCTEXT_NAMESPACE "MetasoundStandardNodes_MidiToFreqNode"
2021-02-16 20:07:50 -04:00
namespace Metasound
{
2021-03-25 00:13:33 -04:00
namespace MidiToFrequencyVertexNames
2021-03-18 08:38:58 -04:00
{
2021-03-25 00:13:33 -04:00
METASOUND_PARAM ( InputMidi , " MIDI In " , " A value representing a MIDI note value. " ) ;
METASOUND_PARAM ( OutputFreq , " Out Frequency " , " Output frequency value in hertz that corresponds to the input Midi note value. " ) ;
2021-03-18 08:38:58 -04:00
}
2021-02-16 20:07:50 -04:00
2021-03-25 00:13:33 -04:00
namespace MidiToFrequencyPrivate
{
template < typename ValueType >
struct TMidiToFreqNodeSpecialization
{
} ;
template < >
struct TMidiToFreqNodeSpecialization < int32 >
{
static int32 GetFreqValue ( int32 InMidi )
{
return Audio : : GetFrequencyFromMidi ( FMath : : Clamp ( InMidi , 0 , 127 ) ) ;
}
static bool IsValueEqual ( int32 InValueA , int32 InValueB )
{
return InValueA = = InValueB ;
}
} ;
template < >
struct TMidiToFreqNodeSpecialization < float >
{
static float GetFreqValue ( float InMidi )
{
return Audio : : GetFrequencyFromMidi ( FMath : : Clamp ( InMidi , 0.0f , 127.0f ) ) ;
}
static bool IsValueEqual ( float InValueA , float InValueB )
{
return FMath : : IsNearlyEqual ( InValueA , InValueB ) ;
}
} ;
}
template < typename ValueType >
class TMidiToFreqOperator : public TExecutableOperator < TMidiToFreqOperator < ValueType > >
2021-02-16 20:07:50 -04:00
{
public :
static const FNodeClassMetadata & GetNodeInfo ( ) ;
static const FVertexInterface & GetVertexInterface ( ) ;
static TUniquePtr < IOperator > CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors ) ;
2021-03-25 00:13:33 -04:00
TMidiToFreqOperator ( const FOperatorSettings & InSettings , const TDataReadReference < ValueType > & InMidiNote ) ;
2021-02-16 20:07:50 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override ;
virtual FDataReferenceCollection GetOutputs ( ) const override ;
void Execute ( ) ;
private :
2021-03-25 00:13:33 -04:00
// The input Midi value
TDataReadReference < ValueType > MidiNote ;
2021-02-16 20:07:50 -04:00
// The output frequency
FFloatWriteRef FreqOutput ;
2021-03-25 00:13:33 -04:00
// Cached Midi note value. Used to catch if the value changes to recompute freq output.
ValueType PrevMidiNote ;
2021-02-16 20:07:50 -04:00
} ;
2021-03-25 00:13:33 -04:00
template < typename ValueType >
TMidiToFreqOperator < ValueType > : : TMidiToFreqOperator ( const FOperatorSettings & InSettings , const TDataReadReference < ValueType > & InMidiNote )
: MidiNote ( InMidiNote )
, FreqOutput ( FFloatWriteRef : : CreateNew ( Audio : : GetFrequencyFromMidi ( * InMidiNote ) ) )
, PrevMidiNote ( * InMidiNote )
2021-02-16 20:07:50 -04:00
{
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
FDataReferenceCollection TMidiToFreqOperator < ValueType > : : GetInputs ( ) const
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
using namespace MidiToFrequencyVertexNames ;
2021-03-18 08:38:58 -04:00
2021-02-16 20:07:50 -04:00
FDataReferenceCollection InputDataReferences ;
2021-03-25 00:13:33 -04:00
InputDataReferences . AddDataReadReference ( METASOUND_GET_PARAM_NAME ( InputMidi ) , MidiNote ) ;
2021-02-16 20:07:50 -04:00
return InputDataReferences ;
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
FDataReferenceCollection TMidiToFreqOperator < ValueType > : : GetOutputs ( ) const
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
using namespace MidiToFrequencyVertexNames ;
2021-03-18 08:38:58 -04:00
2021-02-16 20:07:50 -04:00
FDataReferenceCollection OutputDataReferences ;
2021-03-25 00:13:33 -04:00
OutputDataReferences . AddDataReadReference ( METASOUND_GET_PARAM_NAME ( OutputFreq ) , FreqOutput ) ;
2021-02-16 20:07:50 -04:00
return OutputDataReferences ;
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
void TMidiToFreqOperator < ValueType > : : Execute ( )
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
using namespace MidiToFrequencyPrivate ;
2021-02-16 20:07:50 -04:00
2021-03-25 00:13:33 -04:00
// Only do anything if the Midi note changes
if ( ! TMidiToFreqNodeSpecialization < ValueType > : : IsValueEqual ( * MidiNote , PrevMidiNote ) )
{
PrevMidiNote = * MidiNote ;
* FreqOutput = TMidiToFreqNodeSpecialization < ValueType > : : GetFreqValue ( PrevMidiNote ) ;
2021-02-16 20:07:50 -04:00
}
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
const FVertexInterface & TMidiToFreqOperator < ValueType > : : GetVertexInterface ( )
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
using namespace MidiToFrequencyVertexNames ;
2021-03-18 08:38:58 -04:00
2021-02-16 20:07:50 -04:00
static const FVertexInterface Interface (
FInputVertexInterface (
2021-03-25 00:13:33 -04:00
TInputDataVertexModel < ValueType > ( METASOUND_GET_PARAM_NAME_AND_TT ( InputMidi ) , ( ValueType ) 60.0f )
2021-02-16 20:07:50 -04:00
) ,
FOutputVertexInterface (
2021-03-25 00:13:33 -04:00
TOutputDataVertexModel < float > ( METASOUND_GET_PARAM_NAME_AND_TT ( OutputFreq ) )
2021-02-16 20:07:50 -04:00
)
) ;
return Interface ;
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
const FNodeClassMetadata & TMidiToFreqOperator < ValueType > : : GetNodeInfo ( )
2021-02-16 20:07:50 -04:00
{
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
{
2021-05-10 16:56:43 -04:00
const FName DataTypeName = GetMetasoundDataTypeName < ValueType > ( ) ;
const FName OperatorName = TEXT ( " MIDI To Frequency " ) ;
const FText NodeDisplayName = FText : : Format ( LOCTEXT ( " RandomGetArrayOpDisplayNamePattern " , " MIDI To Frequency ({0}) " ) , GetMetasoundDataTypeDisplayText < ValueType > ( ) ) ;
const FText NodeDescription = LOCTEXT ( " Metasound_MidiToFreqNodeDescription " , " Converts a Midi note value to a frequency (hz) value. " ) ;
2021-03-25 00:13:33 -04:00
2021-02-16 20:07:50 -04:00
FNodeClassMetadata Info ;
2021-08-09 15:13:40 -04:00
Info . ClassName = { StandardNodes : : Namespace , OperatorName , DataTypeName } ;
2021-02-16 20:07:50 -04:00
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
2021-03-25 00:13:33 -04:00
Info . DisplayName = NodeDisplayName ;
Info . Description = NodeDescription ;
2021-02-16 20:07:50 -04:00
Info . Author = PluginAuthor ;
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = GetVertexInterface ( ) ;
2021-08-09 15:13:40 -04:00
Info . CategoryHierarchy . Emplace ( NodeCategories : : Music ) ;
2021-02-16 20:07:50 -04:00
return Info ;
} ;
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
return Info ;
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
TUniquePtr < IOperator > TMidiToFreqOperator < ValueType > : : CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors )
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
using namespace MidiToFrequencyVertexNames ;
2021-03-18 08:38:58 -04:00
2021-02-16 20:07:50 -04:00
const FDataReferenceCollection & InputCollection = InParams . InputDataReferences ;
const FInputVertexInterface & InputInterface = GetVertexInterface ( ) . GetInputInterface ( ) ;
2021-03-25 00:13:33 -04:00
TDataReadReference < ValueType > InMidiNote = InputCollection . GetDataReadReferenceOrConstructWithVertexDefault < ValueType > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputMidi ) , InParams . OperatorSettings ) ;
2021-02-16 20:07:50 -04:00
2021-03-25 00:13:33 -04:00
return MakeUnique < TMidiToFreqOperator > ( InParams . OperatorSettings , InMidiNote ) ;
2021-02-16 20:07:50 -04:00
}
2021-03-25 00:13:33 -04:00
template < typename ValueType >
class METASOUNDSTANDARDNODES_API TMidiToFreqNode : public FNodeFacade
2021-02-16 20:07:50 -04:00
{
2021-03-25 00:13:33 -04:00
public :
/**
* Constructor used by the Metasound Frontend .
*/
TMidiToFreqNode ( const FNodeInitData & InitData )
: FNodeFacade ( InitData . InstanceName , InitData . InstanceID , TFacadeOperatorClass < TMidiToFreqOperator < ValueType > > ( ) )
{
2021-02-16 20:07:50 -04:00
2021-03-25 00:13:33 -04:00
}
} ;
using FMidiToFreqNodeInt32 = TMidiToFreqNode < int32 > ;
METASOUND_REGISTER_NODE ( FMidiToFreqNodeInt32 )
using FMidiToFreqNodeFloat = TMidiToFreqNode < float > ;
METASOUND_REGISTER_NODE ( FMidiToFreqNodeFloat )
2021-02-16 20:07:50 -04:00
}
# undef LOCTEXT_NAMESPACE