Build the beat-tracking STFT without a huge materialized index array

Open Beginner friendly
#45 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
numpy, python
Domain
data, performance

Research direction

Read onset_envelope() in easyedit/beats.py and inspect how its window indices feed the FFT. Compare the current envelope with a strided-window implementation on synthetic audio, as the issue suggests. Done means the envelope stays numerically identical while avoiding the large materialized index array; run the relevant test and the project’s unittest discovery.

Written by the indexing model from the issue text.

Description

good first issue performance

onset_envelope() in easyedit/beats.py builds every analysis window by fancy-indexing the audio with a 2-D index array:

n = 1 + (len(y) - NFFT) // HOP
idx = np.arange(NFFT)[None, :] + HOP * np.arange(n)[:, None]
spec = np.abs(np.fft.rfft(y[idx] * win, axis=1))

With NFFT=2048, HOP=512 and SR=22050, a 4-minute song gives n ≈ 10,300, so idx alone is roughly 10,300 × 2048 integers (~170 MB), and y[idx] plus the windowed copy and the FFT output add several hundred MB more. fetch.resolve() allows music up to 900 seconds, where this reaches multiple gigabytes of peak RSS — on a machine already running Whisper and Chrome, that's where the pipeline falls over.

Nothing about the math needs those copies: the windows are evenly strided slices of y, so a strided view (for example numpy.lib.stride_tricks.sliding_window_view(y, NFFT)[::HOP]) produces exactly the same n rows with no index array at all. Processing the spectrogram in blocks of a few thousand frames would also cap the FFT's peak allocation.

The result should stay numerically identical, so the existing beat output for a given song shouldn't change; a small test comparing the envelope from the old and new paths on synthetic audio would prove it.

Where to look: easyedit/beats.py — onset_envelope()


Getting started: Python 3.10+, Node 22+, FFmpeg on PATH. npm install, pip install -r requirements.txt, then python -m easyedit.doctor. Run python -m unittest discover before opening a PR. Passing --llm none skips the model entirely, which is the fastest way to test. Comment here to claim it. Questions → Discord.

Dominant language
Python
Stars
168
Forks
24
Avg merge
2d 10h
Merged PRs (30d)
14

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from blixvip/easyedit

All issues in blixvip/easyedit

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.