mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Change audio SHM buffer offsets to be in bytes
CLAP allows mixed precision ports. For instance, the main IO ports can be 32-bit only, while some CV ports allow 64-bit audio. The plugin only knows the sample format it receives when the process call happens, so we'll always need to allocate enough space for that to work.
This commit is contained in:
+18
-13
@@ -75,17 +75,22 @@ class AudioShmBuffer {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offsets **in samples** within the shared memory object for an input
|
* Offsets **in bytes** within the shared memory object for an input
|
||||||
* audio channel, indexed by `[bus][channel]`. For VST2 plugins the bus
|
* audio channel, indexed by `[bus][channel]`. For VST2 plugins the bus
|
||||||
* will always be 0. This can be used later to retrieve a pointer to the
|
* will always be 0. This can be used later to retrieve a pointer to the
|
||||||
* audio channel.
|
* audio channel.
|
||||||
|
*
|
||||||
|
* The offsets are in bytes rather than in samples to accommodate mixed
|
||||||
|
* 32-bit and 64-bit IO. This is allowed in CLAP. If a port can do
|
||||||
|
* either 32-bit or 64-bit audio, we'll reserve enough space for 64-bit
|
||||||
|
* samples and then just not use the latter half if the host ends up
|
||||||
|
* using 32-bit samples.
|
||||||
*/
|
*/
|
||||||
std::vector<std::vector<uint32_t>> input_offsets;
|
std::vector<std::vector<uint32_t>> input_offsets;
|
||||||
/**
|
/**
|
||||||
* Offsets **in samples** within the shared memory object for an output
|
* Offsets **in bytes** within the shared memory object for an output
|
||||||
* audio channel, indexed by `[bus][channel]`. For VST2 plugins the bus
|
* audio channel, indexed by `[bus][channel]`. See `input_offsets` for
|
||||||
* will always be 0. This can be used later to retrieve a pointer to the
|
* more details.
|
||||||
* audio channel.
|
|
||||||
*/
|
*/
|
||||||
std::vector<std::vector<uint32_t>> output_offsets;
|
std::vector<std::vector<uint32_t>> output_offsets;
|
||||||
|
|
||||||
@@ -151,16 +156,16 @@ class AudioShmBuffer {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||||
T* input_channel_ptr(const uint32_t bus, const uint32_t channel) noexcept {
|
T* input_channel_ptr(const uint32_t bus, const uint32_t channel) noexcept {
|
||||||
return reinterpret_cast<T*>(shm_bytes_) +
|
return reinterpret_cast<T*>(shm_bytes_ +
|
||||||
config_.input_offsets[bus][channel];
|
config_.input_offsets[bus][channel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||||
const T* input_channel_ptr(const uint32_t bus,
|
const T* input_channel_ptr(const uint32_t bus,
|
||||||
const uint32_t channel) const noexcept {
|
const uint32_t channel) const noexcept {
|
||||||
return reinterpret_cast<const T*>(shm_bytes_) +
|
return reinterpret_cast<const T*>(shm_bytes_ +
|
||||||
config_.input_offsets[bus][channel];
|
config_.input_offsets[bus][channel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,16 +176,16 @@ class AudioShmBuffer {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||||
T* output_channel_ptr(const uint32_t bus, const uint32_t channel) noexcept {
|
T* output_channel_ptr(const uint32_t bus, const uint32_t channel) noexcept {
|
||||||
return reinterpret_cast<T*>(shm_bytes_) +
|
return reinterpret_cast<T*>(shm_bytes_ +
|
||||||
config_.output_offsets[bus][channel];
|
config_.output_offsets[bus][channel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||||
const T* output_channel_ptr(const uint32_t bus,
|
const T* output_channel_ptr(const uint32_t bus,
|
||||||
const uint32_t channel) const noexcept {
|
const uint32_t channel) const noexcept {
|
||||||
return reinterpret_cast<const T*>(shm_bytes_) +
|
return reinterpret_cast<const T*>(shm_bytes_ +
|
||||||
config_.output_offsets[bus][channel];
|
config_.output_offsets[bus][channel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Config config_;
|
Config config_;
|
||||||
|
|||||||
@@ -795,30 +795,34 @@ intptr_t Vst2Bridge::dispatch_wrapper(AEffect* plugin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioShmBuffer::Config Vst2Bridge::setup_shared_audio_buffers() {
|
AudioShmBuffer::Config Vst2Bridge::setup_shared_audio_buffers() {
|
||||||
|
assert(max_samples_per_block_);
|
||||||
|
|
||||||
// We'll first compute the size and channel offsets for our buffer based on
|
// We'll first compute the size and channel offsets for our buffer based on
|
||||||
// the information already passed to us by the host. The offsets for each
|
// the information already passed to us by the host. The offsets for each
|
||||||
// audio channel are in samples (since they'll be used with pointer
|
// audio channel are in bytes because CLAP allows some ports to be 32-bit
|
||||||
// arithmetic in `AudioShmBuffer`), and we'll only use the first bus (since
|
// only while other others are mixed 32-bit and 64-bit if the plugin opts in
|
||||||
// VST2 plugins don't have multiple audio busses).
|
// to it, and the plugin only knows what format it receives during the
|
||||||
assert(max_samples_per_block_);
|
// process call.
|
||||||
|
const size_t sample_size =
|
||||||
|
(double_precision_ ? sizeof(double) : sizeof(float));
|
||||||
|
|
||||||
uint32_t current_offset = 0;
|
uint32_t current_offset = 0;
|
||||||
|
|
||||||
std::vector<uint32_t> input_channel_offsets(plugin_->numInputs);
|
std::vector<uint32_t> input_channel_offsets(plugin_->numInputs);
|
||||||
for (int channel = 0; channel < plugin_->numInputs; channel++) {
|
for (int channel = 0; channel < plugin_->numInputs; channel++) {
|
||||||
input_channel_offsets[channel] = current_offset;
|
input_channel_offsets[channel] = current_offset;
|
||||||
current_offset += *max_samples_per_block_;
|
current_offset += *max_samples_per_block_ * sample_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> output_channel_offsets(plugin_->numOutputs);
|
std::vector<uint32_t> output_channel_offsets(plugin_->numOutputs);
|
||||||
for (int channel = 0; channel < plugin_->numOutputs; channel++) {
|
for (int channel = 0; channel < plugin_->numOutputs; channel++) {
|
||||||
output_channel_offsets[channel] = current_offset;
|
output_channel_offsets[channel] = current_offset;
|
||||||
current_offset += *max_samples_per_block_;
|
current_offset += *max_samples_per_block_ * sample_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The size of the buffer is in bytes, and it will depend on whether the
|
// The size of the buffer is in bytes, and it will depend on whether the
|
||||||
// host is going to pass 32-bit or 64-bit audio to the plugin
|
// host is going to pass 32-bit or 64-bit audio to the plugin
|
||||||
const uint32_t buffer_size =
|
const uint32_t buffer_size = current_offset;
|
||||||
current_offset * (double_precision_ ? sizeof(double) : sizeof(float));
|
|
||||||
|
|
||||||
// We'll set up these shared memory buffers on the Wine side first, and then
|
// We'll set up these shared memory buffers on the Wine side first, and then
|
||||||
// when this request returns we'll do the same thing on the native plugin
|
// when this request returns we'll do the same thing on the native plugin
|
||||||
|
|||||||
@@ -1376,8 +1376,15 @@ std::optional<AudioShmBuffer::Config> Vst3Bridge::setup_shared_audio_buffers(
|
|||||||
|
|
||||||
// We'll query the plugin for its audio bus layouts, and then create
|
// We'll query the plugin for its audio bus layouts, and then create
|
||||||
// calculate the offsets in a large memory buffer for the different audio
|
// calculate the offsets in a large memory buffer for the different audio
|
||||||
// channels. The offsets for each audio channel are in samples (since
|
// channels. The offsets for each audio channel are in bytes because CLAP
|
||||||
// they'll be used with pointer arithmetic in `AudioShmBuffer`).
|
// allows some ports to be 32-bit only while other others are mixed 32-bit
|
||||||
|
// and 64-bit if the plugin opts in to it, and the plugin only knows what
|
||||||
|
// format it receives during the process call.
|
||||||
|
const bool double_precision =
|
||||||
|
instance.process_setup->symbolicSampleSize == Steinberg::Vst::kSample64;
|
||||||
|
const size_t sample_size =
|
||||||
|
(double_precision ? sizeof(double) : sizeof(float));
|
||||||
|
|
||||||
uint32_t current_offset = 0;
|
uint32_t current_offset = 0;
|
||||||
|
|
||||||
auto create_bus_offsets = [&, &setup = instance.process_setup](
|
auto create_bus_offsets = [&, &setup = instance.process_setup](
|
||||||
@@ -1404,7 +1411,7 @@ std::optional<AudioShmBuffer::Config> Vst3Bridge::setup_shared_audio_buffers(
|
|||||||
|
|
||||||
for (size_t channel = 0; channel < num_channels; channel++) {
|
for (size_t channel = 0; channel < num_channels; channel++) {
|
||||||
bus_offsets[bus][channel] = current_offset;
|
bus_offsets[bus][channel] = current_offset;
|
||||||
current_offset += setup->maxSamplesPerBlock;
|
current_offset += setup->maxSamplesPerBlock * sample_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1419,10 +1426,7 @@ std::optional<AudioShmBuffer::Config> Vst3Bridge::setup_shared_audio_buffers(
|
|||||||
|
|
||||||
// The size of the buffer is in bytes, and it will depend on whether the
|
// The size of the buffer is in bytes, and it will depend on whether the
|
||||||
// host is going to pass 32-bit or 64-bit audio to the plugin
|
// host is going to pass 32-bit or 64-bit audio to the plugin
|
||||||
const bool double_precision =
|
const uint32_t buffer_size = current_offset;
|
||||||
instance.process_setup->symbolicSampleSize == Steinberg::Vst::kSample64;
|
|
||||||
const uint32_t buffer_size =
|
|
||||||
current_offset * (double_precision ? sizeof(double) : sizeof(float));
|
|
||||||
|
|
||||||
// If this function has been called previously and the size did not change,
|
// If this function has been called previously and the size did not change,
|
||||||
// then we should not do any work
|
// then we should not do any work
|
||||||
|
|||||||
Reference in New Issue
Block a user