From 95a4ef8eedc016d2f8fb4529d00e351524a50631 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 16 Dec 2020 17:36:49 +0100 Subject: [PATCH] Implement reconstructing ProcessData --- .../serialization/vst3/process-data.cpp | 67 ++++++++++++++++++- src/common/serialization/vst3/process-data.h | 53 +++++++++------ 2 files changed, 98 insertions(+), 22 deletions(-) diff --git a/src/common/serialization/vst3/process-data.cpp b/src/common/serialization/vst3/process-data.cpp index 469e60bd..80b84722 100644 --- a/src/common/serialization/vst3/process-data.cpp +++ b/src/common/serialization/vst3/process-data.cpp @@ -62,7 +62,8 @@ YaAudioBusBuffers::YaAudioBusBuffers( } } -Steinberg::Vst::AudioBusBuffers& YaAudioBusBuffers::get() { +Steinberg::Vst::AudioBusBuffers YaAudioBusBuffers::get() { + Steinberg::Vst::AudioBusBuffers reconstructed_buffers; reconstructed_buffers.silenceFlags = silence_flags; std::visit(overload{ [&](std::vector>& buffers) { @@ -120,4 +121,66 @@ YaProcessData::YaProcessData(const Steinberg::Vst::ProcessData& process_data) } } -// TODO: Reconstruction +Steinberg::Vst::ProcessData& YaProcessData::get() { + // We'll have to transform out `YaAudioBusBuffers` objects into an array of + // `AudioBusBuffers` object so the plugin can deal with them. These objects + // contain pointers to those original objects and thus don't store any + // buffer data themselves. + inputs_audio_bus_buffers.clear(); + for (auto& buffers : inputs) { + inputs_audio_bus_buffers.push_back(buffers.get()); + } + + // We'll do the same with with the outputs, but we'll first have to + // initialize zeroed out buffers for the plugin to work with since we didn't + // serialize those directly + outputs.clear(); + outputs_audio_bus_buffers.clear(); + for (auto& num_channels : outputs_num_channels) { + YaAudioBusBuffers& buffers = outputs.emplace_back( + symbolic_sample_size, num_channels, num_samples); + outputs_audio_bus_buffers.push_back(buffers.get()); + } + + reconstructed_process_data.processMode = process_mode; + reconstructed_process_data.symbolicSampleSize = symbolic_sample_size; + reconstructed_process_data.numSamples = num_samples; + reconstructed_process_data.numInputs = inputs.size(); + reconstructed_process_data.numOutputs = outputs_num_channels.size(); + reconstructed_process_data.inputs = inputs_audio_bus_buffers.data(); + reconstructed_process_data.outputs = outputs_audio_bus_buffers.data(); + + reconstructed_process_data.inputParameterChanges = &input_parameter_changes; + if (output_parameter_changes_supported) { + output_parameter_changes.emplace(); + reconstructed_process_data.outputParameterChanges = + &*output_parameter_changes; + } else { + output_parameter_changes.reset(); + reconstructed_process_data.outputParameterChanges = nullptr; + } + + if (input_events) { + reconstructed_process_data.inputEvents = &*input_events; + } else { + reconstructed_process_data.inputEvents = nullptr; + } + + if (output_events_supported) { + output_events.emplace(); + reconstructed_process_data.outputEvents = &*output_events; + } else { + output_events.reset(); + reconstructed_process_data.outputEvents = nullptr; + } + + if (process_context) { + reconstructed_process_data.processContext = &*process_context; + } else { + reconstructed_process_data.processContext = nullptr; + } + + return reconstructed_process_data; +} + +// TODO: Response creation diff --git a/src/common/serialization/vst3/process-data.h b/src/common/serialization/vst3/process-data.h index 51601895..c3a10167 100644 --- a/src/common/serialization/vst3/process-data.h +++ b/src/common/serialization/vst3/process-data.h @@ -67,9 +67,10 @@ class YaAudioBusBuffers { /** * Reconstruct the original `AudioBusBuffers` object passed to the * constructor and return it. This is used as part of - * `YaProcessData::get()`. + * `YaProcessData::get()`. The object contains pointers to `buffers`, so it + * may not outlive this object. */ - Steinberg::Vst::AudioBusBuffers& get(); + Steinberg::Vst::AudioBusBuffers get(); template void serialize(S& s) { @@ -91,11 +92,6 @@ class YaAudioBusBuffers { } private: - /** - * The `AudioBusBuffers` object we reconstruct during `get()`. - */ - Steinberg::Vst::AudioBusBuffers reconstructed_buffers; - /** * We need these during the reconstruction process to provide a pointer to * an array of pointers to the actual buffers. @@ -260,19 +256,6 @@ class YaProcessData { */ std::optional process_context; - // These last few members are used on the Wine plugin host side to - // reconstruct the original `ProcessData` object. Here we also initialize - // these `output*` fields so the Windows VST3 plugin can write to them - // though a regular `ProcessData` object. Finally we can wrap these output - // fields back into a `YaProcessDataResponse` using - // `move_outputs_to_response()`. so they can be serialized and written back - // to the host's `ProcessData` object. - - /** - * The process data we reconstruct from the other fields during `get()`. - */ - Steinberg::Vst::ProcessData reconstructed_process_data; - // These are the same fields as in `YaProcessDataResponse`. We'll generate // these as part of creating `reconstructed_process_data`, and they will be // moved into a response object during `move_outputs_to_response()`. @@ -295,6 +278,36 @@ class YaProcessData { * `output_events_supported`. */ std::optional output_events; + + // These last few members are used on the Wine plugin host side to + // reconstruct the original `ProcessData` object. Here we also initialize + // these `output*` fields so the Windows VST3 plugin can write to them + // though a regular `ProcessData` object. Finally we can wrap these output + // fields back into a `YaProcessDataResponse` using + // `move_outputs_to_response()`. so they can be serialized and written back + // to the host's `ProcessData` object. + + /** + * Obtained by calling `.get()` on every `YaAudioBusBuffers` object in + * `intputs`. These objects contain pointers to the data in `inputs` and may + * thus not outlive them. + */ + std::vector inputs_audio_bus_buffers; + + /** + * Obtained by calling `.get()` on every `YaAudioBusBuffers` object in + * `outputs`. These objects contain pointers to the data in `outputs` and + * may thus not outlive them. These are created in a two step process, since + * we first have to create `outputs` from `outputs_num_channels` before we + * can transform it into a structure the Windows VST3 plugin can work with. + * Hooray for heap arrays. + */ + std::vector outputs_audio_bus_buffers; + + /** + * The process data we reconstruct from the other fields during `get()`. + */ + Steinberg::Vst::ProcessData reconstructed_process_data; }; namespace Steinberg {