Created
April 4, 2021 21:36
-
-
Save jpcima/ad399211b6fd7df1abf14fce7bf1d7d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/plugins/vst/SfizzVstEvents.h b/plugins/vst/SfizzVstEvents.h | |
new file mode 100644 | |
index 00000000..1c915e70 | |
--- /dev/null | |
+++ b/plugins/vst/SfizzVstEvents.h | |
@@ -0,0 +1,40 @@ | |
+// SPDX-License-Identifier: BSD-2-Clause | |
+ | |
+// This code is part of the sfizz library and is licensed under a BSD 2-clause | |
+// license. You should have receive a LICENSE.md file along with the code. | |
+// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz | |
+ | |
+#pragma once | |
+#include "pluginterfaces/vst/ivstevents.h" | |
+#include "pluginterfaces/vst/ivstparameterchanges.h" | |
+#include "pluginterfaces/vst/ivstaudioprocessor.h" | |
+#include <memory> | |
+ | |
+using namespace Steinberg; | |
+ | |
+template <class T> | |
+class EventProcessorInOrder { | |
+public: | |
+ void initialize(const Vst::ProcessSetup& setup, int32 paramCount); | |
+ void processEvents(int32 numFrames, Vst::IParameterChanges* pcs, Vst::IEventList* evs); | |
+ | |
+private: | |
+ int32 sortParameterChanges(int32 numFrames, Vst::IParameterChanges* pcs); | |
+ | |
+ static inline int32 fixSampleOffset(int32 sampleOffset, int32 numFrames) | |
+ { | |
+ sampleOffset = (sampleOffset < numFrames) ? sampleOffset : (numFrames - 1); | |
+ sampleOffset = (sampleOffset < 0) ? 0 : sampleOffset; | |
+ return sampleOffset; | |
+ } | |
+ | |
+ struct SortableParameterChange { | |
+ Vst::ParamID id; // parameter ID | |
+ int32 sampleOffset; // sample when it happens | |
+ Vst::ParamValue value; // value of parameter | |
+ }; | |
+ std::unique_ptr<SortableParameterChange[]> sortedPcsTemp_; | |
+ int32 maxSortedPcs_ = 0; | |
+}; | |
+ | |
+#include "SfizzVstEvents.hpp" | |
diff --git a/plugins/vst/SfizzVstEvents.hpp b/plugins/vst/SfizzVstEvents.hpp | |
new file mode 100644 | |
index 00000000..db758121 | |
--- /dev/null | |
+++ b/plugins/vst/SfizzVstEvents.hpp | |
@@ -0,0 +1,107 @@ | |
+// SPDX-License-Identifier: BSD-2-Clause | |
+ | |
+// This code is part of the sfizz library and is licensed under a BSD 2-clause | |
+// license. You should have receive a LICENSE.md file along with the code. | |
+// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz | |
+ | |
+#pragma once | |
+#include "SfizzVstEvents.h" | |
+#include <algorithm> | |
+ | |
+template <class T> | |
+void EventProcessorInOrder<T>::initialize(const Vst::ProcessSetup& setup, int32 paramCount) | |
+{ | |
+ maxSortedPcs_ = setup.maxSamplesPerBlock * paramCount; | |
+ sortedPcsTemp_.reset(new SortableParameterChange[maxSortedPcs_]); | |
+} | |
+ | |
+template <class T> | |
+void EventProcessorInOrder<T>::processEvents(int32 numFrames, Vst::IParameterChanges* pcs, Vst::IEventList* evs) | |
+{ | |
+ const int32 numSortedPcs = sortParameterChanges(numFrames, pcs); | |
+ const SortableParameterChange* sortedPcs = sortedPcsTemp_.get(); | |
+ | |
+ int32 eventIndex = 0; | |
+ bool hasMoreEvents = evs != nullptr; | |
+ | |
+ Vst::Event readyEvent; | |
+ bool hasReadyEvent = false; | |
+ | |
+ auto getCurrentEvent = [&]() -> Vst::Event* { | |
+ if (!hasMoreEvents) | |
+ return nullptr; | |
+ if (!hasReadyEvent) { | |
+ if (!(hasMoreEvents = evs->getEvent(eventIndex, readyEvent))) { | |
+ readyEvent.sampleOffset = fixSampleOffset(readyEvent.sampleOffset, numFrames); | |
+ return nullptr; | |
+ } | |
+ } | |
+ return &readyEvent; | |
+ }; | |
+ | |
+ /// | |
+ for (int32 i = 0; i < numSortedPcs; ++i) { | |
+ const SortableParameterChange& sortedPc = sortedPcs[i]; | |
+ const int32 sampleOffset = sortedPc.sampleOffset; | |
+ | |
+ Vst::Event* event; | |
+ while ((event = getCurrentEvent()) && event->sampleOffset <= sampleOffset) { | |
+ static_cast<T*>(this)->processOrderedEvent(*event, event->sampleOffset); | |
+ ++eventIndex; | |
+ } | |
+ | |
+ static_cast<T*>(this)->processOrderedParameterChange(sortedPc.id, sortedPc.value, sampleOffset); | |
+ } | |
+ | |
+ Vst::Event* event; | |
+ while ((event = getCurrentEvent())) { | |
+ static_cast<T*>(this)->processOrderedEvent(*event, event->sampleOffset); | |
+ ++eventIndex; | |
+ } | |
+} | |
+ | |
+template <class T> | |
+int32 EventProcessorInOrder<T>::sortParameterChanges(int32 numFrames, Vst::IParameterChanges* pcs) | |
+{ | |
+ if (!pcs) | |
+ return 0; | |
+ | |
+ // Note: this function may return early if the queues contain duplicate | |
+ // points, which is not supposed to happen. | |
+ | |
+ SortableParameterChange* sortedPcs = sortedPcsTemp_.get(); | |
+ int32 numSortedPcs = 0; | |
+ const int32 maxSortedPcs = maxSortedPcs_; | |
+ | |
+ const int32 paramCount = pcs->getParameterCount(); | |
+ for (int32 paramIndex = 0; paramIndex < paramCount; ++paramIndex) { | |
+ Vst::IParamValueQueue* vq = pcs->getParameterData(paramIndex); | |
+ if (!vq) | |
+ continue; | |
+ | |
+ const Vst::ParamID id = vq->getParameterId(); | |
+ const uint32 pointCount = vq->getPointCount(); | |
+ | |
+ for (int32 pointIndex = 0; pointIndex < pointCount; ++pointIndex) { | |
+ int32 sampleOffset; | |
+ Vst::ParamValue value; | |
+ if (vq->getPoint(pointIndex, sampleOffset, value) == kResultTrue) { | |
+ SortableParameterChange& sortedPc = sortedPcs[numSortedPcs++]; | |
+ sortedPc.id = id; | |
+ sortedPc.sampleOffset = fixSampleOffset(sampleOffset, numFrames); | |
+ sortedPc.value = value; | |
+ | |
+ if (numSortedPcs == maxSortedPcs) | |
+ return numSortedPcs; | |
+ } | |
+ } | |
+ } | |
+ | |
+ std::stable_sort( | |
+ sortedPcs, sortedPcs + numSortedPcs, | |
+ [](const SortableParameterChange& a, const SortableParameterChange& b) -> bool { | |
+ return a.sampleOffset < b.sampleOffset; | |
+ }); | |
+ | |
+ return numSortedPcs; | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment