Bug
#72 tracks the Compressor's per-forward() detector/envelope reset. The same applies to:
- Expander/Gate (
effect.py ~line 1800; expander_cpu.cpp / expander_forward.cu zero-init env each call)
- Limiter (
effect.py ~line 2036; envelope reset and the look-ahead window does not see the previous chunk's tail, so inter-chunk peaks are missed)
- Reverb (
effect.py:855; comb/all-pass delay lines re-zeroed per call — audible discontinuity at every chunk boundary in StreamProcessor use)
The native kernels (binding.cpp) take no state tensors at all, so chunked streaming cannot be state-continuous. This contradicts the streaming story: filters carry DF1 state across chunks, effects do not.
Fix
Thread optional state in/out through the native kernels (CPU + CUDA + bindings) and persist it on the Python effect objects, mirroring the IIR pattern (_state_*, lazy alloc, reset_state()):
- Compressor/Expander: per-channel
[C, 2] (envelope dB, RMS accumulator).
- Limiter: per-channel envelope + carry the trailing
lookahead input samples in Python so peak_env spans the chunk boundary.
- Reverb: per-channel comb/all-pass delay-line buffers + damping state, allocated lazily at first forward.
CUDA mirrors need cluster validation.
Bug
#72 tracks the Compressor's per-
forward()detector/envelope reset. The same applies to:effect.py~line 1800;expander_cpu.cpp/expander_forward.cuzero-init env each call)effect.py~line 2036; envelope reset and the look-ahead window does not see the previous chunk's tail, so inter-chunk peaks are missed)effect.py:855; comb/all-pass delay lines re-zeroed per call — audible discontinuity at every chunk boundary inStreamProcessoruse)The native kernels (
binding.cpp) take no state tensors at all, so chunked streaming cannot be state-continuous. This contradicts the streaming story: filters carry DF1 state across chunks, effects do not.Fix
Thread optional state in/out through the native kernels (CPU + CUDA + bindings) and persist it on the Python effect objects, mirroring the IIR pattern (
_state_*, lazy alloc,reset_state()):[C, 2](envelope dB, RMS accumulator).lookaheadinput samples in Python sopeak_envspans the chunk boundary.CUDA mirrors need cluster validation.