// Copyright Epic Games, Inc. All Rights Reserved. #include "DSP/FloatArrayMath.h" #include "Internationalization/Text.h" #include "MetasoundExecutableOperator.h" #include "MetasoundEnumRegistrationMacro.h" #include "MetasoundNodeRegistrationMacro.h" #include "MetasoundStandardNodesNames.h" #include "MetasoundAudioBuffer.h" #include "MetasoundFacade.h" #include "MetasoundParamHelper.h" #include "MetasoundStandardNodesCategories.h" #define LOCTEXT_NAMESPACE "MetasoundStandardNodes_MetasoundRingModNodes" namespace Metasound { /* RingMod Processor */ namespace RingModVertexNames { METASOUND_PARAM(InputAudioCarrier, "In Carrier", "The carrier audio signal.") METASOUND_PARAM(InputAudioModulator, "In Modulator", "The modulator audio signal.") METASOUND_PARAM(OutputAudio, "Out Audio", "The modulated audio signal.") } // Operator Class class FRingModOperator : public TExecutableOperator { public: FRingModOperator(const FOperatorSettings& InSettings, const FAudioBufferReadRef& InputAudioCarrier, const FAudioBufferReadRef& InputAudioModulator) : AudioInputCarrier(InputAudioCarrier) , AudioInputModulator(InputAudioModulator) , AudioOutput(FAudioBufferWriteRef::CreateNew(InSettings)) { AudioOutput->Zero(); } static const FNodeClassMetadata& GetNodeInfo() { auto CreateNodeClassMetadata = []() -> FNodeClassMetadata { FVertexInterface NodeInterface = DeclareVertexInterface(); FNodeClassMetadata Metadata { FNodeClassName { StandardNodes::Namespace, "RingMod", StandardNodes::AudioVariant }, 1, // Major Version 0, // Minor Version METASOUND_LOCTEXT("RingModDisplayName2", "Ring Modulator"), METASOUND_LOCTEXT("RingModDesc", "Modulates a carrier signal."), PluginAuthor, PluginNodeMissingPrompt, NodeInterface, { NodeCategories::Filters }, { }, FNodeDisplayStyle{} }; return Metadata; }; static const FNodeClassMetadata Metadata = CreateNodeClassMetadata(); return Metadata; } static const FVertexInterface& DeclareVertexInterface() { using namespace RingModVertexNames; static const FVertexInterface Interface( FInputVertexInterface( TInputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(InputAudioCarrier)), TInputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(InputAudioModulator)) ), FOutputVertexInterface( TOutputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(OutputAudio)) ) ); return Interface; } virtual void BindInputs(FInputVertexInterfaceData& InOutVertexData) override { using namespace RingModVertexNames; InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputAudioCarrier), AudioInputCarrier); InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputAudioModulator), AudioInputModulator); } virtual void BindOutputs(FOutputVertexInterfaceData& InOutVertexData) override { using namespace RingModVertexNames; InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(OutputAudio), AudioOutput); } static TUniquePtr CreateOperator(const FBuildOperatorParams& InParams, FBuildResults& OutResults) { using namespace RingModVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; FAudioBufferReadRef CarrierAudioIn = InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputAudioCarrier), InParams.OperatorSettings); FAudioBufferReadRef ModulatorAudioIn = InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputAudioModulator), InParams.OperatorSettings); return MakeUnique(InParams.OperatorSettings, CarrierAudioIn, ModulatorAudioIn); } void Execute() { *AudioOutput = *AudioInputCarrier; // @TODO Add Array Multiply Ain, Bin, Cout Audio::ArrayMultiplyInPlace(*AudioInputModulator, *AudioOutput); } void Reset(const IOperator::FResetParams& InParams) { AudioOutput->Zero(); } private: // The input audio buffer FAudioBufferReadRef AudioInputCarrier; FAudioBufferReadRef AudioInputModulator; // Output audio buffer FAudioBufferWriteRef AudioOutput; }; // Node Class using FRingModNode = TNodeFacade; // Register node METASOUND_REGISTER_NODE(FRingModNode) } #undef LOCTEXT_NAMESPACE