-
Notifications
You must be signed in to change notification settings - Fork 0
AudioFX Plugin API
This page documents the stable interface for post-processing effects.
Source pointers
-
patchbay_desktop_gui/audiofx/base.py– plugin + parameter schema -
patchbay_desktop_gui/audiofx/manager.py– discovery loader -
patchbay_desktop_gui/gui/main_window.py– plugin search paths + persistence layout -
plugins/*.py– built-in plugins +_template_gain.py
classDiagram
class ParamKind {
<<enum>>
FLOAT
INT
BOOL
CHOICE
}
class ParamSpec {
+str param_id
+str label
+ParamKind kind
+Any default
+float min_value
+float max_value
+float step
+str fmt
+list~str~ choices
}
class AudioEffectPluginBase {
+str plugin_id
+str display_name
+List~ParamSpec~ params
+apply(audio, sample_rate, params) np.ndarray
}
class PluginLoadError {
+str path
+str message
}
class AudioFxManager {
+Dict~str,AudioEffectPluginBase~ plugins
+List~PluginLoadError~ load_errors
+register(plugin, source)
+discover(user_dirs)
+list_plugins()
}
ParamSpec --> ParamKind
AudioEffectPluginBase --> ParamSpec
AudioFxManager o--> AudioEffectPluginBase
AudioFxManager o--> PluginLoadError
This reflects the actual code in patchbay_desktop_gui/audiofx/base.py and patchbay_desktop_gui/audiofx/manager.py.
A plugin is a single .py file that exports a module-level variable:
-
PLUGIN: an instance of a subclass ofAudioEffectPluginBase
Example:
import numpy as np
from typing import Any, Dict
from patchbay_desktop_gui.audiofx.base import AudioEffectPluginBase, ParamSpec
class Gain(AudioEffectPluginBase):
plugin_id = "gain"
display_name = "Gain"
params = [
ParamSpec.float("gain_db", "Gain (dB)", default=0.0, min_value=-24.0, max_value=24.0, step=0.5, fmt="%.1f"),
]
def apply(self, audio: np.ndarray, sample_rate: int, params: Dict[str, Any]) -> np.ndarray:
g_db = float(params.get("gain_db", 0.0))
g = 10.0 ** (g_db / 20.0)
return (audio.astype(np.float32, copy=False) * np.float32(g)).astype(np.float32, copy=False)
PLUGIN = Gain()-
plugin_idmust be unique across all loaded plugins. -
apply(...)must be deterministic and must not modify its input array in place. - Audio is passed as float PCM
np.ndarraywith shape(N, C).
The GUI builds an editor from params: list[ParamSpec].
Supported kinds (ParamKind):
-
float,int,bool,choice
Best practice:
- Keep
param_idstable forever (settings persistence relies on it) - Provide min/max/step for numeric parameters to make UI editing safe
- Prefer human-friendly labels and sensible defaults
Plugins are loaded from files and imported under a unique module name to avoid clashes:
importlib.util.spec_from_file_location(...)- unique module name via UUID (no shadowing of third-party packages)
Files starting with _ are ignored.
Duplicate plugin_id values are rejected (first plugin wins; duplicates are recorded as load errors).
The DearPyGui frontend searches:
%APPDATA%\CatSynth\PATCHBAY\plugins-
./plugins(current working directory) -
plugins/shipped with the source tree / installed package (if present) - extra directories from env var
PATCHBAY_AUDIOFX_PLUGIN_DIRS(Windows: semicolon-separated)
Settings are stored under:
settings["audiofx"]["input" | "target" | "residual"][plugin_id][param_id] = value
This means you can use different settings per stream (e.g., normalize input but compress target).
When a plugin fails to load, the manager records a PluginLoadError(path, message).
Common causes:
-
PLUGINvariable missing -
PLUGINnot an instance ofAudioEffectPluginBase - import error (missing dependency, syntax error)
Last updated: 2026-01-24
PATCHBAY • MIT License • Wiki content is intended to match PATCHBAY 0.1.x.
- Home
- Installation
- Quickstart
- User Guide
- Input & Anchors
- Description & Run
- Output
- Export & Files
- Runtime Settings
- Settings & Persistence
- FAQ
- Troubleshooting
- Architecture
- Data Flow
- Backend Interface
- Anchor Algorithms
- Chunking & Reconstruction
- Logging & Debugging
- Parameter Persistence