Repository navigation
Bump dsptap to the srdif engine; close the convolution engine's IR-load race; gate FFT sizes - #36
Merged
Merged
Conversation
…ad race; gate FFT sizes submodules/dsptap moves from 41215c6 to 2137d86 (DspTap main): the floating real FFT is now the clean-room srdif engine, header-only, with tables built in the constructor. tap_dsp_fft exists only under TAP_DSP_FFT_CMSIS now, so the install rule exports it only when the target exists (a top-level configure failed on the old rule). conv_engine: load_ir() (control thread) and process_block() (audio thread) transformed through one scratch buffer, so an IR load during playback corrupted either the partition being built or the audio frame (a standalone repro measured ~5e5 corrupted samples per run of 3.3e5). load_ir() now has its own scratch; the FFT object stays shared, which the engine's k_is_shareable contract permits and a static_assert pins. The double-buffer slot swap also had an ABA window (a block reads the slot it claimed at its start; a second load inside that block wrote it): the audio thread now publishes the slot it is reading and load_ir waits for it to be released (bounded; refused on timeout, never written while in use). The new concurrency scenario fails on the old engine and passes on this one. Size gates, per DspTap's rule that configuration-driven sizes go through supports_size (an unsupported size corrupts the heap in a release build): conv_engine::configure and stft::configure (behind spectra and nr) refuse unsupported sizes and return false leaving the object unchanged; process() emits silence until a configure has succeeded. The C ABI returns -1 on a refusal (the Python bridge already raises on it). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QM4N2sNauJqVYyetTcgNcB
…new dsptap pin convolution_reverb, harmonizer and tune drive conv_engine and pvoc through the C ABI, so the dsptap bump (the srdif engine replacing the Ooura-derived one) moves their output bits; the house rule is to re-execute, and the verified numbers are: convolution exactness against direct convolution tightened from 3.13e-12 to 1.14e-13 (max |engine - direct|, 47 partitions) and the block-size independence from 1.81e-12 to 7.11e-14; every printed number in harmonizer and tune is unchanged (figures re-rendered). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QM4N2sNauJqVYyetTcgNcB
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.
What this changes
submodules/dsptapmoves from 41215c6 to 2137d86 (DspTapmain, the clean-room srdif engine, header-only).conv_enginegets its own scratch buffer forload_ir()plus a reader guard on the IR slot swap,conv_engine::configureandstft::configure(behindspectraandnr) refuse FFT sizes the engine does not support, and the three notebooks that run through the real FFT are re-executed.Why
Found by an adversarial audit of the FFT and its consumers (2026-10-01):
load_ir()on the control thread andprocess_block()on the audio thread transformed through one scratch buffer, so an IR load during playback corrupted either the partition being built or the audio frame. A standalone repro against the old header measured ~5e5 corrupted samples per run of 3.3e5; the new header measures zero. The double-buffer slot swap also had an ABA window (a block reads the slot it claimed at its start; a second load inside that block wrote it), closed by the audio thread publishing the slot it reads andload_irwaiting for it (bounded; refused on timeout, never written while in use). The FFT object stays shared, which DspTap'sk_is_shareablepermits and astatic_assertpins.configurenow returns false and leaves the object unchanged;process()emits silence until a configure succeeds, since it indexed unallocated buffers otherwise. The C ABI returns -1 on refusal (the Python bridge already raises on it).install(TARGETS … tap_dsp_fft)failed every top-level configure against the new pin, where that target exists only underTAP_DSP_FFT_CMSIS.Verification
scripts/tidy.shon the changed TUs: no finding in the changed files (the 46 intaptools_capi.cppare identical onmain). clang-format applied.convolution_reverbexactness against direct convolution tightened from 3.13e-12 to 1.14e-13 and block-size independence from 1.81e-12 to 7.11e-14; every printed number inharmonizerandtuneis unchanged. The book cites none of the moved numbers.configurenow returns a bool its wrappers may want to check, andload_irreturns false on the refusal path; the Max attribute setters that decide whether a non-power-of-two size ever reachesstftare in that repo.Notes for the reviewer
main. The engine swap moves every float and double output bit (the tests tolerate it; the notebooks are re-executed for it).configure()onconv_engine,stft,spectra::remapperandnr::reducerreturnsbool;load_ir()returnsbool; a block size of 1 (N = 2, below the engine's minimum) is now refused where it used to run by accident.🤖 Generated with Claude Code
https://claude.ai/code/session_01QM4N2sNauJqVYyetTcgNcB
Generated by Claude Code