in pedalboard/ExternalPlugin.h [1147:1225]
int process(
const juce::dsp::ProcessContextReplacing<float> &context) override {
if (pluginInstance) {
juce::MidiBuffer emptyMidiBuffer;
if (pluginInstance->getMainBusNumInputChannels() == 0 &&
context.getInputBlock().getNumChannels() > 0) {
throw std::invalid_argument(
"Plugin '" + pluginInstance->getName().toStdString() +
"' does not accept audio input. It may be an instrument plugin "
"instead of an effect plugin.");
}
const juce::dsp::AudioBlock<const float> &inputBlock =
context.getInputBlock();
juce::dsp::AudioBlock<float> &outputBlock = context.getOutputBlock();
if ((size_t)pluginInstance->getMainBusNumInputChannels() !=
inputBlock.getNumChannels()) {
throw std::invalid_argument(
"Plugin '" + pluginInstance->getName().toStdString() +
"' was instantiated with " +
std::to_string(pluginInstance->getMainBusNumInputChannels()) +
"-channel input, but provided audio data contained " +
std::to_string(inputBlock.getNumChannels()) + " channel" +
(inputBlock.getNumChannels() == 1 ? "" : "s") + ".");
}
if ((size_t)pluginInstance->getMainBusNumOutputChannels() <
inputBlock.getNumChannels()) {
throw std::invalid_argument(
"Plugin '" + pluginInstance->getName().toStdString() +
"' produces " +
std::to_string(pluginInstance->getMainBusNumOutputChannels()) +
"-channel output, but provided audio data contained " +
std::to_string(inputBlock.getNumChannels()) + " channel" +
(inputBlock.getNumChannels() == 1 ? " " : "s") +
". (The number of channels returned must match the "
"number of channels passed in.)");
}
std::vector<float *> channelPointers(
pluginInstance->getTotalNumOutputChannels());
for (size_t i = 0; i < outputBlock.getNumChannels(); i++) {
channelPointers[i] = outputBlock.getChannelPointer(i);
}
// Depending on the bus layout, we may have to pass extra buffers to the
// plugin that we don't use. Use vector here to ensure the memory is
// freed via RAII.
std::vector<std::vector<float>> dummyChannels;
for (size_t i = outputBlock.getNumChannels(); i < channelPointers.size();
i++) {
std::vector<float> dummyChannel(outputBlock.getNumSamples());
channelPointers[i] = dummyChannel.data();
dummyChannels.push_back(std::move(dummyChannel));
}
// Create an audio buffer that doesn't actually allocate anything, but
// just points to the data in the ProcessContext.
juce::AudioBuffer<float> audioBuffer(channelPointers.data(),
channelPointers.size(),
outputBlock.getNumSamples());
pluginInstance->processBlock(audioBuffer, emptyMidiBuffer);
samplesProvided += outputBlock.getNumSamples();
// To compensate for any latency added by the plugin,
// only tell Pedalboard to use the last _n_ samples.
long usableSamplesProduced =
std::max(0L, samplesProvided - pluginInstance->getLatencySamples());
return static_cast<int>(
std::min(usableSamplesProduced, (long)outputBlock.getNumSamples()));
}
return 0;
}