From f1aefc0a9dd0a4106a564bc7d571ad286f17a317 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Tue, 15 Dec 2020 22:32:42 +0100 Subject: [PATCH] Finish implementing YaAudioBusBuffers --- meson.build | 2 + .../serialization/vst3/process-data.cpp | 93 +++++++++++++++++++ src/common/serialization/vst3/process-data.h | 12 ++- 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/common/serialization/vst3/process-data.cpp diff --git a/meson.build b/meson.build index 7e514e0b..93443962 100644 --- a/meson.build +++ b/meson.build @@ -84,6 +84,7 @@ vst3_plugin_sources = [ 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/parameter-changes.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', + 'src/common/serialization/vst3/process-data.cpp', 'src/common/configuration.cpp', 'src/common/plugins.cpp', 'src/common/utils.cpp', @@ -122,6 +123,7 @@ if with_vst3 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/parameter-changes.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', + 'src/common/serialization/vst3/process-data.cpp', 'src/wine-host/bridges/vst3-impls/host-application.cpp', 'src/wine-host/bridges/vst3.cpp', ] diff --git a/src/common/serialization/vst3/process-data.cpp b/src/common/serialization/vst3/process-data.cpp new file mode 100644 index 00000000..0fd0662e --- /dev/null +++ b/src/common/serialization/vst3/process-data.cpp @@ -0,0 +1,93 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "process-data.h" + +#include "src/common/utils.h" + +YaAudioBusBuffers::YaAudioBusBuffers() {} + +YaAudioBusBuffers::YaAudioBusBuffers( + Steinberg::Vst::SymbolicSampleSizes sample_size, + size_t num_channels, + size_t num_samples) + : buffers(sample_size == Steinberg::Vst::SymbolicSampleSizes::kSample64 + ? decltype(buffers)(std::vector>( + num_channels, + std::vector(num_samples, 0.0))) + : decltype(buffers)(std::vector>( + num_channels, + std::vector(num_samples, 0.0)))) {} + +YaAudioBusBuffers::YaAudioBusBuffers( + Steinberg::Vst::SymbolicSampleSizes sample_size, + int32 num_samples, + const Steinberg::Vst::AudioBusBuffers& data) + : silence_flags(data.silenceFlags) { + switch (sample_size) { + case Steinberg::Vst::kSample64: { + std::vector> vector_buffers(data.numChannels); + for (int channel = 0; channel < data.numChannels; channel++) { + vector_buffers[channel].assign( + &data.channelBuffers64[channel][0], + &data.channelBuffers64[channel][num_samples]); + } + + buffers = std::move(vector_buffers); + } break; + case Steinberg::Vst::kSample32: + // I don't think they'll add any other sample sizes any time soon + default: { + std::vector> vector_buffers(data.numChannels); + for (int channel = 0; channel < data.numChannels; channel++) { + vector_buffers[channel].assign( + &data.channelBuffers32[channel][0], + &data.channelBuffers32[channel][num_samples]); + } + + buffers = std::move(vector_buffers); + } break; + } +} + +Steinberg::Vst::AudioBusBuffers& YaAudioBusBuffers::get() { + reconstructed_buffers.silenceFlags = silence_flags; + std::visit(overload{ + [&](std::vector>& buffers) { + double_buffer_pointers.clear(); + for (auto& buffer : buffers) { + double_buffer_pointers.push_back(buffer.data()); + } + + reconstructed_buffers.numChannels = buffers.size(); + reconstructed_buffers.channelBuffers64 = + double_buffer_pointers.data(); + }, + [&](std::vector>& buffers) { + float_buffer_pointers.clear(); + for (auto& buffer : buffers) { + float_buffer_pointers.push_back(buffer.data()); + } + + reconstructed_buffers.numChannels = buffers.size(); + reconstructed_buffers.channelBuffers32 = + float_buffer_pointers.data(); + }, + }, + buffers); + + return reconstructed_buffers; +} diff --git a/src/common/serialization/vst3/process-data.h b/src/common/serialization/vst3/process-data.h index ccc07c24..b441452e 100644 --- a/src/common/serialization/vst3/process-data.h +++ b/src/common/serialization/vst3/process-data.h @@ -57,9 +57,11 @@ class YaAudioBusBuffers { * call. Constructed as part of `YaProcessData`. Since `AudioBusBuffers` * contains an untagged union for storing single and double precision * floating point values, the original `ProcessData`'s `symbolicSampleSize` - * field determines which variant of that union to use. + * field determines which variant of that union to use. Similarly the + * `ProcessData`' `numSamples` field determines the extent of these arrays. */ YaAudioBusBuffers(Steinberg::Vst::SymbolicSampleSizes sample_size, + int32 num_samples, const Steinberg::Vst::AudioBusBuffers& data); /** @@ -94,6 +96,14 @@ class YaAudioBusBuffers { */ Steinberg::Vst::AudioBusBuffers reconstructed_buffers; + // Used in reconstructed_buffers, because we need to store pointers to the + // inner vectors in `buffers`. We're using a union instead of void pointers + // here to have at least some resemblance of type safety. + union { + std::vector float_buffer_pointers; + std::vector double_buffer_pointers; + }; + /** * A bitfield for silent channels copied directly from the input struct. */