Repository navigation
perf(core): decimate once per channel after the stereo mix - #4
Conversation
Pan and sum voices at the oversampled rate, then run one shared decimator per output channel instead of one per voice; a centered mix filters once until the channels diverge. Voices retire on their envelope end, and the shared decimator drains the tail and snaps a silent channel to exact zero below the -96 dB floor. Note gain, expression, pan and steal fades now apply before the decimator, so hard gain steps ring for a few frames; tests that asserted instant output-rate cuts now allow that settle window or a derived ramp bound. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012VX1mXsKvNnkr22msEbfwA
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Generated by Claude Code |
Resolve conflicts with the FIR state layout: tail checks use decimatorPeak, and sub-floor history is cleared only once no voice, fade or spill is sounding. A live silent voice now flushes the finite FIR to exact zeros instead, keeping envelope tails intact. Docs and CHANGELOG describe the combined design. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012VX1mXsKvNnkr22msEbfwA
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 94ef9e5ee0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012VX1mXsKvNnkr22msEbfwA
Requested by 小語 · project thread
Summary
renderVoicepans each oversampled sample into synth-levelmixLeft/mixRightbuffers.renderthen runs one shared decimator per output channel after the mix, instead of one per voice. Per-voicefiltersstate is removed.releaseEnd), instead of waiting for its own filter state to drain. The shared decimator drains the tail. Once nothing is sounding, buffered history below the −96 dB floor (decimatorPeak) snaps to zero. A live but silent voice simply flushes the finite FIR to exact zeros. The empty-synth fast path waits for idle (decimatorIdle).panic()resets the shared decimator. Non-finite decimator output resets it and incrementserrorCount.Behavior change
Note gain, expression, pan and steal fades are now applied before the decimator. A hard gain step (e.g.
expression: 0) is band-limited and rings through the FIR (≤26 output frames) instead of cutting instantly, andendedfires at the envelope end.Test changes:
s·p·Σk|h[k]|/4.phasesinstead of the removedfilters.New tests:
Benchmark
Focused
Synth.renderloop (48 kHz, 128 frames, 1000 blocks × best-of-7, median of 3 interleaved runs, Node 22, cloud x64), compared with main after #5 (per-voice FIR):Against the earlier per-voice Butterworth base the gains were 9–19%. A single voice costs about 0.01 ms/block more (mix-buffer overhead), well under 1% of the 2.67 ms deadline.
npm run benchmarkon this host is too noisy (±20% between same-build runs) to resolve these.Verification
npm test: 443/443 pass after the merge.npm run typecheck,npm run sound-qualityandnpm run securitypass.windows-armwas red on main's docs-build tests before perf(core): polyphase half-band FIR decimation #5. If it still fails here, it is that same issue.🤖 Generated with Claude Code
https://claude.ai/code/session_012VX1mXsKvNnkr22msEbfwA