diff --git a/packages/nodegraph/include/nodegraph/operations/NodeGraphOpFilter.h b/packages/nodegraph/include/nodegraph/operations/NodeGraphOpFilter.h index e937b0a..f7aca5e 100644 --- a/packages/nodegraph/include/nodegraph/operations/NodeGraphOpFilter.h +++ b/packages/nodegraph/include/nodegraph/operations/NodeGraphOpFilter.h @@ -120,5 +120,25 @@ namespace l::nodegraph { l::audio::FilterRWA mScaleFilter; }; + + /*********************************************************************/ + class GraphFilterMovingAverage : public GraphFilterBase { + public: + GraphFilterMovingAverage(NodeGraphBase* node, int32_t kernelSize) : + GraphFilterBase(node, "Moving Average"), + mKernelSize(kernelSize) + { + mInputManager.AddInput(InputIterationType::SAMPLED, AddInput("Kernel Size", 1.0f, 1, 1.0f, static_cast(mKernelSize))); + } + virtual ~GraphFilterMovingAverage() = default; + + virtual void ResetInput() override; + virtual void ResetSignal() override; + virtual float ProcessSignal(float input, float cutoff, float resonance) override; + protected: + int32_t mKernelSize = 150; + int32_t mFilterStateIndex = -1; + std::vector mFilterState; + }; } diff --git a/packages/nodegraph/source/common/NodeGraphSchema.cpp b/packages/nodegraph/source/common/NodeGraphSchema.cpp index 70e5be0..2de8d88 100644 --- a/packages/nodegraph/source/common/NodeGraphSchema.cpp +++ b/packages/nodegraph/source/common/NodeGraphSchema.cpp @@ -91,6 +91,9 @@ namespace l::nodegraph { case 152: node = mMainNodeGraph.NewNode(NodeType::Default); break; + case 153: + node = mMainNodeGraph.NewNode(NodeType::Default, 150); + break; case 200: node = mMainNodeGraph.NewNode(NodeType::ExternalOutput); @@ -269,6 +272,7 @@ namespace l::nodegraph { RegisterNodeType("Filter", 150, "Lowpass"); RegisterNodeType("Filter", 151, "Highpass"); RegisterNodeType("Filter", 152, "Chamberlin two-pole (4 mode)"); + RegisterNodeType("Filter", 153, "Moving Average"); } else if (typeGroup == "Output") { RegisterNodeType("Output", 200, "Debug"); diff --git a/packages/nodegraph/source/common/operations/NodeGraphOpFilter.cpp b/packages/nodegraph/source/common/operations/NodeGraphOpFilter.cpp index f10b11b..137750e 100644 --- a/packages/nodegraph/source/common/operations/NodeGraphOpFilter.cpp +++ b/packages/nodegraph/source/common/operations/NodeGraphOpFilter.cpp @@ -12,16 +12,11 @@ namespace l::nodegraph { /* Stateful filtering operations */ /*********************************************************************/ void GraphFilterBase::Reset() { + NodeGraphOp::Reset(); + mSync = 0.0f; mSamplesUntilUpdate = 0.0f; - mNode->SetInput(0, 0.0f); - mNode->SetInput(2, 0.5f); - mNode->SetInput(3, 0.5f); - mNode->SetInputBound(0, InputBound::INPUT_0_TO_1); - mNode->SetInputBound(2, InputBound::INPUT_0_TO_1); - mNode->SetInputBound(3, InputBound::INPUT_0_TO_1); - ResetInput(); ResetSignal(); } @@ -125,4 +120,37 @@ namespace l::nodegraph { return mState.at(mMode); } + + /*********************************************************************/ + void GraphFilterMovingAverage::ResetInput() { + } + + void GraphFilterMovingAverage::ResetSignal() { + mFilterState.resize(mKernelSize); + mFilterStateIndex = -1; + } + + float GraphFilterMovingAverage::ProcessSignal(float input, float, float) { + if (mFilterStateIndex < 0) { + for (int32_t i = 0; i < mFilterState.size(); i++) { + mFilterState.at(i) = input; + } + mFilterStateIndex = 0; + } + + mFilterState[mFilterStateIndex] = input; + float width = mInputManager.GetValueNext(mNumDefaultInputs + 0); + int32_t widthInt = static_cast(width); + mFilterStateIndex = (mFilterStateIndex + 1) % widthInt; + + if (widthInt == 1) { + return input; + } + + float outVal = 0.0; + for (int32_t i = 0; i < widthInt; i++) { + outVal += mFilterState[i]; + } + return outVal / width; + } }