diff --git a/src/common/communication/vst2.h b/src/common/communication/vst2.h index dca302b5..25d2f9bd 100644 --- a/src/common/communication/vst2.h +++ b/src/common/communication/vst2.h @@ -50,14 +50,14 @@ class DefaultDataConverter { const intptr_t value) const; /** - * Write the reponse back to the `data` pointer. + * Write the response back to the `data` pointer. */ virtual void write(const int opcode, void* data, const EventResult& response) const; /** - * Write the reponse back to the `value` pointer. This is only used during + * Write the response back to the `value` pointer. This is only used during * the `effGetSpeakerArrangement` event. */ virtual void write_value(const int opcode, diff --git a/src/common/communication/vst3.h b/src/common/communication/vst3.h index 0a5c015e..4b66faf6 100644 --- a/src/common/communication/vst3.h +++ b/src/common/communication/vst3.h @@ -462,6 +462,24 @@ class Vst3Sockets : public Sockets { audio_processor_buffers.at(object_ref.get().instance_id)); } + /** + * Alternative to `send_audio_processor_message()` for use with + * `MessageReference`, where we also want deserialize into an existing + * object to prevent allocations. Used during audio processing.q + * + * TODO: Think of a better name for this + */ + template + typename T::Response& receive_audio_processor_message_into( + const MessageReference& request_ref, + typename T::Response& response_ref, + std::optional> logging) { + return audio_processor_sockets.at(request_ref.get().instance_id) + .receive_into( + request_ref, response_ref, logging, + audio_processor_buffers.at(request_ref.get().instance_id)); + } + /** * For sending messages from the host to the plugin. After we have a better * idea of what our communication model looks like we'll probably want to diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index a0177105..34827dec 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -220,12 +220,15 @@ Vst3PluginProxyImpl::process(Steinberg::Vst::ProcessData& data) { process_request.data.repopulate(data); process_request.new_realtime_priority = new_realtime_priority; - ProcessResponse response = bridge.send_audio_processor_message( - MessageReference(process_request)); + // We'll also receive the response into an existing object so we can also + // avoid heap allocations there + bridge.receive_audio_processor_message_into( + MessageReference(process_request), + process_response); - response.output_data.write_back_outputs(data); + process_response.output_data.write_back_outputs(data); - return response.result; + return process_response.result; } uint32 PLUGIN_API Vst3PluginProxyImpl::getTailSamples() { diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index 315da918..3ac986f0 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -489,6 +489,13 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { */ YaAudioProcessor::Process process_request; + /** + * The response object we'll get in return when we send the + * `process_request` object above to the Wine plugin host. This object also + * contains heap data, so we also want to reuse this. + */ + YaAudioProcessor::ProcessResponse process_response; + // Caches /** diff --git a/src/plugin/bridges/vst3.h b/src/plugin/bridges/vst3.h index 8ffcb03a..c5d015ce 100644 --- a/src/plugin/bridges/vst3.h +++ b/src/plugin/bridges/vst3.h @@ -121,6 +121,21 @@ class Vst3PluginBridge : PluginBridge> { object, std::pair(logger, true)); } + /** + * Send an `IAudioProcessor` or `IComponent` control message to a specific + * plugin instance, receiving the results into an existing object. This is + * similar to the `send_audio_processor_message()` above, but this lets us + * avoid allocations in response objects that contain heap data. + */ + template + typename T::Response& receive_audio_processor_message_into( + const T& object, + typename T::Response& response_object) { + return sockets.receive_audio_processor_message_into( + object, response_object, + std::pair(logger, true)); + } + /** * The logging facility used for this instance of yabridge. Wraps around * `PluginBridge::generic_logger`.