inline void init_stream_resampler()

in pedalboard/io/StreamResampler.h [301:420]


inline void init_stream_resampler(py::module &m) {
  py::class_<StreamResampler<float>, std::shared_ptr<StreamResampler<float>>>
      resampler(
          m, "StreamResampler",
          "A streaming resampler that can change the sample rate of multiple "
          "chunks of audio in series, while using constant memory.\n\nFor a "
          "resampling plug-in that can be used in :class:`Pedalboard` objects, "
          "see :class:`pedalboard.Resample`.\n\n*Introduced in v0.6.0.*");

  resampler.def(
      py::init([](float sourceSampleRate, float targetSampleRate,
                  int numChannels, ResamplingQuality quality) {
        return std::make_unique<StreamResampler<float>>(
            sourceSampleRate, targetSampleRate, numChannels, quality);
      }),
      py::arg("source_sample_rate"), py::arg("target_sample_rate"),
      py::arg("num_channels"),
      py::arg("quality") = ResamplingQuality::WindowedSinc32,
      "Create a new StreamResampler, capable of resampling a "
      "potentially-unbounded audio stream with a constant amount of memory. "
      "The source sample rate, target sample rate, quality, or number of "
      "channels cannot be changed once the resampler is instantiated.");

  resampler.def("__repr__", [](const StreamResampler<float> &resampler) {
    std::ostringstream ss;
    ss << "<pedalboard.io.StreamResampler";

    ss << " source_sample_rate=" << resampler.getSourceSampleRate();
    ss << " target_sample_rate=" << resampler.getTargetSampleRate();
    ss << " num_channels=" << resampler.getNumChannels();
    ss << " quality=";

    switch (resampler.getQuality()) {
    case ResamplingQuality::ZeroOrderHold:
      ss << "ZeroOrderHold";
      break;
    case ResamplingQuality::Linear:
      ss << "Linear";
      break;
    case ResamplingQuality::CatmullRom:
      ss << "CatmullRom";
      break;
    case ResamplingQuality::Lagrange:
      ss << "Lagrange";
      break;
    case ResamplingQuality::WindowedSinc:
      ss << "WindowedSinc";
      break;
    default:
      ss << "unknown";
      break;
    }

    ss << " at " << &resampler;
    ss << ">";
    return ss.str();
  });

  resampler.def(
      "process",
      [](StreamResampler<float> &resampler,
         std::optional<py::array_t<float, py::array::c_style>> input) {
        std::optional<juce::AudioBuffer<float>> inputBuffer;
        if (input) {
          std::optional<ChannelLayout> layout =
              resampler.getLastChannelLayout();
          if (!layout) {
            try {
              layout = detectChannelLayout(*input);
              resampler.setLastChannelLayout(*layout);
            } catch (...) {
              // Use the last cached layout.
            }
          }
          inputBuffer = convertPyArrayIntoJuceBuffer(*input, *layout);
        }

        juce::AudioBuffer<float> output;
        {
          py::gil_scoped_release release;
          output = resampler.process(inputBuffer);
        }

        return copyJuceBufferIntoPyArray(output,
                                         *resampler.getLastChannelLayout(), 0);
      },
      py::arg("input") = py::none(),
      "Resample a 32-bit floating-point audio buffer. The returned buffer may "
      "be smaller than the provided buffer depending on the quality method "
      "used. Call :meth:`process()` without any arguments to flush the "
      "internal buffers and return all remaining audio.");

  resampler.def("reset", &StreamResampler<float>::reset,
                "Used to reset the internal state of this resampler. Call this "
                "method when resampling a new audio stream to prevent audio "
                "from leaking between streams.");

  resampler.def_property_readonly("num_channels",
                                  &StreamResampler<float>::getNumChannels,
                                  "The number of channels expected to be "
                                  "passed in every call to :meth:`process()`.");
  resampler.def_property_readonly(
      "source_sample_rate", &StreamResampler<float>::getSourceSampleRate,
      "The source sample rate of the input audio that this resampler expects "
      "to be passed to :meth:`process()`.");

  resampler.def_property_readonly(
      "target_sample_rate", &StreamResampler<float>::getTargetSampleRate,
      "The sample rate of the audio that this resampler will return from "
      ":meth:`process()`.");

  resampler.def_property_readonly(
      "quality", &StreamResampler<float>::getQuality,
      "The resampling algorithm used by this resampler.");

  resampler.def_property_readonly(
      "input_latency", &StreamResampler<float>::getInputLatency,
      "The number of samples (in the input sample rate) that must be supplied "
      "before this resampler will begin returning output.");
}