Reduce duplication in VST3 audio buffers

Using C++20 templated lambdas.
This commit is contained in:
Robbert van der Helm
2021-05-23 16:08:19 +02:00
parent d2965e048d
commit 0b2ce6a05f
+59 -85
View File
@@ -23,29 +23,25 @@ YaAudioBusBuffers::YaAudioBusBuffers() noexcept {}
void YaAudioBusBuffers::clear(int32 sample_size, void YaAudioBusBuffers::clear(int32 sample_size,
size_t num_samples, size_t num_samples,
size_t num_channels) { size_t num_channels) {
auto do_clear = [&]<typename T>(T) {
if (!std::holds_alternative<std::vector<std::vector<T>>>(buffers)) {
buffers.emplace<std::vector<std::vector<T>>>();
}
std::vector<std::vector<T>>& vector_buffers =
std::get<std::vector<std::vector<T>>>(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 (sample_size == Steinberg::Vst::SymbolicSampleSizes::kSample64) {
if (!std::holds_alternative<std::vector<std::vector<double>>>( // XXX: Clangd doesn't let you specify template parameters for templated
buffers)) { // lambdas. This argument should get optimized out
buffers.emplace<std::vector<std::vector<double>>>(); do_clear(double());
}
std::vector<std::vector<double>>& vector_buffers =
std::get<std::vector<std::vector<double>>>(buffers);
vector_buffers.resize(num_channels);
for (size_t i = 0; i < vector_buffers.size(); i++) {
vector_buffers[i].resize(num_samples);
}
} else { } else {
if (!std::holds_alternative<std::vector<std::vector<float>>>(buffers)) { do_clear(float());
buffers.emplace<std::vector<std::vector<float>>>();
}
std::vector<std::vector<float>>& vector_buffers =
std::get<std::vector<std::vector<float>>>(buffers);
vector_buffers.resize(num_channels);
for (size_t i = 0; i < vector_buffers.size(); i++) {
vector_buffers[i].resize(num_samples);
}
} }
} }
@@ -55,39 +51,26 @@ void YaAudioBusBuffers::repopulate(
const Steinberg::Vst::AudioBusBuffers& data) { const Steinberg::Vst::AudioBusBuffers& data) {
silence_flags = data.silenceFlags; silence_flags = data.silenceFlags;
switch (sample_size) { auto do_repopuldate = [&]<typename T>(T** original_buffer) {
case Steinberg::Vst::kSample64: { if (!std::holds_alternative<std::vector<std::vector<T>>>(buffers)) {
if (!std::holds_alternative<std::vector<std::vector<double>>>( buffers.emplace<std::vector<std::vector<T>>>();
buffers)) { }
buffers.emplace<std::vector<std::vector<double>>>();
}
std::vector<std::vector<double>>& vector_buffers = std::vector<std::vector<T>>& vector_buffers =
std::get<std::vector<std::vector<double>>>(buffers); std::get<std::vector<std::vector<T>>>(buffers);
vector_buffers.resize(data.numChannels); vector_buffers.resize(data.numChannels);
for (int channel = 0; channel < data.numChannels; channel++) { for (int channel = 0; channel < data.numChannels; channel++) {
vector_buffers[channel].assign( vector_buffers[channel].assign(
&data.channelBuffers64[channel][0], &original_buffer[channel][0],
&data.channelBuffers64[channel][num_samples]); &original_buffer[channel][num_samples]);
} }
} break; };
case Steinberg::Vst::kSample32:
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 // I don't think they'll add any other sample sizes any time soon
default: { do_repopuldate(data.channelBuffers32);
if (!std::holds_alternative<std::vector<std::vector<float>>>(
buffers)) {
buffers.emplace<std::vector<std::vector<float>>>();
}
std::vector<std::vector<float>>& vector_buffers =
std::get<std::vector<std::vector<float>>>(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;
} }
} }
@@ -96,31 +79,25 @@ void YaAudioBusBuffers::reconstruct(
// We'll update the `AudioBusBuffers` object in place to point to our new // We'll update the `AudioBusBuffers` object in place to point to our new
// data // data
reconstructed_buffers.silenceFlags = silence_flags; reconstructed_buffers.silenceFlags = silence_flags;
std::visit(overload{
[&](std::vector<std::vector<double>>& buffers) {
buffer_pointers.resize(buffers.size());
for (size_t i = 0; i < buffers.size(); i++) {
buffer_pointers[i] = buffers[i].data();
}
reconstructed_buffers.numChannels = std::visit(
static_cast<int32>(buffers.size()); [&]<typename T>(std::vector<std::vector<T>>& buffers) {
reconstructed_buffers.channelBuffers64 = buffer_pointers.resize(buffers.size());
reinterpret_cast<double**>(buffer_pointers.data()); for (size_t i = 0; i < buffers.size(); i++) {
}, buffer_pointers[i] = buffers[i].data();
[&](std::vector<std::vector<float>>& buffers) { }
buffer_pointers.resize(buffers.size());
for (size_t i = 0; i < buffers.size(); i++) {
buffer_pointers[i] = buffers[i].data();
}
reconstructed_buffers.numChannels = reconstructed_buffers.numChannels =
static_cast<int32>(buffers.size()); static_cast<int32>(buffers.size());
reconstructed_buffers.channelBuffers32 = if constexpr (std::is_same_v<T, double>) {
reinterpret_cast<float**>(buffer_pointers.data()); reconstructed_buffers.channelBuffers64 =
}, reinterpret_cast<T**>(buffer_pointers.data());
}, } else {
buffers); reconstructed_buffers.channelBuffers32 =
reinterpret_cast<T**>(buffer_pointers.data());
}
},
buffers);
} }
size_t YaAudioBusBuffers::num_channels() const { size_t YaAudioBusBuffers::num_channels() const {
@@ -131,22 +108,19 @@ size_t YaAudioBusBuffers::num_channels() const {
void YaAudioBusBuffers::write_back_outputs( void YaAudioBusBuffers::write_back_outputs(
Steinberg::Vst::AudioBusBuffers& output_buffers) const { Steinberg::Vst::AudioBusBuffers& output_buffers) const {
output_buffers.silenceFlags = silence_flags; output_buffers.silenceFlags = silence_flags;
std::visit( std::visit(
overload{ [&]<typename T>(const std::vector<std::vector<T>>& buffers) {
[&](const std::vector<std::vector<double>>& buffers) { for (int channel = 0; channel < output_buffers.numChannels;
for (int channel = 0; channel < output_buffers.numChannels; channel++) {
channel++) { if constexpr (std::is_same_v<T, double>) {
std::copy(buffers[channel].begin(), buffers[channel].end(), std::copy(buffers[channel].begin(), buffers[channel].end(),
output_buffers.channelBuffers64[channel]); output_buffers.channelBuffers64[channel]);
} } else {
},
[&](const std::vector<std::vector<float>>& buffers) {
for (int channel = 0; channel < output_buffers.numChannels;
channel++) {
std::copy(buffers[channel].begin(), buffers[channel].end(), std::copy(buffers[channel].begin(), buffers[channel].end(),
output_buffers.channelBuffers32[channel]); output_buffers.channelBuffers32[channel]);
} }
}, }
}, },
buffers); buffers);
} }