Repository navigation
Reuse NumPy buffers and eliminate steady-state HPF/AEC DSP allocations - #3
Merged
Merged
Conversation
egorsmkv
force-pushed
the
perf/reusable-audio-buffers
branch
from
October 8, 2026 09:16
9ded05f to
714dee2
Compare
egorsmkv
force-pushed
the
perf/reusable-audio-buffers
branch
from
October 8, 2026 09:29
714dee2 to
619649e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The default mono/stereo HPF+AEC path now bypasses graph packet allocation and reuses planar buffers.
process_into()writes to a caller-owned float32 NumPy array;process_frames_into()amortizes safe NumPy borrowing over a batch. The existingprocess()API and optional NS/AGC/post-filter graph behavior are preserved, withbackend="graph"available for comparison.Vendor only the aec3 0.4.0 library sources, minimal manifest and LICENSE/PATENT (no upstream workflows, editor instructions, demos, CLI tools, integration tests, release docs or nested lockfile), with four targeted DSP patches: stack FFT scratch, recycled render queue tensors, disabled diagnostic formatting when diagnostics are off, and bounded diagnostic history. Preserve LICENSE/PATENT and document provenance. Include vendored sources in the sdist.
Validation: 124 normal-build tests pass (12 allocation tests intentionally skipped); tracking builds exercise all 136 tests. 24 baseline signal configurations produce bit-identical audio and metrics. Native allocation probe covers 24 rate/channel/HPF configurations, queue overflow, delay/gain changes and 700 seconds of diagnostic history. On Linux, mono processing falls from 105/139/240 µs to 57/76/119 µs at 16/32/48 kHz. The measured medians and limitations are in docs/performance.md; raw JSON outputs are generated locally and are not committed.
Scope of the allocation guarantee: zero native DSP heap allocations after warmup with stable mono/stereo HPF+AEC configuration. Safe NumPy borrow checks still request three allocations (540 bytes) per Python call, independent of batch size; CPython allocations are not measured. DSP format conversion remains necessary, so this is not an end-to-end zero-copy claim. Content-driven core reconfiguration and graph-only optional stages can allocate.
CI covers Linux/macOS/Windows, Python 3.10–3.14, Rust 1.88, lint and allocation probes on all three operating systems.
Batch arrays require C-contiguous row-major layout; Fortran layouts are rejected before DSP state changes.
Python quality: pinned Ruff lint/format and Pyright checks cover tests, benchmarks and examples on Python 3.10, using a packaged float32 NumPy API stub. Fix typed Path handling, potentially uninitialized results, import ordering and strict zip lengths. The quality dependency group is locked in uv.lock. No JSON files remain in the PR tree.