mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 12:10:09 +02:00
Also preallocate small buffers for VST2 events
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user