Implement writing back YaProcessDataResponse

Everything around `ProcessData` is now fully implemented and should in
theory work.
This commit is contained in:
Robbert van der Helm
2020-12-16 18:14:28 +01:00
parent 6f38f8400c
commit 2bf98d0a97
9 changed files with 107 additions and 2 deletions
+2
View File
@@ -26,6 +26,8 @@ incomplete list of things that still have to be done before this can be used:
- Fully implemented:
- `GetPluginFactory()` and `IPluginFactory{,2,3}`
- `IPluginBase` and `IComponent`
- Everything surrounding `ProcessData`, `ProcessingContext` and
`AudioBusBuffers`
- `IParameterChanges`, `IParamValueQueue`, `IEventList`, and all event types
in VST 3.7.1
- `IBStream`
@@ -194,6 +194,17 @@ YaEventList::~YaEventList() {
FUNKNOWN_DTOR
}
void YaEventList::write_back_outputs(
Steinberg::Vst::IEventList& output_events) const {
// TODO: I assume the host is responsible for directly copying heap data
// (e.g. text) in these events and they're not supposed to stay
// around, right? If not, then we'll find out very quickly.
for (auto& event : events) {
Steinberg::Vst::Event reconstructed_event = event.get();
output_events.addEvent(reconstructed_event);
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
IMPLEMENT_FUNKNOWN_METHODS(YaEventList,
@@ -227,6 +227,12 @@ class YaEventList : public Steinberg::Vst::IEventList {
DECLARE_FUNKNOWN_METHODS
/**
* Write these events an output events queue on the `ProcessData` object
* provided by the host.
*/
void write_back_outputs(Steinberg::Vst::IEventList& output_events) const;
// From `IEventList`
virtual int32 PLUGIN_API getEventCount() override;
virtual tresult PLUGIN_API
@@ -47,6 +47,16 @@ IMPLEMENT_FUNKNOWN_METHODS(YaParamValueQueue,
Steinberg::Vst::IParamValueQueue::iid)
#pragma GCC diagnostic pop
void YaParamValueQueue::write_back_outputs(
Steinberg::Vst::IParamValueQueue& output_queue) const {
// We don't need this value
int32 index;
for (const auto& [sample_offset, value] : queue) {
// We don't check for `kResultOk` here
output_queue.addPoint(sample_offset, value, index);
}
}
Steinberg::Vst::ParamID PLUGIN_API YaParamValueQueue::getParameterId() {
return parameter_id;
}
@@ -51,6 +51,13 @@ class YaParamValueQueue : public Steinberg::Vst::IParamValueQueue {
DECLARE_FUNKNOWN_METHODS
/**
* Write this queue back the output parameter changes object on the
* `ProcessData` object provided by the host.
*/
void write_back_outputs(
Steinberg::Vst::IParamValueQueue& output_queue) const;
// From `IParamValueQueue`
Steinberg::Vst::ParamID PLUGIN_API getParameterId() override;
int32 PLUGIN_API getPointCount() override;
@@ -72,12 +79,12 @@ class YaParamValueQueue : public Steinberg::Vst::IParamValueQueue {
});
}
private:
/**
* For `IParamValueQueue::getParameterId`.
*/
Steinberg::Vst::ParamID parameter_id;
private:
/**
* The actual parameter changes queue. The specification doesn't mention
* that this should be a priority queue or something, but I'd assume both
@@ -41,6 +41,19 @@ IMPLEMENT_FUNKNOWN_METHODS(YaParameterChanges,
Steinberg::Vst::IParameterChanges::iid)
#pragma GCC diagnostic pop
void YaParameterChanges::write_back_outputs(
Steinberg::Vst::IParameterChanges& output_queues) const {
for (auto& queue : queues) {
// We don't need this, but the SDK requires us to need this
int32 output_queue_index;
if (Steinberg::Vst::IParamValueQueue* output_queue =
output_queues.addParameterData(queue.parameter_id,
output_queue_index)) {
queue.write_back_outputs(*output_queue);
}
}
}
int32 PLUGIN_API YaParameterChanges::getParameterCount() {
return queues.size();
}
@@ -45,6 +45,13 @@ class YaParameterChanges : public Steinberg::Vst::IParameterChanges {
DECLARE_FUNKNOWN_METHODS
/**
* Write these changes back to an output parameter changes queue on the
* `ProcessData` object provided by the host.
*/
void write_back_outputs(
Steinberg::Vst::IParameterChanges& output_queues) const;
// From `IParameterChanges`
int32 PLUGIN_API getParameterCount() override;
Steinberg::Vst::IParamValueQueue* PLUGIN_API
@@ -92,6 +92,45 @@ Steinberg::Vst::AudioBusBuffers YaAudioBusBuffers::get() {
return reconstructed_buffers;
}
void YaAudioBusBuffers::write_back_outputs(
Steinberg::Vst::AudioBusBuffers& output_buffers) const {
output_buffers.silenceFlags = silence_flags;
std::visit(
overload{
[&](const std::vector<std::vector<double>>& buffers) {
for (int channel = 0; channel < output_buffers.numChannels;
channel++) {
std::copy(buffers[channel].begin(), buffers[channel].end(),
output_buffers.channelBuffers64[channel]);
}
},
[&](const std::vector<std::vector<float>>& buffers) {
for (int channel = 0; channel < output_buffers.numChannels;
channel++) {
std::copy(buffers[channel].begin(), buffers[channel].end(),
output_buffers.channelBuffers32[channel]);
}
},
},
buffers);
}
void YaProcessDataResponse::write_back_outputs(
Steinberg::Vst::ProcessData& process_data) {
for (int i = 0; i < process_data.numOutputs; i++) {
outputs[i].write_back_outputs(process_data.outputs[i]);
}
if (output_parameter_changes && process_data.outputParameterChanges) {
output_parameter_changes->write_back_outputs(
*process_data.outputParameterChanges);
}
if (output_events && process_data.outputEvents) {
output_events->write_back_outputs(*process_data.outputEvents);
}
}
YaProcessData::YaProcessData() {}
YaProcessData::YaProcessData(const Steinberg::Vst::ProcessData& process_data)
+11 -1
View File
@@ -72,6 +72,13 @@ class YaAudioBusBuffers {
*/
Steinberg::Vst::AudioBusBuffers get();
/**
* Write these buffers and the silence flag back to an `AudioBusBuffers
* object provided by the host.
*/
void write_back_outputs(
Steinberg::Vst::AudioBusBuffers& output_buffers) const;
template <typename S>
void serialize(S& s) {
s.value8b(silence_flags);
@@ -134,7 +141,10 @@ struct YaProcessDataResponse {
std::optional<YaParameterChanges> output_parameter_changes;
std::optional<YaEventList> output_events;
// TODO: Add function to write these back to the host's `ProcessData`
/**
* Write all of this output data back to the host's `ProcessData` object.
*/
void write_back_outputs(Steinberg::Vst::ProcessData& process_data);
template <typename S>
void serialize(S& s) {