Avoid NR2 wisdom generation on audio thread#2275
Conversation
There was a problem hiding this comment.
Thanks @jensenpat — well-diagnosed fix. The root-cause analysis (stale fftw-3.3.10 wisdom rejected by 3.3.11) matches the symptom (audio worker thread blocked in FFTW_PATIENT plan creation), and the change correctly splits import (fast, safe on the audio thread) from generation (slow, must run on the background dialog thread).
A few small observations:
Minor / non-blocking
-
AudioEngine::needsWisdomGeneration()now has an observable side effect — it imports wisdom into FFTW global state viaSpectralNR::loadWisdom(). The name still reads as a pure query. This is harmless in practice (the only caller isMainWindow::enableNr2WithWisdom()on the UI thread, and the import is fast), but consider renaming to something likeensureWisdomReady()or adding a one-line comment noting the side effect. Not a blocker. -
When
needsWisdomGeneration()returns true because the file existed but failed to import, the subsequent background path callsSpectralNR::generateWisdom()which begins by attemptingloadWisdom()again — a second guaranteed-failed import on the same stale file before it falls through to full generation. Minor redundancy, no correctness issue. -
Lock order looks fine:
setNr2Enabledholdsm_dspMutex(recursive) and then briefly takess_fftwMutexinsideloadWisdom. There is no other path that takes them in the reverse order, so no ABBA risk. -
qCWarning(lcDsp)is already established in this file (line 90), so the new export-failure log fits convention.
The HAVE_FFTW3 guards in both needsWisdomGeneration() and setNr2Enabled() are good — fallback FFT builds will no longer claim wisdom is needed and won't attempt imports.
LGTM as a targeted bug fix. The validation steps (build + ctest + reproducing the import failure with fftw-wisdom) are appropriate for this change.
The v0.9.5.1 entry was originally cut for just the TCI TX hotfix (#2285), but six additional fixes had already landed in main between the v0.9.5 tag and v0.9.5.1: - #2275 NR2 wisdom generation off the audio thread - #2278 SmartLink disconnect teardown - #2279 Reset RX slice tabs on disconnect (#2254) - #2280 macOS panadapter pop-out refresh + multi-pan dock layout - #2282 SmartLink reconnect after WAN drop - #2284 Qt log handler serialization fixes macOS tune-time crash CHANGELOG.md gets a per-fix entry with root cause + behavior change. WhatsNewData.cpp regenerated via scripts/gen_whatsnew.py so the in-app What's New dialog reflects the full v0.9.5.1 contents. Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Match the v0.9.5 `(#NNNN, contributor)` heading style and call out @rfoust and @jensenpat in the summary for the bulk of this release. Authors per PR: - @rfoust: #2278, #2279, #2280, #2282 (SmartLink + macOS popout) - @jensenpat: #2275, #2284 (NR2 wisdom + Qt log serialization) WhatsNewData.cpp regenerated. Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Summary
Fixes a macOS NR2 stall where enabling NR2 could freeze RX audio and the WAVE scope for minutes when the local FFTW wisdom file existed but could not be imported by the current FFTW runtime.
Root Cause
AudioEngine::needsWisdomGeneration()only checked whetheraethersdr_fftw_wisdomexisted. If the file was stale or incompatible,setNr2Enabled()still calledSpectralNR::generateWisdom()on the audio worker thread.generateWisdom()then failed to import the file and started full FFTW wisdom generation, which can run for several minutes and blocks the audio thread. That explains the observed audio stop, WAVE hang, and later recovery.On the affected macOS machine, the local wisdom file was present and had a
fftw-3.3.10header, while the current build uses FFTW 3.3.11;fftw-wisdomrejected it with an import error.Changes
SpectralNR::loadWisdom()so Aether can validate/import wisdom without triggering full generation.AudioEngine::needsWisdomGeneration()return true when the wisdom file exists but cannot be imported.AudioEngine::setNr2Enabled()from ever running full FFTW wisdom generation on the audio worker thread.Impact
When wisdom is missing or stale, NR2 enable now routes through the existing background progress dialog path instead of blocking audio playback. If wisdom import unexpectedly fails at enable time, NR2 proceeds with runtime FFTW_MEASURE plans rather than hanging RX audio.
Validation
cmake --build build --parallel 10ctest --test-dir build --output-on-failurefftw-wisdom -w /Users/patj/.config/AetherSDR/AetherSDR/aethersdr_fftw_wisdom.👨🏼💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat