fix: remove stale RADE DSP guards that silenced NR4/NR2/etc. on unrelated pans#2025
Conversation
There was a problem hiding this comment.
Clean, well-scoped fix. CI is green (build, CodeQL, analyze all pass). One file changed, all four changes are consistent with the dual-buffer architecture from #1953.
Guard removal (6 DSP setters + setRadeMode teardown): Correct. Post-#1953, RADE decoded audio flows through m_radeRxBuffer and is mixed in the drain timer after the DSP stage — the DSP pipeline only touches m_rxBuffer, so the guards were silencing DSP on pans that never see RADE audio. Good catch.
updateRxBufferStats(): Summing both buffers gives an accurate picture of total buffered audio for diagnostics. Fine.
Drain timer clamp: Moving from a per-sample clamp inside the RADE mix loop to a single pass over the full output block is the right call. One minor observation: before this PR, the non-RADE path (out[i] += rx[i]) never clamped at all — the new code now clamps unconditionally, which is actually a small improvement (prevents out-of-range samples reaching the DAC even in non-RADE scenarios). The cost of iterating len/floatBytes samples for a clamp is negligible at audio sample rates.
No issues found — scope is tight, no convention violations, no null-pointer risks, no resource leaks. Excellent PR description too.
Thanks for the thorough multi-pan testing on the 8400, @NF0T.
…n another pan With ten9876#1953, decoded RADE speech writes to m_radeRxBuffer and bypasses the DSP chain entirely. DSP (NR2/NR4/RN2/BNR/DFNR) runs only on m_rxBuffer, which carries SSB/CW audio from all non-RADE slices. The original guards that prevented DSP while m_radeMode was set were motivated by the old single- buffer design, where decoded speech flowed through feedAudioData() → DSP. With the dual-buffer architecture those guards are wrong: - In multi-pan (RADE on Pan A, SSB on Pan B) the guards silently discarded any attempt to enable NR4/etc. on Pan B. The button illuminated but no processing occurred — confirmed by user testing (NF0T, FLEX-8400 v4.1.5). - setRadeMode(true) tore down any already-active DSP on entry, killing noise reduction on a concurrently listening SSB pan. Decoded speech in m_radeRxBuffer is never touched by DSP regardless; removing the guards cannot affect RADE speech quality. Also address two minor issues noted in the ten9876#1953 review (aethersdr-agent): - updateRxBufferStats() now sums m_rxBuffer + m_radeRxBuffer so the buffer diagnostics UI (rxBufferBytes / rxBufferPeakBytes) reflects total buffered audio rather than omitting the RADE speech contribution. - Drain-timer mix clamp: both source loops now use plain += and a single std::clamp pass runs over the full output array after both sources are mixed. Previously the clamp was applied only to the RADE addition, which was functionally correct (RADE ran last) but fragile and unclear in intent. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
ad7e82c to
e1c6a08
Compare
Background
This fix was identified during post-merge testing of PR #1953 (dual-buffer RADE
RX architecture). After #1953 landed, multi-pan testing revealed that
client-side DSP (NR4, NR2, RN2, BNR, DFNR, MNR) was completely silenced on any
non-RADE pan while RADE was active — a regression introduced by guards that were
correct before #1953 but became harmful once the dual-buffer design separated
RADE decoded audio from the DSP pipeline entirely.
Problem
In a two-pan setup (Pan A = RADE/FreeDV, Pan B = SSB/CW), engaging NR4 or any
client-side DSP on Pan B had no effect. The UI buttons illuminated correctly,
but the audio pipeline was untouched.
Root Cause
AudioEnginehadif (m_radeMode) return;guards at the top of every DSPsetter (
setNr4Enabled,setNr2Enabled,setRn2Enabled,setBnrEnabled,setDfnrEnabled,setMnrEnabled) and a teardown loop insetRadeMode(on=true)that forcibly disabled all DSP.
These guards were appropriate when RADE decoded audio flowed through the same
m_rxBuffer/ DSP pipeline as regular audio — running NR on decoded speechwould have degraded it. They are no longer correct after PR #1953: decoded
speech now flows exclusively through
m_radeRxBufferand is mixed in the draintimer after the DSP stage. The DSP pipeline only ever touches
m_rxBuffer;RADE audio never enters it.
Fix
if (m_radeMode) return;from all six client-side DSP setterssetRadeMode(on=true)updateRxBufferStats()to sum both buffers for accurate diagnosticsstd::clampin a single passover the full output block (was only clamping the RADE portion)
Testing
Tested on FLEX-8400, firmware v4.1.5.39794, two-panadapter layout:
🤖 Generated with Claude Code