Skip to content

Add AetherDSP settings dialog, NR4 noise reduction, and DSP tooltips#796

Merged
ten9876 merged 7 commits into
aethersdr:mainfrom
boydsoftprez:feature/aether-dsp-settings
Apr 5, 2026
Merged

Add AetherDSP settings dialog, NR4 noise reduction, and DSP tooltips#796
ten9876 merged 7 commits into
aethersdr:mainfrom
boydsoftprez:feature/aether-dsp-settings

Conversation

@boydsoftprez

@boydsoftprez boydsoftprez commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • AetherDSP Settings dialog — new modeless dialog (Settings menu + NR2 right-click) with configurable parameters for NR2 and NR4 client-side noise reduction
  • NR4 noise reduction — new client-side spectral noise reduction using bundled libspecbleach (LGPL-2.1), with 7 tunable parameters, full UI integration, and persistence
  • DSP tooltips — ~95 tooltips added across all DSP buttons, sliders, and receiver controls (overlay panel, VFO DSP tab, RX applet, AetherDSP dialog)

What's New

AetherDSP Settings Dialog

  • Accessible from Settings menu and NR2/NR4 right-click context menus
  • NR2 tab: Gain method (Linear/Log/Gamma/Trained), NPE method (OSMS/MMSE/NSTAT), AE artifact filter, reduction depth, smoothing, and voice threshold sliders
  • NR4 tab: Noise estimation method (SPP-MMSE/Brandt/Martin), adaptive noise toggle, reduction (dB), smoothing, whitening, masking depth, and suppression sliders
  • All parameters persist via AppSettings (PascalCase keys)
  • Reset Defaults button on each tab
  • DspParamPopup: right-click any NR2 or NR4 button for quick parameter access

NR4 Noise Reduction (libspecbleach)

  • Spectral denoising at 24 kHz, 40ms frames, processing stereo int16 audio
  • 7 tunable parameters with thread-safe atomic setters (audio thread reads, main thread writes)
  • Bundled libspecbleach in third_party/ — no external dependency, uses FFTW3 (already required by NR2)
  • HAVE_SPECBLEACH compile flag (ON by default), stubs when disabled
  • Full mutual exclusion with NR2/RN2/BNR in all directions
  • NR4 button in spectrum overlay DSP panel and VFO DSP tab
  • Keyboard shortcut NR cycle extended: Off → NR → NR2 → NR4 → Off
  • Session + per-band persistence, auto-disabled in digital modes, MIDI rx.nr4Enable

DSP Tooltips

  • ~95 tooltips across 4 files, inspired by Thetis and SmartSDR but rewritten
  • Covers all DSP abbreviations: NB, NR, NR2, ANF, NRL, NRS, RNN, RN2, NRF, ANFL, ANFT, BNR, NR4, APF, WNB, AGC, SQL, RIT, XIT, and display controls
  • Consistent style: 1-2 sentences, plain English

How to Use

NR4 Quick Start

  1. Connect to your radio
  2. Click NR4 in the VFO DSP tab or spectrum overlay DSP panel
  3. NR4 activates with sensible defaults (10 dB reduction, adaptive noise on)
  4. Right-click the NR4 button for quick parameter tweaks
  5. Open Settings → AetherDSP Settings → NR4 tab for full control

NR2 Parameter Tuning

  1. Enable NR2 from the VFO DSP tab or overlay
  2. Right-click the NR2 button → adjust Reduction, Smoothing, or AE filter
  3. For deeper tuning: Settings → AetherDSP Settings → NR2 tab
  4. Try different Gain Methods: Gamma (default) works well for SSB; Trained may help on noisy bands

Tooltips

  • Hover over any DSP button, slider, or control to see what it does

Test Plan

  • Build with ENABLE_SPECBLEACH=ON (default) and verify NR4 appears
  • Build with -DENABLE_SPECBLEACH=OFF and verify clean compile (stubs)
  • Enable NR4 → verify audio processing (noise reduced)
  • Toggle NR4 → NR2 → verify mutual exclusion
  • Right-click NR4 button → verify popup with sliders
  • AetherDSP Settings → NR4 tab → adjust all 7 parameters
  • Quit/relaunch → verify NR4 state restored
  • Change bands → verify per-band NR4 state save/restore
  • Switch to DIGU mode → verify NR4 auto-disables
  • Hover over all DSP buttons in overlay → verify tooltips
  • Hover over all VFO DSP tab buttons → verify tooltips
  • Hover over RX applet controls (AGC, SQL, RIT, XIT) → verify tooltips
  • Open AetherDSP Settings → hover over all NR2/NR4 controls → verify tooltips

