Skip to content

Instantly share code, notes, and snippets.

@jpcima
Created April 4, 2021 21:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpcima/ad399211b6fd7df1abf14fce7bf1d7d7 to your computer and use it in GitHub Desktop.
Save jpcima/ad399211b6fd7df1abf14fce7bf1d7d7 to your computer and use it in GitHub Desktop.
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