int process()

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;
  }