Python Start
Use this path to process a planar NumPy array.
pip install effetune
Wheels target CPython 3.10+ on manylinux x86-64, Windows AMD64, macOS Intel, and
macOS Apple Silicon. musllinux is not provided. Input must be C-contiguous
float32 with shape (channels, frames); the core does not resample.
Generated effect constructors and create_effect() accept Python
snake_case keywords:
shift = et.PitchShifter(pitch_shift=3)
same_shift = et.create_effect("PitchShifter", pitch_shift=3)
Chain JSON and scheduled event parameter objects use the semantic catalog name
pitchShift. The camelCase semantic name is not a Python constructor alias.
import numpy as np
import effetune as et
frames = 512
phase = np.arange(frames, dtype=np.float32)
mono = (0.5 * np.sin(2 * np.pi * phase / 97)).astype(np.float32)
audio = np.ascontiguousarray(np.stack((mono, mono)))
chain = et.Chain([et.Volume(volume=-6)])
output = chain.process(audio, sample_rate=48_000)
print(output.shape, float(np.max(np.abs(output))))
Offline calls start with fresh state. Use Chain.stream() when filter history,
tails, or seeded random state must continue. See Python API
and Determinism.
Graph v1 quickstart
Graph v1 is opt-in routing for branching and merging. This complete example uses the wet/dry recipe, processes once with fresh state, then opens a stateful static stream and reads its prepared compile snapshot:
import numpy as np
import effetune as et
audio = np.full((2, 128), 0.25, dtype=np.float32)
graph = et.Graph.wet_dry(
et.Volume(id="wet", volume=-6),
dry=0.5,
wet=0.5,
)
stream = None
try:
offline = graph.process(audio, sample_rate=48_000)
stream = graph.stream(48_000, channels=2, block_size=128)
continuous = stream.process(audio)
print(
float(offline[0, 0]),
float(continuous[0, 0]),
stream.latency_samples,
stream.compile_snapshot["effectiveSchedule"],
)
finally:
if stream is not None:
stream.close()
graph.close()
See Graph v1 for the document contract, conversion from a Chain, capacity, and stable error fields.
Reading an audio file
SoundFile returns (frames, channels). Convert it explicitly to the library’s
planar, C-contiguous float32 layout:
import numpy as np
import soundfile as sf
decoded, sample_rate = sf.read("input.wav", dtype="float32", always_2d=True)
audio = np.ascontiguousarray(decoded.T, dtype=np.float32)
output = chain.process(audio, sample_rate=sample_rate)
sf.write("output.wav", output.T, sample_rate, subtype="FLOAT")