JJ Boyd ~KG4VCF
🤖 Co-Authored with Claude Code

boydsoftprez and others added 5 commits April 5, 2026 16:22
Phase 1+3 of the AetherDSP feature: exposes NR2 noise reduction
parameters that were previously hardcoded constants.

AetherDSP Settings dialog (Settings menu):
- Modeless dialog with tabs for NR2, NR4, RN2, BNR
- NR2 tab: Gain Method (Linear/Log/Gamma/Trained), NPE Method
  (OSMS/MMSE/NSTAT), AE Filter toggle, Reduction Depth slider,
  Smoothing slider, Voice Threshold slider
- Dark themed, live apply, all values persist via AppSettings
- NR4/RN2/BNR tabs are placeholders for Phase 2

Right-click popup on NR2 buttons:
- Quick access to essential NR2 params (Gain, Smoothing, AE Filter)
- "AetherDSP Settings..." button opens the full dialog
- Works on both spectrum overlay and VFO DSP tab NR2 buttons
- Auto-dismisses on click outside (Qt::Popup)

SpectralNR parameter exposure:
- GainMax, GainSmooth, Q_SPP converted from compile-time constants
  to std::atomic members with setter/getter methods
- Thread-safe: main thread writes, audio thread reads
- Saved params restored when NR2 is enabled via AppSettings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bundle libspecbleach (LGPL-2.1) in third_party/ for NR4 spectral
noise reduction with adaptive noise estimation, psychoacoustic
masking, and tonal component preservation.

Core integration:
- SpecbleachFilter wrapper class with thread-safe parameter setters
- AudioEngine NR4 enable/disable with 4-way mutual exclusion
  (NR2/NR4/RN2/BNR — client-side only, radio NR independent)
- Processing in feedAudioData audio pipeline
- Parameters restored from AppSettings on enable
- Gated by HAVE_SPECBLEACH / ENABLE_SPECBLEACH CMake option
- Requires fftw3f (float precision FFTW3)

GUI buttons and AetherDSP Settings NR4 tab are next.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rsistence

Complete the NR4 (libspecbleach) feature with full UI integration:

- AetherDSP Settings NR4 tab: 7 controls (reduction, smoothing, whitening,
  adaptive noise, estimation method, masking depth, suppression) with
  AppSettings persistence and reset defaults
- NR4 button in spectrum overlay DSP panel and VFO DSP tab grid
- Right-click parameter popup on NR4 buttons (matches NR2 pattern)
- Full MainWindow wiring: syncNr4 lambda, overlay/VFO toggle signals,
  dialog parameter signals, session + per-band persistence, digital mode
  auto-disable, MIDI rx.nr4Enable parameter, diagnostics display
- AudioEngine: 4 new parameter setters (adaptive noise, estimation method,
  masking depth, suppression strength), full 7-param restore from AppSettings
  on enable, mutual exclusion with NR2/RN2/BNR in all directions
- HAVE_SPECBLEACH guards fixed: NR4 API always available with stub no-ops
  when not compiled, matching the BNR pattern
- Keyboard shortcut NR cycle extended: Off → NR → NR2 → NR4 → Off

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
~95 tooltips across 4 files, covering every DSP button, slider,
and receiver control that previously had no inline documentation.
Text inspired by Thetis and SmartSDR descriptions, rewritten in
concise plain English.

- SpectrumOverlayMenu: 13 DSP buttons, 8 DSP sliders, 7 menu
  buttons, 4 ANT panel controls, 14 display panel controls
- VfoWidget: 14 DSP toggle buttons, APF slider, audio tab controls
  (mute, AF gain, SQL, AGC, pan), RIT/XIT buttons
- RxApplet: lock, antenna selectors, step size controls, audio/AGC/
  squelch, RIT/XIT with zero buttons
- AetherDspDialog: NR2 gain method radios, NPE method radios, AE
  checkbox, NR2 sliders, NR4 method radios, adaptive checkbox,
  NR4 sliders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Preserves development context for the feature/aether-dsp-settings branch:
