spotify / pedalboard

🎛 🔊 A Python library for audio.
https://spotify.github.io/pedalboard
GNU General Public License v3.0
5.18k stars 260 forks source link

Parallel and Feedback Plug-in Composition? #108

Closed SamKouteili closed 2 years ago

SamKouteili commented 2 years ago

I'm a newcomer to pedalboard, so apologies if there is already some way to do this!

Is there any way of chaining plugins in a non sequential way? In particular, having an input pass by two plugins in parallel and then combining them again, or creating some sort of feedback loop with a defined time delay?

Currently, it seems as though only direct plugins or a sequence (list) of plugins are supported - this limits the potential for creating more interesting plugins.

TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. pedalboard_native.utils.Chain(plugins: List[pedalboard_native.Plugin])
    2. pedalboard_native.utils.Chain()
psobot commented 2 years ago

Hi @SamKouteili! My apologies - comprehensive documentation is on my team's TODO list, but we haven't gotten there just yet.

What you're looking for (parallel plugins) can be accomplished with the Mix plugin. You can find its docstrings by doing:

> import pedalboard
> help(pedalboard.Mix)
Help on class Mix in module pedalboard_native.utils:

class Mix(pedalboard_native.PluginContainer)
 |  A utility plugin that allows running other plugins in parallel. All plugins provided will be mixed equally.
[...]
 __init__(self: pedalboard_native.utils.Mix, plugins: List[pedalboard_native.Plugin]) -> None

You mention passing an input through two plugins in parallel, then combining them again; you can do something like this with:

from pedalboard import Mix, Compressor, Delay, Reverb, Gain, Pedalboard

board = Pedalboard([
    Compressor(),
    Mix([ # Mix two copies of the signal together:
        Delay(delay_seconds=0.25),  # A copy delayed by 0.25s
        Gain(gain_db=0)             # A copy with no change (gain = 0dB)
    ]),
    Reverb()
])

While Mix allows you to mix multiple chains in parallel, there's not currently a "feedback" mechanism per se; the graph of plugins is a directed acyclic graph (DAG) and an earlier plugin can't receive a later plugin's output. You could manually implement this by passing one Pedalboard's output back into its input.

SamKouteili commented 2 years ago

Thank you so much for this thorough and illustrative response - this is exactly what I was looking for!