Also preallocate small buffers for VST2 events

This commit is contained in:
Robbert van der Helm
2021-05-23 00:10:03 +02:00
parent 095ca11535
commit e700678a11
4 changed files with 27 additions and 8 deletions
+2
View File
@@ -38,6 +38,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
and preventing memory allocations in the process.
- Further optimized VST3 audio processing by preallocating small vectors for
event and parameter change queues.
- VST2 audio processing also received the same small vector optimization to get
rid of any last potential allocations during audio processing.
- Changed the way mutual recursion in VST3 plugins on the plugin side works to
counter any potential GUI related timing issues with VST3 plugins.
- The deserialization part of yabridge's communication is now slightly faster by
+17 -5
View File
@@ -19,11 +19,13 @@
#include <variant>
#include <bitsery/ext/std_optional.h>
#include "../bitsery/ext/in-place-variant.h"
#include <bitsery/traits/array.h>
#include <bitsery/traits/vector.h>
#include <vestige/aeffectx.h>
#include <boost/container/small_vector.hpp>
#include "../bitsery/ext/in-place-variant.h"
#include "../bitsery/traits/small-vector.h"
#include "../utils.h"
#include "../vst24.h"
#include "common.h"
@@ -162,6 +164,9 @@ struct ChunkData {
* 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 using the `as_c_events()` method.
*
* Using preallocated small vectors here gets rid of all event related
* allocations in normal use cases.
*/
class alignas(16) DynamicVstEvents {
public:
@@ -177,9 +182,11 @@ class alignas(16) DynamicVstEvents {
VstEvents& as_c_events();
/**
* MIDI events are sent in batches.
* MIDI events are sent just before the audio processing call. Technically a
* host can call `effProcessEvents()` multiple times, but in practice this
* of course doesn't happen.
*/
std::vector<VstEvent> events;
boost::container::small_vector<VstEvent, 64> events;
template <typename S>
void serialize(S& s) {
@@ -194,14 +201,19 @@ class alignas(16) DynamicVstEvents {
* `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
* actuall 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.
*/
std::vector<uint8_t> vst_events_buffer;
boost::container::small_vector<
uint8_t,
sizeof(VstEvents) +
((64 - 1) *
sizeof(VstEvent*))> // NOLINT(bugprone-sizeof-expression)
vst_events_buffer;
};
/**
+2 -2
View File
@@ -185,10 +185,10 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* function. If they are sent during any other time or from another thread,
* then the host will just discard them. Because we're receiving our host
* callbacks on a separate thread, we have to temporarily store any events
* we receive so we can send them to the host at the end of
* we receive so we can send them to host on the audio thread at the end of
* `process_replacing()`.
*/
std::vector<DynamicVstEvents> incoming_midi_events;
boost::container::small_vector<DynamicVstEvents, 4> incoming_midi_events;
/**
* Mutex for locking the above event queue, since recieving and processing
* now happens in two different threads.
+6 -1
View File
@@ -189,8 +189,13 @@ class Vst2Bridge : public HostBridge {
* events they receive but some plugins such as Kontakt only store pointers
* to these events, which means that the actual `VstEvent` objects must live
* at least until the next audio buffer gets processed.
*
* Technically a host can send more than one of these at a time, but in
* practice every host will bundle all events in a single
* `effProcessEvents()` call.
*/
std::vector<DynamicVstEvents> next_audio_buffer_midi_events;
boost::container::small_vector<DynamicVstEvents, 4>
next_audio_buffer_midi_events;
/**
* Whether `next_audio_buffer_midi_events` should be cleared before
* inserting new events.