Allow for an arbitrary number of midi events

By building the object on the heap in a buffer. I preferred the old
solution but this is more flexible.
This commit is contained in:
Robbert van der Helm
2020-03-28 14:07:11 +01:00
parent 2ea480a09d
commit 629fa72e0c
3 changed files with 31 additions and 24 deletions
-3
View File
@@ -14,9 +14,6 @@ There are a few things that should be done before releasing this, including:
- Fix implementation bugs:
- KiloHearts plugins fail during initialization.
- Serum crashes when closing bitwig (but otherwise exits just fine).
- Serum crashes if you keep playing midi notes while the GUI is blocked.
Related to the above, and probably because of the current limit of 512 midi
events.
- Melda plugins crash when opening their GUI.
- Add missing details if any to the architecture section.
- Document what this has been tested on and what does or does not work.
+18 -6
View File
@@ -25,13 +25,25 @@ DynamicVstEvents::DynamicVstEvents(const VstEvents& c_events)
}
VstEvents& DynamicVstEvents::as_c_events() {
vst_events.numEvents = events.size();
// As explained in `vst_events_buffer`'s docstring we have to build the
// `VstEvents` struct by hand on the heap since it's actually a dynamically
// sized object
// Populate the vst_events struct with data from the vector. This will
// overflow past the defined length of `vst_events.events` because it's
// actually a VLA. This is why I put some padding at the end of this struct.
std::transform(events.begin(), events.end(), &vst_events.events[0],
// First we need to allocate enough memory for the entire object. The events
// are stored as pointers to objects in the `events` vector that we sent
// over the socket.
static_assert(std::extent<decltype(VstEvents::events)>::value == 1);
const size_t buffer_size =
sizeof(VstEvents) + (events.size() - 1) * sizeof(VstEvent*);
vst_events_buffer.resize(buffer_size);
// Now we can populate the VLA with pointers to the objects in the `events`
// vector
VstEvents* vst_events =
reinterpret_cast<VstEvents*>(vst_events_buffer.data());
vst_events->numEvents = events.size();
std::transform(events.begin(), events.end(), vst_events->events,
[](VstEvent& event) -> VstEvent* { return &event; });
return vst_events;
return *vst_events;
}
+13 -15
View File
@@ -42,7 +42,7 @@ constexpr size_t max_buffer_size = 16384;
/**
* The maximum number of midi events in a single `VstEvents` struct.
*/
constexpr size_t max_midi_events = 256;
constexpr size_t max_midi_events = max_buffer_size / sizeof(size_t);
/**
* The maximum size in bytes of a string or buffer passed through a void pointer
* in one of the dispatch functions. This is used to create buffers for plugins
@@ -122,7 +122,7 @@ void serialize(S& s, VstTimeInfo& time_info) {
*
* Before serialization the events are read from a C-style array into a vector
* using this class's constructor, and after deserializing the original struct
* can be reconstructed usign the `as_c_events()` method.
* can be reconstructed using the `as_c_events()` method.
*/
class alignas(16) DynamicVstEvents {
public:
@@ -144,20 +144,18 @@ class alignas(16) DynamicVstEvents {
private:
/**
* A `VstEvents` struct based on the `events` vector. Use the
* `as_c_events()` method to populate and return this after the `events`
* vector has been filled.
* Some buffer we can build a `VstEvents`. This object can be populated with
* contents of the `VstEvents` vector using the `as_c_events()` method.
*
* The reason why this is necessary is because the `VstEvents` struct is
* actually a variable size object. In the definition in
* `vestige/aeffectx.h` the struct contains a single element `VstEvent`
* pointer array, but the actual length of this array is
* `VstEvents::numEvents`. Because there is no real limit on the number of
* midi events the host can send at once we have to build this object on the
* heap by hand.
*/
VstEvents vst_events;
/**
* The `VstEvents` struct is defined to look like it contains a one or two
* element array of `VstEvent` pointers. The actual truth is that the
* `VstEvents::event` array is actually a variable length array with length
* `VstEvents::numEvents`. This is probably not part of any header files
* because VLAs are not part of any C++ standard. This struct is here to
* make sure there is enough room to copy the elements into.
*/
size_t dummy[max_midi_events];
std::vector<uint8_t> vst_events_buffer;
};
/**