This PR allows Pedalboard to load and run third-party (VST/AU) instrument plugins, in addition to its existing support for effect plugins.
To accommodate this, this PR adds:
a new __call__ method on ExternalPlugin that takes MIDI messages as input, rather than audio.
new is_instrument and is_effect properties on Plugin that allow users to determine if any instance of Plugin is an instrument plugin (i.e.: accepts only MIDI as input, returns audio) or an effect plugin (accepts audio and returns audio).
a vendored copy of Magical8BitPlug2, a great GPLv3 instrument VST, to be used in tests on macOS and Windows.
TODO:
[x] Ensure documentation is comprehensive for instrument plugin support
[x] Update README
[x] Test with a variety of commercial VST3 plugins
[x] Ensure instrument plugins cannot be added to AudioStream objects
[x] Test multi-threaded rendering of MIDI to audio
Example usage:
from pedalboard import Pedalboard, Reverb, load_plugin
from pedalboard.io import AudioFile
from mido import Message # not part of Pedalboard, but convenient!
# Load a VST3 or Audio Unit plugin from a known path on disk:
instrument = load_plugin("./VSTs/Magical8BitPlug2.vst3")
effect = load_plugin("./VSTs/RoughRider3.vst3")
print(effect.parameters.keys())
# dict_keys([
# 'sc_hpf_hz', 'input_lvl_db', 'sensitivity_db',
# 'ratio', 'attack_ms', 'release_ms', 'makeup_db',
# 'mix', 'output_lvl_db', 'sc_active',
# 'full_bandwidth', 'bypass', 'program',
# ])
# Set the "ratio" parameter to 15
effect.ratio = 15
# Render some audio by passing MIDI to an instrument:
samplerate = 44100
audio = instrument(
[Message("note_on", note=60), Message("note_off", note=60, time=5)],
samplerate,
duration=5, # seconds
)
# Apply effects to this audio:
effected = effect(audio, samplerate)
# ...or put the effect into a chain with other plugins:
board = Pedalboard([effect, Reverb()])
# ...and run that pedalboard with the same VST instance!
effected = board(audio, samplerate)
Closes #18 and #220.
This PR allows Pedalboard to load and run third-party (VST/AU) instrument plugins, in addition to its existing support for effect plugins.
To accommodate this, this PR adds:
__call__
method onExternalPlugin
that takes MIDI messages as input, rather than audio.is_instrument
andis_effect
properties onPlugin
that allow users to determine if any instance ofPlugin
is an instrument plugin (i.e.: accepts only MIDI as input, returns audio) or an effect plugin (accepts audio and returns audio).TODO:
AudioStream
objectsExample usage: