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.");
}