void processSamples()

in pedalboard/juce_overrides/juce_BlockingConvolution.cpp [107:193]


  void processSamples(const float *input, float *output, size_t numSamples) {
    // Overlap-add, zero latency convolution algorithm with uniform partitioning
    size_t numSamplesProcessed = 0;

    auto indexStep = numInputSegments / numSegments;

    auto *inputData = bufferInput.getWritePointer(0);
    auto *outputTempData = bufferTempOutput.getWritePointer(0);
    auto *outputData = bufferOutput.getWritePointer(0);
    auto *overlapData = bufferOverlap.getWritePointer(0);

    while (numSamplesProcessed < numSamples) {
      const bool inputDataWasEmpty = (inputDataPos == 0);
      auto numSamplesToProcess =
          jmin(numSamples - numSamplesProcessed, blockSize - inputDataPos);

      FloatVectorOperations::copy(inputData + inputDataPos,
                                  input + numSamplesProcessed,
                                  static_cast<int>(numSamplesToProcess));

      auto *inputSegmentData =
          buffersInputSegments[currentSegment].getWritePointer(0);
      FloatVectorOperations::copy(inputSegmentData, inputData,
                                  static_cast<int>(fftSize));

      fftObject->performRealOnlyForwardTransform(inputSegmentData);
      prepareForConvolution(inputSegmentData);

      // Complex multiplication
      if (inputDataWasEmpty) {
        FloatVectorOperations::fill(outputTempData, 0,
                                    static_cast<int>(fftSize + 1));

        auto index = currentSegment;

        for (size_t i = 1; i < numSegments; ++i) {
          index += indexStep;

          if (index >= numInputSegments)
            index -= numInputSegments;

          convolutionProcessingAndAccumulate(
              buffersInputSegments[index].getWritePointer(0),
              buffersImpulseSegments[i].getWritePointer(0), outputTempData);
        }
      }

      FloatVectorOperations::copy(outputData, outputTempData,
                                  static_cast<int>(fftSize + 1));

      convolutionProcessingAndAccumulate(
          inputSegmentData, buffersImpulseSegments.front().getWritePointer(0),
          outputData);

      updateSymmetricFrequencyDomainData(outputData);
      fftObject->performRealOnlyInverseTransform(outputData);

      // Add overlap
      FloatVectorOperations::add(
          &output[numSamplesProcessed], &outputData[inputDataPos],
          &overlapData[inputDataPos], (int)numSamplesToProcess);

      // Input buffer full => Next block
      inputDataPos += numSamplesToProcess;

      if (inputDataPos == blockSize) {
        // Input buffer is empty again now
        FloatVectorOperations::fill(inputData, 0.0f, static_cast<int>(fftSize));

        inputDataPos = 0;

        // Extra step for segSize > blockSize
        FloatVectorOperations::add(&(outputData[blockSize]),
                                   &(overlapData[blockSize]),
                                   static_cast<int>(fftSize - 2 * blockSize));

        // Save the overlap
        FloatVectorOperations::copy(overlapData, &(outputData[blockSize]),
                                    static_cast<int>(fftSize - blockSize));

        currentSegment = (currentSegment > 0) ? (currentSegment - 1)
                                              : (numInputSegments - 1);
      }

      numSamplesProcessed += numSamplesToProcess;
    }
  }