suggested release notes, integration lessons (libspecbleach, guard strategy,
tooltip research, mutual exclusion), and key file reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@boydsoftprez boydsoftprez requested a review from ten9876 as a code owner April 5, 2026 21:56
boydsoftprez and others added 2 commits April 5, 2026 17:59
Merges 5 upstream commits (Intel Mac DMG, TUNE inhibit routing, CW mode
NR2/RN2/BNR auto-disable, VFO flag GPU fix, waterfall color schemes).
Single conflict in SpectrumOverlayMenu.cpp resolved: keep both includes.
Added tooltip for new waterfall color scheme combo from upstream.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GCC on Linux requires the explicit include for std::atomic members
(m_gainMax, m_qSpp, m_gainSmooth). macOS Clang resolves it transitively.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@boydsoftprez boydsoftprez enabled auto-merge (squash) April 5, 2026 22:20
@ten9876 ten9876 merged commit 477f1eb into aethersdr:main Apr 5, 2026
3 checks passed
ten9876 added a commit that referenced this pull request Apr 6, 2026
Runs MSVC build only when CMakeLists.txt, third_party/, or workflow
files change. Catches platform-specific build failures (like the
libspecbleach MSVC issue from #796) before release instead of at
tag time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ten9876 added a commit that referenced this pull request Apr 6, 2026
Runs MSVC build only when CMakeLists.txt, third_party/, or workflow
files change. Catches platform-specific build failures (like the
libspecbleach MSVC issue from #796) before release instead of at
tag time.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ten9876 added a commit that referenced this pull request May 22, 2026
… PR 8) (#2953)

Eight docs leave the top-level docs/ tree, partitioned by purpose:

docs/archive/ — historical planning/session notes, kept for grep
context:
  - issue-2136-feasibility-report.md     (PR #2759, shipped)
  - issue-2136-implementation-plan.md    (PR #2759, shipped)
  - TX_SYNC_FIX_REPORT.md                 (PR #353, RadioModel.cpp still
    references the report by name)
  - aether-dsp-session-notes.md          (#796 maintainer notebook)

docs/data/ — reference fixtures (not bundled, not runtime):
  - SSDR.settings + SmartSDR.exe.config   (SmartSDR parity reference)
  - rxapplet_mode_settings.csv            (per-mode RX control research)
  - vfo_mode_filters.csv                  (VFO filter-preset research;
    VfoWidget.cpp comment updated to new path)

Kept in docs/ (still active):
  - audio_test_plan.md  (17 KB, edited 2026-04-29, ongoing test plan)
  - profile-import-export-manual-checklist.md (PR #2641 QA checklist)

Both new dirs include a one-paragraph README explaining the convention
so a future maintainer doesn't have to guess what belongs where.

Cross-references audited:
  - AppSettings.h:9 mentions "SmartSDR's SSDR.settings" as a concept,
    not a path — no change.
  - RadioModel.cpp:3991 references TX_SYNC_FIX_REPORT by name — no
    change, file is findable via grep/find.
  - VfoWidget.cpp:3324 carried a literal "docs/vfo_mode_filters.csv"
    path — updated to docs/data/.

Verified with a clean local Release build (cmake --build … --target
AetherSDR exits 0).

After this PR, docs/ contains 18 markdown files (architecture/user
docs), the assets/ subdir from PR 5, and the new archive/ + data/
subdirs — matches the acceptance criteria in the cleanup plan.

Principle I.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ten9876 added a commit that referenced this pull request May 28, 2026
## Summary

Drop the \`check-paths\` allow-list job that gated \`check-windows\` and
\`check-macos\` based on a hand-maintained set of files. Both
cross-platform CI builds now run on every PR.

## Why

The path-filter approach has been a chronic leaker. Every time a new
file gained a platform-guarded branch (\`#ifdef Q_OS_WIN\`, \`#ifdef
Q_OS_MAC\`, \`HAVE_PIPEWIRE\`, etc.) that wasn't on the allow-list, CI
silently skipped the relevant cross-platform check and the regression
surfaced at release tag time. The follow-up was always to add another
path to the filter — and then the same class of issue would resurface
elsewhere a few PRs later.

Pattern receipts:
- #796 — original \"MSVC issue slipped past CI\" lesson
- #2633#2662 — macOS \`m_daxBridge\` reference inside macOS-only
guard, missed
- #2670 — Windows behavior change not exercised by CI
- #2671 — added MainWindow.cpp/.h to filter after a miss
- #2929#3052 — WASAPI mono-mic recovery landed unverified; added
AudioEngine.cpp/.h
- #3210 — re-added AudioEngine after a relapse
- v26.5.3 — ClientPhaseRotator.cpp \`M_PI\` MSVC break slipped through
- #3241 (yesterday) — CwSidetonePortAudioSink WASAPI fix; entire
\`#ifdef Q_OS_WIN\` block never compiled by CI because the file wasn't
on the filter

## Trade-off

Cost: ~15-20 min of GitHub Actions runner time per PR (Windows + macOS
in parallel, both cached aggressively — cold ~5 min, warm ~2-3 min).

Benefit: a whole class of release-time regression we've been paying for
repeatedly.

## Test plan

- [x] YAML valid (\`python3 -c 'import yaml; yaml.safe_load(...)'\`)
- [ ] Confirm \`check-windows\` and \`check-macos\` actually run on this
PR (no longer marked \`skipping\`)
- [ ] Both pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
G6PWY-Chris pushed a commit to G6PWY-Chris/AetherSDR that referenced this pull request Jun 22, 2026
…sdr#2933, PR 8) (aethersdr#2953)

Eight docs leave the top-level docs/ tree, partitioned by purpose:

docs/archive/ — historical planning/session notes, kept for grep
context:
  - issue-2136-feasibility-report.md     (PR aethersdr#2759, shipped)
  - issue-2136-implementation-plan.md    (PR aethersdr#2759, shipped)
  - TX_SYNC_FIX_REPORT.md                 (PR aethersdr#353, RadioModel.cpp still
    references the report by name)
  - aether-dsp-session-notes.md          (aethersdr#796 maintainer notebook)

docs/data/ — reference fixtures (not bundled, not runtime):
  - SSDR.settings + SmartSDR.exe.config   (SmartSDR parity reference)
  - rxapplet_mode_settings.csv            (per-mode RX control research)
  - vfo_mode_filters.csv                  (VFO filter-preset research;
    VfoWidget.cpp comment updated to new path)

Kept in docs/ (still active):
  - audio_test_plan.md  (17 KB, edited 2026-04-29, ongoing test plan)
  - profile-import-export-manual-checklist.md (PR aethersdr#2641 QA checklist)

Both new dirs include a one-paragraph README explaining the convention
so a future maintainer doesn't have to guess what belongs where.

Cross-references audited:
  - AppSettings.h:9 mentions "SmartSDR's SSDR.settings" as a concept,
    not a path — no change.
  - RadioModel.cpp:3991 references TX_SYNC_FIX_REPORT by name — no
    change, file is findable via grep/find.
  - VfoWidget.cpp:3324 carried a literal "docs/vfo_mode_filters.csv"
    path — updated to docs/data/.

Verified with a clean local Release build (cmake --build … --target
AetherSDR exits 0).

After this PR, docs/ contains 18 markdown files (architecture/user
docs), the assets/ subdir from PR 5, and the new archive/ + data/
subdirs — matches the acceptance criteria in the cleanup plan.

Principle I.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
G6PWY-Chris pushed a commit to G6PWY-Chris/AetherSDR that referenced this pull request Jun 22, 2026
## Summary

Drop the \`check-paths\` allow-list job that gated \`check-windows\` and
\`check-macos\` based on a hand-maintained set of files. Both
cross-platform CI builds now run on every PR.

## Why

The path-filter approach has been a chronic leaker. Every time a new
file gained a platform-guarded branch (\`#ifdef Q_OS_WIN\`, \`#ifdef
Q_OS_MAC\`, \`HAVE_PIPEWIRE\`, etc.) that wasn't on the allow-list, CI
silently skipped the relevant cross-platform check and the regression
surfaced at release tag time. The follow-up was always to add another
path to the filter — and then the same class of issue would resurface
elsewhere a few PRs later.

Pattern receipts:
- aethersdr#796 — original \"MSVC issue slipped past CI\" lesson
- aethersdr#2633aethersdr#2662 — macOS \`m_daxBridge\` reference inside macOS-only
guard, missed
- aethersdr#2670 — Windows behavior change not exercised by CI
- aethersdr#2671 — added MainWindow.cpp/.h to filter after a miss
- aethersdr#2929aethersdr#3052 — WASAPI mono-mic recovery landed unverified; added
AudioEngine.cpp/.h
- aethersdr#3210 — re-added AudioEngine after a relapse
- v26.5.3 — ClientPhaseRotator.cpp \`M_PI\` MSVC break slipped through
- aethersdr#3241 (yesterday) — CwSidetonePortAudioSink WASAPI fix; entire
\`#ifdef Q_OS_WIN\` block never compiled by CI because the file wasn't
on the filter

## Trade-off

Cost: ~15-20 min of GitHub Actions runner time per PR (Windows + macOS
in parallel, both cached aggressively — cold ~5 min, warm ~2-3 min).

Benefit: a whole class of release-time regression we've been paying for
repeatedly.

## Test plan

- [x] YAML valid (\`python3 -c 'import yaml; yaml.safe_load(...)'\`)
- [ ] Confirm \`check-windows\` and \`check-macos\` actually run on this
PR (no longer marked \`skipping\`)
- [ ] Both pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants