Source code for noisemaker.effects_registry
"""Effect decorator for Noisemaker Composer Presets"""
from __future__ import annotations
import inspect
from typing import Any, Callable
EFFECTS: dict[str, dict[str, Any]] = {}
[docs]
def effect(*args: str) -> Callable:
"""
Function decorator for declaring composable effects.
Registers effect functions with their parameter defaults for use in Composer presets.
Validates that effects accept required "time" and "speed" keyword arguments.
Args:
*args: Optional effect name. If not provided, uses function name.
Returns:
Decorator function that registers the effect and returns the original function
Raises:
ValueError: If function doesn't accept required "time" or "speed" parameters,
or if keyword parameter counts don't match defaults
"""
def decorator_fn(func: Callable) -> Callable:
argspec = inspect.getfullargspec(func)
params = argspec.args
for param in ["time", "speed"]:
if param not in params:
raise ValueError(f'{func.__name__}() needs to accept a "{param}" keyword arg. Please add it to the function signature.')
# All effects respond to "tensor", "shape". Removing these non-keyword args should make params the same length as defaults.
params.remove("tensor")
params.remove("shape")
defaults = argspec.defaults or ()
if params and len(params) != len(defaults):
raise ValueError(f'Expected {len(defaults)} keyword params to "{func.__name__}", but got {len(params)}.')
# Register effect name and params
name = args[0] if args else func.__name__
EFFECTS[name] = dict((params[i], defaults[i]) for i in range(len(params)))
EFFECTS[name]["func"] = func
return func
return decorator_fn