2021-06-21 21:39:37 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "Internationalization/Text.h"
|
|
|
|
|
#include "MetasoundFacade.h"
|
|
|
|
|
#include "MetasoundExecutableOperator.h"
|
|
|
|
|
#include "MetasoundNodeRegistrationMacro.h"
|
|
|
|
|
#include "MetasoundPrimitives.h"
|
|
|
|
|
#include "MetasoundStandardNodesNames.h"
|
|
|
|
|
#include "MetasoundStandardNodesCategories.h"
|
|
|
|
|
#include "DSP/Dsp.h"
|
|
|
|
|
#include "MetasoundParamHelper.h"
|
|
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MetasoundStandardNodes_LinearToLogFreqNode"
|
|
|
|
|
|
|
|
|
|
namespace Metasound
|
|
|
|
|
{
|
|
|
|
|
namespace LinearToLogFrequencyVertexNames
|
|
|
|
|
{
|
|
|
|
|
METASOUND_PARAM(InputValue, "Value", "Linear input value to map to log frequency output. Input and output are clamped to specified domain and range.");
|
|
|
|
|
METASOUND_PARAM(InputDomainMin, "Min Domain", "Min domain for the input value.");
|
|
|
|
|
METASOUND_PARAM(InputDomainMax, "Max Domain", "Max domain for the input value.");
|
2021-09-15 15:01:04 -04:00
|
|
|
METASOUND_PARAM(InputRangeMin, "Min Range", "Min positive range for the output frequency (Hz) value.");
|
|
|
|
|
METASOUND_PARAM(InputRangeMax, "Max Range", "Max positive range for the output frequency (Hz) value.");
|
2021-06-21 21:39:37 -04:00
|
|
|
METASOUND_PARAM(OutputFreq, "Frequency", "Output frequency value in hertz that is the log frequency of the input value.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class FLinearToLogFrequencyOperator : public TExecutableOperator<FLinearToLogFrequencyOperator>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
static const FNodeClassMetadata& GetNodeInfo()
|
|
|
|
|
{
|
|
|
|
|
auto InitNodeInfo = []() -> FNodeClassMetadata
|
|
|
|
|
{
|
|
|
|
|
FName OperatorName = TEXT("Linear To Log Frequency");
|
2022-02-10 18:36:47 -05:00
|
|
|
FText NodeDisplayName = METASOUND_LOCTEXT("LinearToLogFrequencyName", "Linear To Log Frequency");
|
|
|
|
|
const FText NodeDescription = METASOUND_LOCTEXT("LinearToLogFrequencyDescription", "Converts a linear space input value to log-frequency space.");
|
2021-06-21 21:39:37 -04:00
|
|
|
|
|
|
|
|
FNodeClassMetadata Info;
|
2021-08-09 15:08:37 -04:00
|
|
|
Info.ClassName = { StandardNodes::Namespace, OperatorName, TEXT("") };
|
2021-06-21 21:39:37 -04:00
|
|
|
Info.MajorVersion = 1;
|
|
|
|
|
Info.MinorVersion = 0;
|
|
|
|
|
Info.DisplayName = NodeDisplayName;
|
|
|
|
|
Info.Description = NodeDescription;
|
|
|
|
|
Info.Author = PluginAuthor;
|
|
|
|
|
Info.PromptIfMissing = PluginNodeMissingPrompt;
|
|
|
|
|
Info.DefaultInterface = GetVertexInterface();
|
2021-09-15 15:01:04 -04:00
|
|
|
Info.CategoryHierarchy.Emplace(NodeCategories::Math);
|
2022-08-17 16:42:56 -04:00
|
|
|
Info.Keywords.Add(METASOUND_LOCTEXT("LinearToLogPitchKeyword", "Pitch"));
|
2021-06-21 21:39:37 -04:00
|
|
|
|
|
|
|
|
return Info;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const FNodeClassMetadata Info = InitNodeInfo();
|
|
|
|
|
|
|
|
|
|
return Info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
|
|
|
{
|
|
|
|
|
using namespace LinearToLogFrequencyVertexNames;
|
|
|
|
|
|
|
|
|
|
static const FVertexInterface Interface(
|
|
|
|
|
FInputVertexInterface(
|
2022-03-31 16:49:59 -04:00
|
|
|
TInputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputValue), 0.0f),
|
|
|
|
|
TInputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputDomainMin), 0.0f),
|
|
|
|
|
TInputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputDomainMax), 1.0f),
|
|
|
|
|
TInputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputRangeMin), 20.0f),
|
|
|
|
|
TInputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputRangeMax), 20000.0f)
|
2021-06-21 21:39:37 -04:00
|
|
|
),
|
|
|
|
|
FOutputVertexInterface(
|
2022-03-31 16:49:59 -04:00
|
|
|
TOutputDataVertex<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(OutputFreq))
|
2021-06-21 21:39:37 -04:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return Interface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static TUniquePtr<IOperator> CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors)
|
|
|
|
|
{
|
|
|
|
|
using namespace LinearToLogFrequencyVertexNames;
|
|
|
|
|
|
|
|
|
|
const FDataReferenceCollection& InputCollection = InParams.InputDataReferences;
|
|
|
|
|
const FInputVertexInterface& InputInterface = GetVertexInterface().GetInputInterface();
|
|
|
|
|
|
|
|
|
|
TDataReadReference<float> InValue = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputValue), InParams.OperatorSettings);
|
|
|
|
|
TDataReadReference<float> InDomainMin = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputDomainMin), InParams.OperatorSettings);
|
|
|
|
|
TDataReadReference<float> InDomainMax = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputDomainMax), InParams.OperatorSettings);
|
|
|
|
|
TDataReadReference<float> InRangeMin = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputRangeMin), InParams.OperatorSettings);
|
|
|
|
|
TDataReadReference<float> InRangeMax = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputRangeMax), InParams.OperatorSettings);
|
|
|
|
|
|
|
|
|
|
return MakeUnique<FLinearToLogFrequencyOperator>(InValue, InDomainMin, InDomainMax, InRangeMin, InRangeMax);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FLinearToLogFrequencyOperator(
|
2021-09-15 15:01:04 -04:00
|
|
|
const TDataReadReference<float>& InValue,
|
2021-06-21 21:39:37 -04:00
|
|
|
const TDataReadReference<float>& InDomainMin,
|
|
|
|
|
const TDataReadReference<float>& InDomainMax,
|
|
|
|
|
const TDataReadReference<float>& InRangeMin,
|
|
|
|
|
const TDataReadReference<float>& InRangeMax)
|
|
|
|
|
: Value(InValue)
|
|
|
|
|
, DomainMin(InDomainMin)
|
|
|
|
|
, DomainMax(InDomainMax)
|
|
|
|
|
, RangeMin(InRangeMin)
|
|
|
|
|
, RangeMax(InRangeMax)
|
|
|
|
|
, FreqOutput(FFloatWriteRef::CreateNew(GetOutputValue()))
|
|
|
|
|
, PrevInputValue(*Value)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-22 13:28:27 -04:00
|
|
|
virtual void BindInputs(FInputVertexInterfaceData& InOutVertexData) override
|
2021-06-21 21:39:37 -04:00
|
|
|
{
|
|
|
|
|
using namespace LinearToLogFrequencyVertexNames;
|
|
|
|
|
|
2023-05-22 13:28:27 -04:00
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputValue), Value);
|
|
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputDomainMin), DomainMin);
|
|
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputDomainMax), DomainMax);
|
|
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputRangeMin), RangeMin);
|
|
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputRangeMax), RangeMax);
|
|
|
|
|
}
|
2021-06-21 21:39:37 -04:00
|
|
|
|
2023-05-22 13:28:27 -04:00
|
|
|
virtual void BindOutputs(FOutputVertexInterfaceData& InOutVertexData) override
|
|
|
|
|
{
|
|
|
|
|
using namespace LinearToLogFrequencyVertexNames;
|
2021-06-21 21:39:37 -04:00
|
|
|
|
2023-05-22 13:28:27 -04:00
|
|
|
InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(OutputFreq), FreqOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 {};
|
2021-06-21 21:39:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual FDataReferenceCollection GetOutputs() const override
|
|
|
|
|
{
|
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 {};
|
2021-06-21 21:39:37 -04:00
|
|
|
}
|
|
|
|
|
|
2023-03-02 14:40:35 -05:00
|
|
|
void Reset(const IOperator::FResetParams& InParams)
|
|
|
|
|
{
|
|
|
|
|
PrevInputValue = *Value;
|
|
|
|
|
*FreqOutput = GetOutputValue();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 21:39:37 -04:00
|
|
|
void Execute()
|
|
|
|
|
{
|
|
|
|
|
using namespace LinearToLogFrequencyVertexNames;
|
|
|
|
|
|
|
|
|
|
if (!FMath::IsNearlyEqual(*Value, PrevInputValue))
|
|
|
|
|
{
|
|
|
|
|
PrevInputValue = *Value;
|
|
|
|
|
*FreqOutput = GetOutputValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
float GetOutputValue() const
|
|
|
|
|
{
|
|
|
|
|
float RangeMinClamped = FMath::Max(*RangeMin, SMALL_NUMBER);
|
|
|
|
|
float RangeMaxClamped = FMath::Max(*RangeMax, SMALL_NUMBER);
|
|
|
|
|
float Result = Audio::GetLogFrequencyClamped(*Value, { *DomainMin, *DomainMax }, { RangeMinClamped, RangeMaxClamped });
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TDataReadReference<float> Value;
|
|
|
|
|
TDataReadReference<float> DomainMin;
|
|
|
|
|
TDataReadReference<float> DomainMax;
|
|
|
|
|
TDataReadReference<float> RangeMin;
|
|
|
|
|
TDataReadReference<float> RangeMax;
|
|
|
|
|
|
|
|
|
|
FFloatWriteRef FreqOutput;
|
|
|
|
|
|
|
|
|
|
float PrevInputValue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class METASOUNDSTANDARDNODES_API FLinearToLogFrequencyNode : public FNodeFacade
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* Constructor used by the Metasound Frontend.
|
|
|
|
|
*/
|
|
|
|
|
FLinearToLogFrequencyNode(const FNodeInitData& InitData)
|
|
|
|
|
: FNodeFacade(InitData.InstanceName, InitData.InstanceID, TFacadeOperatorClass<FLinearToLogFrequencyOperator>())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
METASOUND_REGISTER_NODE(FLinearToLogFrequencyNode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|