in pedalboard/ExternalPlugin.h [1424:2078]
inline void init_external_plugins(py::module &m) {
py::enum_<ExternalPluginReloadType>(
m, "ExternalPluginReloadType",
"Indicates the behavior of an external plugin when reset() is called.")
.value("Unknown", ExternalPluginReloadType::Unknown,
"The behavior of the plugin is unknown. This will force a full "
"reinstantiation of the plugin every time reset is called.")
.value(
"ClearsAudioOnReset", ExternalPluginReloadType::ClearsAudioOnReset,
"This plugin clears its internal buffers correctly when reset() is "
"called. The plugin will not be reinstantiated when reset is called.")
.value("PersistsAudioOnReset",
ExternalPluginReloadType::PersistsAudioOnReset,
"This plugin does not clear its internal buffers as expected when "
"reset() is called. This will force a full reinstantiation of the "
"plugin every time reset is called.")
.export_values();
py::class_<juce::AudioProcessorParameter>(
m, "_AudioProcessorParameter",
"An abstract base class for parameter objects that can be added to an "
"AudioProcessor.")
.def("__repr__",
[](juce::AudioProcessorParameter ¶meter) {
std::ostringstream ss;
ss << "<pedalboard.AudioProcessorParameter";
ss << " name=\"" << parameter.getName(512).toStdString() << "\"";
if (!parameter.getLabel().isEmpty())
ss << " label=\"" << parameter.getLabel().toStdString() << "\"";
if (parameter.isBoolean())
ss << " boolean";
if (parameter.isDiscrete())
ss << " discrete";
ss << " raw_value=" << parameter.getValue();
ss << ">";
return ss.str();
})
.def_property(
"raw_value", &juce::AudioProcessorParameter::getValue,
&juce::AudioProcessorParameter::setValue,
"The internal value of this parameter. Convention is that this "
"parameter should be between 0 and 1.0. This may or may not "
"correspond with the value shown to the user.")
.def_property_readonly(
"default_raw_value", &juce::AudioProcessorParameter::getDefaultValue,
"The default internal value of this parameter. Convention is that "
"this parameter should be between 0 and 1.0. This may or may not "
"correspond with the value shown to the user.")
.def(
"get_name",
[](juce::AudioProcessorParameter ¶m, int length) {
return param.getName(length).toStdString();
},
py::arg("maximum_string_length"),
"Returns the name to display for this parameter, which is made to "
"fit within the given string length")
.def_property_readonly(
"name",
[](juce::AudioProcessorParameter ¶m) {
return param.getName(512).toStdString();
},
"Returns the name to display for this parameter at its longest.")
.def_property_readonly(
"label",
[](juce::AudioProcessorParameter ¶m) {
return param.getLabel().toStdString();
},
"Some parameters may be able to return a label string for their "
"units. For example \"Hz\" or \"%\".")
.def_property_readonly(
"num_steps", &juce::AudioProcessorParameter::getNumSteps,
"Returns the number of steps that this parameter's range should be "
"quantised into. See also: is_discrete, is_boolean.")
.def_property_readonly("is_discrete",
&juce::AudioProcessorParameter::isDiscrete,
"Returns whether the parameter uses discrete "
"values, based on the result of getNumSteps, or "
"allows the host to select values continuously.")
.def_property_readonly(
"is_boolean", &juce::AudioProcessorParameter::isBoolean,
"Returns whether the parameter represents a boolean switch, "
"typically with \"On\" and \"Off\" states.")
.def(
"get_text_for_raw_value",
[](juce::AudioProcessorParameter ¶m, float value,
int maximumStringLength) {
return param.getText(value, maximumStringLength).toStdString();
},
py::arg("raw_value"), py::arg("maximum_string_length") = 512,
"Returns a textual version of the supplied normalised parameter "
"value.")
.def(
"get_raw_value_for_text",
[](juce::AudioProcessorParameter ¶m, std::string &text) {
return param.getValueForText(text);
},
py::arg("string_value"),
"Returns the raw value of the supplied text. Plugins may handle "
"errors however they see fit, but will likely not raise "
"exceptions.")
.def_property_readonly(
"is_orientation_inverted",
&juce::AudioProcessorParameter::isOrientationInverted,
"If true, this parameter operates in the reverse direction. (Not "
"all plugin formats will actually use this information).")
.def_property_readonly("is_automatable",
&juce::AudioProcessorParameter::isAutomatable,
"Returns true if this parameter can be automated.")
.def_property_readonly("is_automatable",
&juce::AudioProcessorParameter::isAutomatable,
"Returns true if this parameter can be "
"automated (i.e.: scheduled to "
"change over time, in real-time, in a DAW).")
.def_property_readonly(
"is_meta_parameter", &juce::AudioProcessorParameter::isMetaParameter,
"A meta-parameter is a parameter that changes other parameters.")
.def_property_readonly(
"index", &juce::AudioProcessorParameter::getParameterIndex,
"The index of this parameter in its plugin's parameter list.")
.def_property_readonly(
"string_value",
[](juce::AudioProcessorParameter ¶m) {
return param.getCurrentValueAsText().toStdString();
},
"Returns the current value of the parameter as a string.");
py::object externalPlugin =
py::class_<AbstractExternalPlugin, Plugin,
std::shared_ptr<AbstractExternalPlugin>>(
m, "ExternalPlugin", py::dynamic_attr(),
"A wrapper around a third-party effect plugin.\n\nDon't use this "
"directly; use one of :class:`pedalboard.VST3Plugin` or "
":class:`pedalboard.AudioUnitPlugin` instead.")
.def(py::init([]() {
throw py::type_error(
"ExternalPlugin is an abstract base class - don't instantiate "
"this directly, use its subclasses instead.");
return nullptr;
}))
.def(
"process",
[](std::shared_ptr<AbstractExternalPlugin> self,
py::object midiMessages, float duration, float sampleRate,
unsigned int numChannels, unsigned long bufferSize,
bool reset) -> py::array_t<float> {
throw py::type_error("ExternalPlugin is an abstract base class "
"- use its subclasses instead.");
py::array_t<float> nothing;
return nothing;
},
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("midi_messages"),
py::arg("duration"), py::arg("sample_rate"),
py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def(
"process",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize,
reset);
},
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("input_array"),
py::arg("sample_rate"),
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def(
"__call__",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize,
reset);
},
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("input_array"), py::arg("sample_rate"),
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def(
"__call__",
[](std::shared_ptr<AbstractExternalPlugin> self,
py::object midiMessages, float duration, float sampleRate,
unsigned int numChannels, unsigned long bufferSize,
bool reset) -> py::array_t<float> {
throw py::type_error("ExternalPlugin is an abstract base class "
"- use its subclasses instead.");
py::array_t<float> nothing;
return nothing;
},
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("midi_messages"), py::arg("duration"),
py::arg("sample_rate"), py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true);
#if (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
py::class_<ExternalPlugin<juce::PatchedVST3PluginFormat>,
AbstractExternalPlugin,
std::shared_ptr<ExternalPlugin<juce::PatchedVST3PluginFormat>>>(
m, "VST3Plugin",
R"(A wrapper around third-party, audio effect or instrument plugins in
`Steinberg GmbH's VST3® <https://en.wikipedia.org/wiki/Virtual_Studio_Technology>`_
format.
VST3® plugins are supported on macOS, Windows, and Linux. However, VST3® plugin
files are not cross-compatible with different operating systems; a platform-specific
build of each plugin is required to load that plugin on a given platform. (For
example: a Windows VST3 plugin bundle will not load on Linux or macOS.)
.. warning::
Some VST3® plugins may throw errors, hang, generate incorrect output, or
outright crash if called from background threads. If you find that a VST3®
plugin is not working as expected, try calling it from the main thread
instead and `open a GitHub Issue to track the incompatibility
<https://github.com/spotify/pedalboard/issues/new>`_.
*Support for instrument plugins introduced in v0.7.4.*
*Support for running VST3® plugins on background threads introduced in v0.8.8.*
)")
.def(
py::init([](std::string &pathToPluginFile, py::object parameterValues,
std::optional<std::string> pluginName,
float initializationTimeout) {
std::shared_ptr<ExternalPlugin<juce::PatchedVST3PluginFormat>>
plugin = std::make_shared<
ExternalPlugin<juce::PatchedVST3PluginFormat>>(
pathToPluginFile, pluginName, initializationTimeout);
py::cast(plugin).attr("__set_initial_parameter_values__")(
parameterValues);
return plugin;
}),
py::arg("path_to_plugin_file"),
py::arg("parameter_values") = py::none(),
py::arg("plugin_name") = py::none(),
py::arg("initialization_timeout") =
DEFAULT_INITIALIZATION_TIMEOUT_SECONDS)
.def("__repr__",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
std::ostringstream ss;
ss << "<pedalboard.VST3Plugin";
ss << " \"" << plugin.getName() << "\"";
ss << " at " << &plugin;
ss << ">";
return ss.str();
})
.def("load_preset",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::loadPresetFile,
"Load a VST3 preset file in .vstpreset format.",
py::arg("preset_file_path"))
.def_property(
"preset_data",
[](const ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
juce::MemoryBlock presetData;
plugin.getPreset(presetData);
return py::bytes((const char *)presetData.getData(),
presetData.getSize());
},
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin,
const py::bytes &presetData) {
py::buffer_info info(py::buffer(presetData).request());
plugin.setPreset(info.ptr, static_cast<size_t>(info.size));
},
"Get or set the current plugin state as bytes in .vstpreset "
"format.\n\n"
".. warning::\n This property can be set to change the "
"plugin's internal state, but providing invalid data may cause the "
"plugin to crash, taking the entire Python process down with it.")
.def_static(
"get_plugin_names_for_file",
[](std::string filename) {
return getPluginNamesForFile<juce::PatchedVST3PluginFormat>(
filename);
},
"Return a list of plugin names contained within a given VST3 "
"plugin (i.e.: a \".vst3\"). If the provided file cannot be "
"scanned, "
"an ImportError will be raised.")
.def_property_readonly_static(
"installed_plugins",
[](py::object /* cls */) { return findInstalledVSTPluginPaths(); },
"Return a list of paths to VST3 plugins installed in the default "
"location on this system. This list may not be exhaustive, and "
"plugins in this list are not guaranteed to be compatible with "
"Pedalboard.")
.def_property_readonly(
"name",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.getName().toStdString();
},
"The name of this plugin.")
.def_property(
"raw_state",
[](const ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
juce::MemoryBlock state;
plugin.getState(state);
return py::bytes((const char *)state.getData(), state.getSize());
},
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin,
const py::bytes &state) {
py::buffer_info info(py::buffer(state).request());
plugin.setState(info.ptr, static_cast<size_t>(info.size));
},
"A :py:class:`bytes` object representing the plugin's internal "
"state.\n\n"
"For the VST3 format, this is usually an XML-encoded string "
"prefixed with an 8-byte header and suffixed with a single null "
"byte.\n\n"
".. warning::\n This property can be set to change the "
"plugin's internal state, but providing invalid data may cause the "
"plugin to crash, taking the entire Python process down with it.")
.def_property_readonly(
"descriptive_name",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.descriptiveName.toStdString();
},
"A more descriptive name for this plugin. This may be the same as "
"the 'name' field, but some plugins may provide an alternative "
"name.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"category",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.category.toStdString();
},
"A category that this plugin falls into, such as \"Dynamics\", "
"\"Reverbs\", etc.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"manufacturer_name",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.manufacturerName.toStdString();
},
"The name of the manufacturer of this plugin, as reported by the "
"plugin itself.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"version",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.version.toStdString();
},
"The version string for this plugin, as reported by the plugin "
"itself.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"is_instrument",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.isInstrument;
},
"True iff this plugin identifies itself as an instrument (generator, "
"synthesizer, etc) plugin.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"has_shared_container",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.hasSharedContainer;
},
"True iff this plugin is part of a multi-plugin "
"container.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"identifier",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.foundPluginDescription.createIdentifierString()
.toStdString();
},
"A string that can be saved and used to uniquely identify this "
"plugin (and version) again.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"reported_latency_samples",
[](ExternalPlugin<juce::PatchedVST3PluginFormat> &plugin) {
return plugin.getLatencyHint();
},
"The number of samples of latency (delay) that this plugin reports "
"to introduce into the audio signal due to internal buffering "
"and processing. Pedalboard automatically compensates for this "
"latency during processing, so this property is present for "
"informational purposes. Note that not all plugins correctly report "
"the latency that they introduce, so this value may be inaccurate "
"(especially if the plugin reports 0).\n\n*Introduced in v0.9.12.*")
.def_property_readonly(
"_parameters",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::getParameters,
py::return_value_policy::reference_internal)
.def("_get_parameter",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::getParameter,
py::return_value_policy::reference_internal)
.def("show_editor",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::showEditor,
SHOW_EDITOR_DOCSTRING, py::arg("close_event") = py::none())
.def(
"process",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize, reset);
},
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("input_array"),
py::arg("sample_rate"), py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def(
"__call__",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize, reset);
},
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("input_array"), py::arg("sample_rate"),
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE, py::arg("reset") = true)
.def("process",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::renderMIDIMessages,
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("midi_messages"),
py::arg("duration"), py::arg("sample_rate"),
py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def("__call__",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::renderMIDIMessages,
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("midi_messages"), py::arg("duration"),
py::arg("sample_rate"), py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def_readwrite(
"_reload_type",
&ExternalPlugin<juce::PatchedVST3PluginFormat>::reloadType,
"The behavior that this plugin exhibits when .reset() is called. "
"This is an internal attribute which gets set on plugin "
"instantiation and should only be accessed for debugging and "
"testing.");
#endif
#if JUCE_PLUGINHOST_AU && JUCE_MAC
py::class_<ExternalPlugin<juce::AudioUnitPluginFormat>,
AbstractExternalPlugin,
std::shared_ptr<ExternalPlugin<juce::AudioUnitPluginFormat>>>(
m, "AudioUnitPlugin", R"(
A wrapper around third-party, audio effect or instrument
plugins in `Apple's Audio Unit <https://en.wikipedia.org/wiki/Audio_Units>`_
format.
Audio Unit plugins are only supported on macOS. This class will be
unavailable on non-macOS platforms. Plugin files must be installed
in the appropriate system-wide path for them to be
loadable (usually ``/Library/Audio/Plug-Ins/Components/`` or
``~/Library/Audio/Plug-Ins/Components/``).
For a plugin wrapper that works on Windows and Linux as well,
see :class:`pedalboard.VST3Plugin`.)
.. warning::
Some Audio Unit plugins may throw errors, hang, generate incorrect output, or
outright crash if called from background threads. If you find that a Audio Unit
plugin is not working as expected, try calling it from the main thread
instead and `open a GitHub Issue to track the incompatibility
<https://github.com/spotify/pedalboard/issues/new>`_.
*Support for instrument plugins introduced in v0.7.4.*
*Support for running Audio Unit plugins on background threads introduced in v0.8.8.*
*Support for loading AUv3 plugins (* ``.appex`` *bundles) introduced in v0.9.5.*
)")
.def(
py::init([](std::string &pathToPluginFile, py::object parameterValues,
std::optional<std::string> pluginName,
float initializationTimeout) {
std::shared_ptr<ExternalPlugin<juce::AudioUnitPluginFormat>>
plugin = std::make_shared<
ExternalPlugin<juce::AudioUnitPluginFormat>>(
pathToPluginFile, pluginName, initializationTimeout);
py::cast(plugin).attr("__set_initial_parameter_values__")(
parameterValues);
return plugin;
}),
py::arg("path_to_plugin_file"),
py::arg("parameter_values") = py::none(),
py::arg("plugin_name") = py::none(),
py::arg("initialization_timeout") =
DEFAULT_INITIALIZATION_TIMEOUT_SECONDS)
.def("__repr__",
[](const ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
std::ostringstream ss;
ss << "<pedalboard.AudioUnitPlugin";
ss << " \"" << plugin.getName() << "\"";
ss << " at " << &plugin;
ss << ">";
return ss.str();
})
.def_static(
"get_plugin_names_for_file",
[](std::string filename) {
return getPluginNamesForFile<juce::AudioUnitPluginFormat>(filename);
},
py::arg("filename"),
"Return a list of plugin names contained within a given Audio Unit "
"bundle (i.e.: a ``.component`` or ``.appex`` file). If the provided "
"file cannot be scanned, an ``ImportError`` will be raised.\n\nNote "
"that most Audio Units have a single plugin inside, but this method "
"can be useful to determine if multiple plugins are present in one "
"bundle, and if so, what their names are.")
.def_property_readonly_static(
"installed_plugins",
[](py::object /* cls */) {
return AudioUnitPathFinder::findInstalledAudioUnitPaths();
},
"Return a list of paths to Audio Units installed in the default "
"location on this system. This list may not be exhaustive, and "
"plugins in this list are not guaranteed to be compatible with "
"Pedalboard.")
.def_property_readonly(
"name",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.getName().toStdString();
},
"The name of this plugin, as reported by the plugin itself.")
.def_property(
"raw_state",
[](const ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
juce::MemoryBlock state;
plugin.getState(state);
return py::bytes((const char *)state.getData(), state.getSize());
},
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin,
const py::bytes &state) {
py::buffer_info info(py::buffer(state).request());
plugin.setState(info.ptr, static_cast<size_t>(info.size));
},
"A :py:class:`bytes` object representing the plugin's internal "
"state.\n\n"
"For the Audio Unit format, this is usually a binary property list "
"that can be decoded or encoded with the built-in :py:mod:`plistlib` "
"package.\n\n"
".. warning::\n This property can be set to change the "
"plugin's internal state, but providing invalid data may cause the "
"plugin to crash, taking the entire Python process down with it.")
.def_property_readonly(
"name",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.getName().toStdString();
},
"The name of this plugin.")
.def_property_readonly(
"descriptive_name",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.descriptiveName.toStdString();
},
"A more descriptive name for this plugin. This may be the same as "
"the 'name' field, but some plugins may provide an alternative "
"name.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"category",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.category.toStdString();
},
"A category that this plugin falls into, such as \"Dynamics\", "
"\"Reverbs\", etc.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"manufacturer_name",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.manufacturerName.toStdString();
},
"The name of the manufacturer of this plugin, as reported by the "
"plugin itself.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"version",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.version.toStdString();
},
"The version string for this plugin, as reported by the plugin "
"itself.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"is_instrument",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.isInstrument;
},
"True iff this plugin identifies itself as an instrument (generator, "
"synthesizer, etc) plugin.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"has_shared_container",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.hasSharedContainer;
},
"True iff this plugin is part of a multi-plugin "
"container.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"identifier",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.foundPluginDescription.createIdentifierString()
.toStdString();
},
"A string that can be saved and used to uniquely identify this "
"plugin (and version) again.\n\n*Introduced in v0.9.4.*")
.def_property_readonly(
"reported_latency_samples",
[](ExternalPlugin<juce::AudioUnitPluginFormat> &plugin) {
return plugin.getLatencyHint();
},
"The number of samples of latency (delay) that this plugin reports "
"to introduce into the audio signal due to internal buffering "
"and processing. Pedalboard automatically compensates for this "
"latency during processing, so this property is present for "
"informational purposes. Note that not all plugins correctly report "
"the latency that they introduce, so this value may be inaccurate "
"(especially if the plugin reports 0).\n\n*Introduced in v0.9.12.*")
.def_property_readonly(
"_parameters",
&ExternalPlugin<juce::AudioUnitPluginFormat>::getParameters,
py::return_value_policy::reference_internal)
.def("_get_parameter",
&ExternalPlugin<juce::AudioUnitPluginFormat>::getParameter,
py::return_value_policy::reference_internal)
.def("show_editor",
&ExternalPlugin<juce::AudioUnitPluginFormat>::showEditor,
SHOW_EDITOR_DOCSTRING, py::arg("close_event") = py::none())
.def(
"process",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize, reset);
},
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("input_array"),
py::arg("sample_rate"), py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def(
"__call__",
[](std::shared_ptr<Plugin> self, const py::array inputArray,
double sampleRate, unsigned int bufferSize, bool reset) {
return process(inputArray, sampleRate, {self}, bufferSize, reset);
},
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("input_array"), py::arg("sample_rate"),
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE, py::arg("reset") = true)
.def("process",
&ExternalPlugin<juce::AudioUnitPluginFormat>::renderMIDIMessages,
EXTERNAL_PLUGIN_PROCESS_DOCSTRING, py::arg("midi_messages"),
py::arg("duration"), py::arg("sample_rate"),
py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def("__call__",
&ExternalPlugin<juce::AudioUnitPluginFormat>::renderMIDIMessages,
"Run an audio or MIDI buffer through this plugin, returning "
"audio. Alias for :py:meth:`process`.",
py::arg("midi_messages"), py::arg("duration"),
py::arg("sample_rate"), py::arg("num_channels") = 2,
py::arg("buffer_size") = DEFAULT_BUFFER_SIZE,
py::arg("reset") = true)
.def_readwrite(
"_reload_type",
&ExternalPlugin<juce::AudioUnitPluginFormat>::reloadType,
"The behavior that this plugin exhibits when .reset() is called. "
"This is an internal attribute which gets set on plugin "
"instantiation and should only be accessed for debugging and "
"testing.");
#endif
}