From 0b2ce6a05f5edc5ada94b29cd2dc8f3c6c7d5eb7 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 23 May 2021 16:08:19 +0200 Subject: [PATCH] Reduce duplication in VST3 audio buffers Using C++20 templated lambdas. --- .../serialization/vst3/process-data.cpp | 144 +++++++----------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/src/common/serialization/vst3/process-data.cpp b/src/common/serialization/vst3/process-data.cpp index dee47284..f14daf7e 100644 --- a/src/common/serialization/vst3/process-data.cpp +++ b/src/common/serialization/vst3/process-data.cpp @@ -23,29 +23,25 @@ YaAudioBusBuffers::YaAudioBusBuffers() noexcept {} void YaAudioBusBuffers::clear(int32 sample_size, size_t num_samples, size_t num_channels) { + auto do_clear = [&](T) { + if (!std::holds_alternative>>(buffers)) { + buffers.emplace>>(); + } + + std::vector>& vector_buffers = + std::get>>(buffers); + vector_buffers.resize(num_channels); + for (size_t i = 0; i < vector_buffers.size(); i++) { + vector_buffers[i].resize(num_samples); + } + }; + if (sample_size == Steinberg::Vst::SymbolicSampleSizes::kSample64) { - if (!std::holds_alternative>>( - buffers)) { - buffers.emplace>>(); - } - - std::vector>& vector_buffers = - std::get>>(buffers); - vector_buffers.resize(num_channels); - for (size_t i = 0; i < vector_buffers.size(); i++) { - vector_buffers[i].resize(num_samples); - } + // XXX: Clangd doesn't let you specify template parameters for templated + // lambdas. This argument should get optimized out + do_clear(double()); } else { - if (!std::holds_alternative>>(buffers)) { - buffers.emplace>>(); - } - - std::vector>& vector_buffers = - std::get>>(buffers); - vector_buffers.resize(num_channels); - for (size_t i = 0; i < vector_buffers.size(); i++) { - vector_buffers[i].resize(num_samples); - } + do_clear(float()); } } @@ -55,39 +51,26 @@ void YaAudioBusBuffers::repopulate( const Steinberg::Vst::AudioBusBuffers& data) { silence_flags = data.silenceFlags; - switch (sample_size) { - case Steinberg::Vst::kSample64: { - if (!std::holds_alternative>>( - buffers)) { - buffers.emplace>>(); - } + auto do_repopuldate = [&](T** original_buffer) { + if (!std::holds_alternative>>(buffers)) { + buffers.emplace>>(); + } - std::vector>& vector_buffers = - std::get>>(buffers); - vector_buffers.resize(data.numChannels); - for (int channel = 0; channel < data.numChannels; channel++) { - vector_buffers[channel].assign( - &data.channelBuffers64[channel][0], - &data.channelBuffers64[channel][num_samples]); - } - } break; - case Steinberg::Vst::kSample32: + std::vector>& vector_buffers = + std::get>>(buffers); + vector_buffers.resize(data.numChannels); + for (int channel = 0; channel < data.numChannels; channel++) { + vector_buffers[channel].assign( + &original_buffer[channel][0], + &original_buffer[channel][num_samples]); + } + }; + + if (sample_size == Steinberg::Vst::kSample64) { + do_repopuldate(data.channelBuffers64); + } else { // I don't think they'll add any other sample sizes any time soon - default: { - if (!std::holds_alternative>>( - buffers)) { - buffers.emplace>>(); - } - - std::vector>& vector_buffers = - std::get>>(buffers); - vector_buffers.resize(data.numChannels); - for (int channel = 0; channel < data.numChannels; channel++) { - vector_buffers[channel].assign( - &data.channelBuffers32[channel][0], - &data.channelBuffers32[channel][num_samples]); - } - } break; + do_repopuldate(data.channelBuffers32); } } @@ -96,31 +79,25 @@ void YaAudioBusBuffers::reconstruct( // We'll update the `AudioBusBuffers` object in place to point to our new // data reconstructed_buffers.silenceFlags = silence_flags; - std::visit(overload{ - [&](std::vector>& buffers) { - buffer_pointers.resize(buffers.size()); - for (size_t i = 0; i < buffers.size(); i++) { - buffer_pointers[i] = buffers[i].data(); - } - reconstructed_buffers.numChannels = - static_cast(buffers.size()); - reconstructed_buffers.channelBuffers64 = - reinterpret_cast(buffer_pointers.data()); - }, - [&](std::vector>& buffers) { - buffer_pointers.resize(buffers.size()); - for (size_t i = 0; i < buffers.size(); i++) { - buffer_pointers[i] = buffers[i].data(); - } + std::visit( + [&](std::vector>& buffers) { + buffer_pointers.resize(buffers.size()); + for (size_t i = 0; i < buffers.size(); i++) { + buffer_pointers[i] = buffers[i].data(); + } - reconstructed_buffers.numChannels = - static_cast(buffers.size()); - reconstructed_buffers.channelBuffers32 = - reinterpret_cast(buffer_pointers.data()); - }, - }, - buffers); + reconstructed_buffers.numChannels = + static_cast(buffers.size()); + if constexpr (std::is_same_v) { + reconstructed_buffers.channelBuffers64 = + reinterpret_cast(buffer_pointers.data()); + } else { + reconstructed_buffers.channelBuffers32 = + reinterpret_cast(buffer_pointers.data()); + } + }, + buffers); } size_t YaAudioBusBuffers::num_channels() const { @@ -131,22 +108,19 @@ size_t YaAudioBusBuffers::num_channels() const { void YaAudioBusBuffers::write_back_outputs( Steinberg::Vst::AudioBusBuffers& output_buffers) const { output_buffers.silenceFlags = silence_flags; + std::visit( - overload{ - [&](const std::vector>& buffers) { - for (int channel = 0; channel < output_buffers.numChannels; - channel++) { + [&](const std::vector>& buffers) { + for (int channel = 0; channel < output_buffers.numChannels; + channel++) { + if constexpr (std::is_same_v) { std::copy(buffers[channel].begin(), buffers[channel].end(), output_buffers.channelBuffers64[channel]); - } - }, - [&](const std::vector>& buffers) { - for (int channel = 0; channel < output_buffers.numChannels; - channel++) { + } else { std::copy(buffers[channel].begin(), buffers[channel].end(), output_buffers.channelBuffers32[channel]); } - }, + } }, buffers); }