Releases: aethersdr/AetherSDR
v26.6.1.1
Hotfix release on top of v26.6.1 — resolves the macOS DMG release-build failure plus two GUI fixes. No other changes. Full detail in CHANGELOG.md.
Fixes
- macOS DMG release build unblocked (#3349) — the
create-dmgstep referenced a background image (docs/assets/logo-invert.png) that had been removed in an earlier cleanup, and a trailing|| truemasked the failure so DMG signing then failed on a disk image that was never produced. The Apple Silicon DMG now builds, signs, and notarizes cleanly. - Tuning-step toast no longer fires on radio syncs (#3337) — the "Step: …" toast only appears on deliberate user step changes, not on radio-driven status updates.
- Radio Setup tall tabs stay reachable (#3347) — tab pages are wrapped in a scroll area so controls on tall tabs are no longer clipped off-screen.
Downloads
- Linux —
x86_64/aarch64AppImage - macOS — Apple Silicon DMG (signed + notarized)
- Windows — installer (
setup.exe) + portable ZIP - Stream Deck — plugin + StreamController bundle
AetherSDR v26.6.1 — HID input devices + Windows hardening + new protocol surfaces
143 commits across 14 contributors since v26.5.3. Full detail in CHANGELOG.md.
Headlines
HID input devices — three new physical-device classes, all opt-in:
- Elgato StreamDeck+ — encoders, LCD buttons, touchscreen with live labels (#3236)
- Ulanzi Dial — cross-platform on Linux evdev, Windows, and macOS (#3238, #3239)
- Native Icom RC-28 encoder support (#3293)
- AetherPad RC-28 Arduino emulator recognised via VID/PID alias (#3171)
Windows hardening
- PerMonitorV2 DPI awareness (#3208)
- Discrete-GPU preference on hybrid laptops (#3299)
- Microsoft Store MSIX packaging groundwork + embedded DFNR weights (#3178, #3205, #3225)
- Windows Snap restoration for the frameless title bar (#3069)
- WASAPI CW sidetone routing for low-latency keying (#3193 → #3241)
New protocol surfaces
- SmartCAT TCP server — TS-2000 + FlexCAT dialects (#3131)
- Unified RADE TX pipeline — EOO frame transmission + callsign encoding (#3221)
- AX.25 1200-baud VHF Bell 202 receive + transmit (#3253, #3256)
- SSDR-parity PWR/SWR metering on PGXL/TGXL amplifier applets (#3277)
- TCI
clicked_on_spotevent for Log4OM interoperability (#3145)
Reliability sweep
- 7-year-old NR2 Gamma crackling fix — SpectralNR Bessel function variants corrected (#1507 → #3275)
- Multi-monitor main-window restore under Minimal Mode (#2483 → #3174)
- Multi-pan TCI spot freeze — spot-marker rebuilds coalesced (#2481 → #3310)
- FreeDV / Quindar interactions (#3317, #3320) + RADE filter passband alignment (#3301)
New applets and UI
- HLTH antenna health applet (#3153)
- Customizable button bar with favourites + push-down drawer (#3150)
- Reference target curve overlay on the Aetherial Parametric EQ (#3259)
- AetherControl double-click to latch / unlatch (#3103)
- ESC click-to-adjust polar display for phase and gain (#3134)
Adaptive throttle UX
- Toggle in the Connect panel for all modes (#3175)
- Visibility through status-bar heartbeat colour and Network Diagnostics graphs (#3203)
Theming foundation (early beta)
A runtime theming system lands as early beta, opt-in via Settings → Theme Editor. Default Dark remains the shipped default. Token names, the .aethertheme file format, and the editor UX are expected to change before stabilising — please file issues with the theme label if you try it.
ThemeManagerfoundation + 51-token design taxonomy- Theme Editor dialog with live colour editing, gradient editor, font + sizing pickers
- New Default Light theme alongside Default Dark
.aetherthemeimport/export with drag-and-drop- Embedded DSEG Modern 7- and 14-segment fonts (SIL OFL 1.1)
See the Theming section in CHANGELOG.md for phase-by-phase detail.
Build, CI, and packaging
check-windows+check-macosalways run on every PR (#3244) — retires the path-filter allow-list that was leaking platform-only regressions- Sanitizer step pinned to bash so
pipefailworks (#3155) - SOURCE_DATE_EPOCH for reproducible builds (#3165)
- System-library opt-in flags for distro packagers (#3135 — @dawkagaming):
USE_SYSTEM_ZLIB,USE_SYSTEM_MSPACK,USE_SYSTEM_LIBMOSQUITTO,USE_SYSTEM_RTMIDI - Lowercase binary name option (#3138 — @dawkagaming), Linux 256×256 icon (#3143 — @dawkagaming), improved
.desktopdescription (#3074 — @dawkagaming) - Debian multiarch tuple for Qt6GuiPrivate probe (#3159 — @K5PTB)
Contributors
Big thanks to @jensenpat (22 commits — TCI/CAT, multi-monitor restore, network diagnostics), @aethersdr-agent (the AetherClaude orchestrator, 28 commits), @NF0T (10 commits — Windows packaging, RADE TX pipeline), @nigelfenton (8 commits — TCI fixes), @M7HNF-Ian (7 commits — XVTR, slice spawning, NR2 Gamma fix), @chibondking (6 commits — bandplan corrections, panadapter context slice spawning), @K5PTB (5 commits — MQTT publish topics, CMake Debian multiarch fix), @dawkagaming (4 community PRs — distro packaging quality-of-life), @rfoust (4 commits), and first-time contributors @w5jwp (Icom RC-28 encoder support), @motoham88 (StreamDeck+ support), @mvanhorn (theme migration tool cleanup), and @VU3ESV (macOS phys_footprint memory reporting).
73, Jeremy KK7GWY & Claude (AI dev partner)
Downloads
Linux AppImage, macOS universal DMG, Windows installer and portable ZIP are attached below — built and signed by CI workflows on this tag.
Verifying releases: see docs/VERIFYING-RELEASES.md. Signing key: docs/RELEASE-SIGNING-KEY.pub.asc.
AetherSDR v26.5.3 — Aetherial Audio TX completion + security hardening + 100-commit reliability sweep
AetherSDR v26.5.3 — Aetherial Audio TX completion + security hardening + 100-commit reliability sweep
139 commits across 14 contributors in this cycle. The headline is the TX path of the Aetherial Audio Channel Strip reaching feature-complete with the new PAPR processor and split-band de-esser, two published security advisories landing their enforcement phases (SmartLink TLS cert pinning + CAT PTY symlink hardening), the MQTT configuration moving into a dedicated Settings dialog, and a substantial reliability sweep across audio (WASAPI / CoreAudio / macOS mic), spectrum (TX waterfall scroll rate, panadapter dBm prime), and CAT (rigctld, TCI, MIDI). Native Hamlib NET rigctl ships as a first-class CAT path alongside TCI.
Security advisories landed
GHSA-wfx7-w6p8-4jr2 — SmartLink TLS cert pin enforcement Phase 2 (#3026)
Phase 1 (warn-only) shipped in v26.5.2; Phase 2 promotes a cert-fingerprint mismatch to a hard handshake pause. On mismatch the client emits a modal dialog (Accept new cert / Reject and disconnect) before sending wan validate — a MITM attacker never sees an authenticated session. New SmartLink tab in Radio Setup lists pinned certs with per-row Forget. Pin cache schema migrates Phase 1 string entries to Phase 2 {fp, pinnedAt} objects on first save.
GHSA-qxhr-cwrc-pvrm — CAT PTY symlink hardening (#3027)
rigctld's slice PTY symlinks moved from /tmp/ to per-user runtime dirs ($XDG_RUNTIME_DIR on Linux, ~/Library/Application Support/... on macOS) so a local attacker can no longer race-create the symlink targets. Windows unaffected.
Headline content
Aetherial Audio Channel Strip TX path completion (#3024)
- PAPR processor — new all-pass biquad cascade (4 stages at 300/700/1500/2500 Hz) for peak-to-average-power-ratio reduction. Drive (0–18 dB) + Phase knobs in the channel strip; auto-makeup gain linked to Drive so RMS lifts alongside peaks instead of disappearing into the compressor's gain reduction.
- Split-band de-esser — replaces the old broadband-attenuation pattern (
l *= gainLin; r *= gainLin;) withoutput = full + bandpass × (gain − 1). Fixes the broadband-attenuation bug that was costing operators ~30W of forward power on voice content. User-selectable cascade stages (12/24/36/48 dB/oct). - Peak-hold toggle on all meters; CRST + RMS + THRESH styling unified via the canonical
MeterSmoother(30 ms attack / 180 ms release at 120 Hz). - 10 Hz throttle on text readouts; live audio response at 125 Hz — meters track the audio without spamming the GUI thread.
Native Hamlib NET rigctl (#2975)
Full 149-test rigctld implementation for WSJT-X / JTDX / fldigi / Winlink VARA / N1MM+ / DXLog interoperability without a standalone rigctld bridge. Slices A–H each expose a TTY (per-user runtime path on Linux + macOS, see #3027) and a TCP port (4532–4539).
MQTT settings dialog refactor (#3051 — @s53zo)
Substantial community PR that moves MQTT configuration out of the live applet into a dedicated Settings → MQTT… dialog. The applet stays as the live surface (connect/disconnect, status, message log, publish buttons); the dialog owns broker credentials, TLS/CA config, subscription rows, display-on-panadapter flags, and publish button definitions. Persists On/Off state as MqttEnabled for auto-reconnect on startup. Also self-found and fixed a subscription-state bug where removed topics could survive across reconnects. Maintainer follow-ups consolidate the 8 MQTT flat AppSettings keys into a single nested MqttSettings JSON block per Principle V, with one-shot transparent migration from legacy keys.
TX waterfall scroll rate matches RX (#3031)
After #3019 stabilised TX waterfall rendering across slices, the FFT-derived row path scrolled at line_duration cadence (~10 rows/sec) while RX native tiles arrived at the FFT rate (~30 rows/sec) — TX appeared 3× slower than RX. Diagnosed via inline probe; corrected by dropping the FFT row throttle and emitting one row per FFT frame.
Panadapter dBm range prime on reconnect (#3034 — @chibondking)
Secondary panadapters (Slices B–H) could go completely flat on reconnect with the dBm scale stuck at the default [-50, +50] while the radio's saved range was different. Cause traced end-to-end: noise-floor auto-adjust animated from the wrong baseline, fired dbmRangeChangeRequested with bogus values, and the pendingDbm guard locked them in. Fix: prime the spectrum widget with the pan's current dBm range immediately on wire. Solid community contribution.
FlexControl wheel tuning overhaul (#3029 — @rfoust)
Two-axis QoL improvement to the virtual FlexControl wheel: new Mouse Sensitivity slider, de-jitter clamping at 15°, lazy re-anchoring across centre-zone crossings, coast / pointer-clock separation, and UI polish.
WASAPI mono-only USB PnP mic silent-open recovery (#2929)
Some USB PnP mics report mono-only capture natively; Qt accepts an unsupported stereo open and returns a non-null QIODevice that delivers zero bytes. Three-layer fix: pre-emptive channel-count clamp, fallback-ladder skip of only the failed (rate, ch) combo, and a 1.5 s silent-open watchdog that retries as mono.
ATU pre-tune Auto-mode safety nets (#3050)
Four-layer guardrail bundle for the unattended ATU sweep — license-class filter (data-driven from the active bandplan), max-points soft cap with TX-duration warning, high-power warning above 20 W, and audible cue on per-point timeout + 3-fail bypass abort. Paired with #3063 for per-band early exit (3 consecutive failures on a band skip past that band instead of aborting the whole sweep).
Windows hybrid-GPU support (#1921)
NvOptimusEnablement = 1 and AmdPowerXpressRequestHighPerformance = 1 exports so the Windows binary launches on the discrete GPU on hybrid laptops. Sidesteps the Intel iGPU D3D11 driver bug that crashed AetherSDR during QRhiWidget reparenting.
TCI server enhancements (#2841, #2950, #3065)
Panadapter FFT row forwarding to subscribed TCI clients, new tx_gain command + ALC reading via tx_sensors, and a TX overflow-mode picker — right-click the TCI TX slider to choose Clip (saturating ±1.0, default), NaNGuard (bit-exact passthrough; only zero NaN/Inf), or Measure (true bypass — count overshoots for telemetry, never mutate samples). WSJT-X / FT8 operators chasing bit-exact tone fidelity can now drop the float-domain limiter entirely.
Also new this cycle
Features: AetherControl virtual FlexControl (#2888), adaptive frame-rate throttle + graceful reconnect (#2829), mute-all-slices + reconnect mute fix (#2833), spectrum Ctrl+wheel cursor-anchored zoom (#2869), multiFLEX per-client disconnect (#2981), loop antenna A/B controls (#2863), MQTT antenna display names (#2881), cycle-TX-slice shortcut (#2836), drag value popups on sliders (#2944), audio device hotplug prompt suppression (#2926), FlexControl WheelAgcT mode (#2907), status-bar slice-locked toast (#2984).
Notable fixes: TCI use-after-free in queued lambdas (#2814), RigctlProtocol use-after-free (#2995), set_split_vfo TX slice ping-pong (#2931), rigctld cwx routing through CwxModel (#2909), MIDI VFO encoder direction + step size (#2993), MIDI tx.mox uses isTransmitting (#2859), HID IcomRC28Parser byte offsets (7-year-old bug, #1896), slice-state cached + replayed for profile recall (#2917), off-screen slice indicator click reveal (#2941).
Refactor & internals: AppSettings nested-JSON consolidation (MQTT block; Principle V), MeterSmoother canonicalisation, revealOffscreen ternary collapse, post-#3019 spectrum FFT accumulator removal, off-screen click comfort margin, panadapter dBm prime path rewrite, and an Ae...
AetherSDR v26.5.2.1 — Six days of community momentum + Day-1 hotfix sweep
AetherSDR v26.5.2.1 — Six days of community momentum + Day-1 hotfix sweep
The first natural-cadence release after the 1.0-equivalent v26.5.1. 123 commits in six days, driven by an unusually active week from community contributors and the AetherClaude orchestrator — plus four Day-1 fixes shipped within hours of the original v26.5.2 tag.
Why .1? v26.5.2 was tagged earlier today and immediately surfaced a regression in TCI TX audio level (down ~6 dB at the source for WSJT-X / JTDX), a Windows process-hang on close, and an AppImage x86_64 build failure. Rather than leave v26.5.2 advertised with known bugs, this hotfix consolidates all four fixes into a single recommended release. Anyone targeting v26.5.2 should install v26.5.2.1 instead.
Headline content
AetherModem — AX.25 packet decoder, Phase 0 (@jensenpat)
Native HDLC/AX.25 receiver with a 21-lane phase bank, FCS validation, and a dedicated Packet Decode dialog. RX is active on 300 baud HF and 1200 baud VHF; TX is live on 300 baud HF with timing refinements queued for Phase 1. (#2753, #2766, #2788, #2791)
FreeDV / RADE ergonomics (@NF0T)
Sync + SNR indicator in the VFO widget for FDVU/FDVL slices, a far-end info row showing decoded callsign and frequency offset, and end-of-over (EOO) callsign decode that posts to FreeDV Reporter. (#2776, #2660, #2659)
4 m / 2 m bands on FLEX-6500 and FLEX-6700
Surfaced via ModelCapabilities using FlexLib ModelInfo.cs as the authority. Works with the radio's internal XVTR or any external transverter. (#2757, closes #695)
PersistentDialog architecture sweep
New PersistentDialog base class + showOrRaisePersistent<T>() lifecycle pattern. 10+ dialogs migrated: Profile Manager, Profile Import/Export, Memory, Network Diagnostics, PropDashboard, TxBand, Waveforms, RadioSetup (primary + 3 secondary entry points), DxCluster, AetherDsp, AX.25 Packet Decoder, MIDI, MQTT, SpotHub. Frameless toggle now propagates correctly across all of them; geometry persists; the duplicate-window class of bug is gone. (#2644, #2676, #2742, #2772, #2774, #2775, #2795)
Spectrum & panadapter stabilization (@rfoust)
Panadapter restore-on-reconnect across multi-pan and floating-pan setups, macOS GPU lifecycle cleanup, dBm-range echo smoothing (no snap-back after release), Ctrl-drag dBm zoom, Ctrl-drag waterfall rate. (#2786, #2792, #2793, #2717, #2783)
Protocol hardening
M-message severity parsing (no more Info notices popping modals), hex meter num field handling, tx_slice_mode from transmit status, FlexWaveformModel for firmware v4.2.18 waveform status. (#2785, #2771, #2773, #2759)
Also new this cycle
Features: Smart Spot Filtering, auto-squelch 3-way SQL cycle, local antenna display names, ATU band pre-tune sweep, FlexRadio .ssdr_cfg profile import/export, FlexControl CWX F1-F12 macros, independent RX/TX CW decode toggles, audio device hotplug with notification dialog, PEP peak-hold tick on FWDPWR, two-tone TUNE via right-click, TNF status tooltip, network audio packet-loss concealment, pan-follow-VFO flag-edge trigger, radio-letter slice display for Multi-Flex, interlock notification system, numeric entry for Aetherial Audio params, RF Gain / AGC-T shortcuts.
Notable fixes: Profile-Save silently no-oping on existing names, XVTR waterfall offset on unvalidated profiles, XVTR direct-entry tuning above 450 MHz, vanished panstack on left-dock startup, ATU walk on discrete-channel bands (60 m), TCI v2.0 spec/impl compliance + RF2K-S amplifier interop, macOS Bluetooth headset mic capture rate, macOS frameless title-bar drag, CW Int16 sidetone fallback on WASAPI, RADE DAX stream lifecycle on macOS, Windows DAX flag toggle on slice-mode change, and the spot-tooltip / cluster-echo / DVK shortcut polish that always shows up in a community-driven cycle.
Infrastructure: log rotation + retention cap, AsyncLogWriter and PerfTelemetry test harnesses, IARU R1 reference table lock, VirtualAudioBridge thread safety, CI post-merge guard for stale-snapshot reverts, in-repo URL refresh after the ten9876 → aethersdr org move, zlib 1.3.1 vendored, spec-kit constitution at .specify/memory/constitution.md, audio pipeline + TCI mDNS schema docs.
Day-1 hotfix sweep (new in v26.5.2.1)
TCI TX audio level regression vs v26.5.1 (#2806)
v26.5.2's TCI server identity (device:SunSDR2DX + protocol:ExpertSDR2,1.9, added in #2597 for RF2K-S amplifier whitelist compatibility) hit a specific code path in WSJT-X's TCITransceiver that halves outgoing TX sample amplitude (K2 = 0.499 / 0x7FFF vs K1 = 0.999 / 0x7FFF) when both of these match:
device:is"SunSDR2DX"or"SunSDR2PRO"protocol:is not"ExpertSDR3"
Operators measured ~70 W of 100 W expected on a 100 W slice. The fix changes identity to device:AetherSDR + protocol:ExpertSDR3,1.5, which clears both triggers and selects WSJT-X command formats that AetherSDR has supported correctly since v26.5.1.
Everything else from #2597 (strict init-burst order, vfo_limits, if_limits, channels_count, split_enable, post-READY audio stream configuration) is preserved — that's the bulk of what the RF2K-S TCI parser actually keys on to engage. Configurable / per-client adaptive identity to restore the SunSDR2DX whitelist half is tracked in #2806.
Windows process lingering in Task Manager after close (#2802, @chibondking)
Three independent root causes ganged up to keep AetherSDR.exe visible in Task Manager indefinitely after the main window closed:
m_aetherialStripcarriesQt::Windowfor an independent taskbar entry; Qt 6 treats that as top-level forquitOnLastWindowClosed, and the defaultWA_QuitOnClose = trueblocked the quit signal.m_appletPanelFloatWindowis constructedparent = nullptr(a real top-level) and was the only top-level secondary window in the codebase missingWA_QuitOnClose = false.MqttClient::~MqttClientcalledmosquitto_destroy()on Windows without ever stopping the loop thread. libmosquitto's contract requiresloop_stopbeforedestroy; the destructor now callsmosquitto_loop_stop(m_mosq, true)(force=true, can't deadlock).
Each fix is a single line matching an existing precedent in the codebase. Result: process exits within ~1 s of main-window close, every time.
Linux AppImage build failure on gcc 11 strict mode (#2799)
third_party/libmodem_core/bitstream.h:192 used unqualified container inside the noexcept(noexcept(...)) clause of a class-template member. gcc 11.4 (Ubuntu 22.04's native compiler, used by the AppImage workflow) requires this->container for two-phase name lookup. Newer gcc (the Docker CI image) was lenient; AppImage CI bombed on the v26.5.2 tag push. Fix qualifies both references with this-> — pure portability, zero user-visible change.
SSA (Sweden) band plan (#2805, @NF0T)
Swedish national overlay on IARU Region 1 with the correct 6 m band edge (50–52 MHz, not the IARU R1 file's 50–54), embedded power-limit suffixes on bands where PTSFS 2025:1 imposes substantially lower caps (60 m 15 W e.i.r.p., 30 m 150 W p.e.p.), Swedish segment labels (ALLA, FYRAR, SMAL DIGI), and finer 6 m segmentation matching SSA's published v3.0 plan. 89 Swedish-language activity-center / digital / beacon / emergency spots. Auto-loaded by BandPlanManager::loadPlans(), surfaced in View → Band Plan submenu.
Contributors
Huge thanks to:
- @jensenpat — AetherModem Phase 0, AX.25 receive timing, FFT floor lock edge cases, XVTR waterfall offset, RF Gain / AGC-T shortcuts, spot auto-mode routing
- @NF0T (Ryan) — FreeDV sync indicator, Waveforms dialog, FlexWaveformModel protocol, hex meter parser, CWX context menu + CharGap, RADE auto-deactivate, tx_slice_mode, RX-applet radeActivated restore, SSA (Sweden) band plan
- @rfoust (Robbie) — panadapter persistence + macOS GPU lifecycle, dBm Ctrl-zoom, Ctrl-drag waterfall rate, TNF status tooltip, panadapter restore-window extension, spectrum dBm echo smoothing, FFT floor edge cases
- @chibondking (CJ Johnson) — Windows process-hang root-cause analysis and triple-fix (Day-1 hotfix)
- @M7HNF-Ian — spot tooltips near waterfall edge, SpotHub auto-reconnect
- @algojogacor — spot label gap in spectrum
- AetherClaude (@aethersdr-agent) — 30+ mechanical fixes including the entire PersistentDialog migration sweep, persistence fixes, log rotation, naming polish, AsyncLogWriter + PerfTelemetry test harnesses, NoiseFloor diagnostics
Verifying this release
Detached PGP signatures (.asc) accompany every artifact. Public key at docs/RELEASE-SIGNING-KEY.pub.asc and on the usual keyservers (keys.openpgp.org). See docs/VERIFYING-RELEASES.md for the full procedure. macOS bundles are also notarized by Apple.
Full changelog
See CHANGELOG.md for the complete commit-by-commit list (both the v26.5.2 entry and t...
AetherSDR v26.5.1 — Native. Open. Yours.
AetherSDR v26.5.1 — Native. Open. Yours.
The 1.0-equivalent stable release.
After eight 0.9.x cycles, AetherSDR is ready to drop the pre-1.0 framing. The client now covers every documented SmartSDR feature on the FLEX-6000, FLEX-8000, and Aurora platforms; ships the Aetherial Audio Channel Strip's RX and TX paths in full; and runs natively on Linux, macOS, and Windows without Wine, virtual machines, or compatibility shims of any kind. Confidence in stability across the three platforms is high enough that we no longer want the version string to imply otherwise.
This release also marks the project's switch from semver to CalVer (YY.M.patch). AetherSDR's release cadence is driven by FlexLib protocol changes, ham contest seasons, and a steady stream of community-contributed fixes — not by API stability commitments to downstream consumers. CalVer communicates "this is what shipped in month X" more honestly than a semantic version would. The previous v0.9.x tags remain in git history; new tags start at v26.5.1.
What AetherSDR is, at 1.0
A Linux-native client for FlexRadio Systems transceivers, built from the ground up with Qt6 and C++20. It speaks the SmartSDR protocol natively — v1.4.0.0, validated against firmware 4.2.18 on a FLEX-8600 — and aims to replicate the full SmartSDR experience without depending on any Windows-specific tooling.
Core capabilities
- GPU-accelerated rendering — QRhi waterfall + FFT spectrum on GPU (OpenGL/Metal/D3D11), 71 % CPU reduction vs. CPU rasterization, heat-map FFT display.
- Multi-slice operation — color-coded VFO overlays, independent TX assignment, diversity mode with ESC beamforming.
- Multi-panadapter — up to 8 pans (FLEX-6700), 6 layout options, detachable pop-out windows, per-pan display controls, native VITA-49 waterfall tiles.
- Full RX/TX control — filter presets, custom filter edges, AGC, DSP, EQ, mic/compression gauges, ATU, TUNE/MOX.
- Aetherial Audio Channel Strip — unified RX and TX DSP suite (gate, EQ, compressor, de-esser, tube, AetherVoice exciter, Freeverb on TX, brickwall limiter on TX / output trim on RX) with a savable preset library and a wall-clock-accurate scope on each side.
- Client-side noise reduction — NR2 (spectral), RN2 (RNNoise neural), NR4 (libspecbleach), DFNR (DeepFilterNet3 neural), BNR (NVIDIA GPU AI denoiser), MNR (macOS MMSE-Wiener).
- AetherSweep — in-panadapter SWR analyzer with log scale, threshold-band shading, interpolated bandwidth at SWR ≤ 1.5 / 2.0.
- Network Diagnostics — per-metric trend graphs, packet-loss / RTT / jitter metrics, live log tail.
- Memory channels + profiles — memory bank with quick recall; global / mic / TX profile management synced with the radio.
- CW operator suite — real-time Morse decoder with auto pitch/speed detection, keyboard + MIDI-mapped straight key and iambic paddles with full break-in / QSK respect, optional Apollo-era Quindar tones on PTT.
- SpotHub — DX Cluster, RBN, WSJT-X, POTA, FreeDV Reporter spots with density badges, auto-mode switch, auto-reconnect.
- DAX virtual audio — 4 RX + 1 TX channels for WSJT-X, fldigi, VARA, JS8Call (Linux PipeWire native / PulseAudio, macOS CoreAudio, Windows via TCI / external bridges).
- DAX IQ streaming — raw I/Q to SDR apps at 24/48/96/192 kHz.
- SmartLink remote operation — Auth0 login, TLS command channel, WAN UDP streaming with credential persistence.
- TCI server — full TCI v2.0 protocol over WebSocket: CAT + audio + IQ + CW + spots in one connection.
- CAT control — 4-channel rigctld TCP + virtual serial ports, CW macros for contest loggers.
- MIDI controller mapping — Learn mode, 50+ parameters, named profiles.
- FlexControl USB tuning knob — auto-detect, acceleration, configurable buttons; new WheelRit / WheelXit modes in this release.
- Serial PTT/CW keying — USB-serial DTR/RTS for external keyers and foot switches.
- FreeDV RADE — AI-based digital voice codec with client-side neural encoder/decoder.
- 4o3a Tuner Genius XL — relay control, autotune, 3x1 antenna switch, SWR/power gauges.
- Multi-Flex — independent operation alongside SmartSDR/Maestro with clickable dashboard.
- Adaptive predistortion (APD) — SmartSignal toggle and status display for FLEX-8000 series, including External APD sampler-port selection for training against an external linear amplifier.
Supported hardware
Tested against:
- FLEX-6000 series: 6300, 6400, 6400M, 6500, 6600, 6600M, 6700
- FLEX-8000 series: 8400, 8400M, 8600, 8600M
- Aurora series: AU-510, AU-510M, AU-520, AU-520M
- ML-, CL-, and RT-series devices
What's new since v0.9.8
55 commits over 4 days. Highlights — for the comprehensive list see CHANGELOG.md.
Features
- S-History v2 — CNN classifier that distinguishes voice signals from QRM channels in the Signal History overlay. Voice and QRM markers age out independently; QRM channels with voice riding on top get both markers simultaneously so operators can see the interference and the person trying to work through it.
- Connected Stations dialog when multiFLEX is disabled — see who else is on the radio without needing Multi-Flex mode.
- FPS meters and performance telemetry — footer FPS readouts for spectrum/waterfall plus a perf-heartbeat hook feeding the in-progress System Info diagnostics dialog.
- 8-axis edge resize on the frameless main window, matching the Aetherial Audio Channel Strip.
- SpotHub Display tab + tunable Signal History consolidation with grouped sections.
- Frameless chrome on Memory Channels dialog — gradient title bar, drag handle, 8-axis resize.
- Float popped-out applet panel as a frameless project window — three new title-bar icons (dock-left / dock-right / pop-out) replace the legacy status-bar
☰toggle. - Always-on-Top pin on popped-out applets for instrument-on-instrument workflows.
- FlexControl WheelRit / WheelXit modes drive RIT and XIT offsets directly without touching slice frequency.
Bug fixes
- Linux waterfall smear after TX — 10–18 s post-TX vertical-stripe smear traced to a stale "last good row" retained across the TX→RX transition. Cleared on TX-exit; blanker now gated on
!m_transmitting. - Multi-Flex / multi-pan crash cluster — slice reduction crash on disconnect cascade, float→dock GPU corruption, and exit crash on rapid quit-while-streaming all consolidated and guarded with lifetime checks.
- Spot
background_colorhonored when override is off — third-party spotting tools (wave-flex-integrator, SpotCollector) encoding priority / worked-before via the FlexLibbackground_colorfield now render correctly. Was silently dropped at the model→view boundary. - ALC gauge rewired to SW ALC meter — was previously driven by HWALC (RCA voltage telemetry), producing meaningless readings. Mirror across Phone + CW panels with the new
HGauge::setFillFromRightmode. - DSP curve widgets: HarfBuzz reshape on every paint — DSP curve axis labels now cached as
QStaticTextwith aggressive caching; ~7× drop inshapeTextcost. - macOS app icon missing on local builds —
.icnsgeneration moved into CMake (sourced from the committeddocs/logo-circle.png); local builds now match CI builds exactly. - Stream Deck mute toggle — corrected TCI command dispatch.
- DAX IQ silently broken on Windows / non-PipeWire Linux — proper fallback for systems without native PipeWire.
- Windows ClangCL build failures — NR4/specbleach toolchain compat.
- RTTY squelch auto-disable — squelch on RTTY notches characters out and breaks decoding.
- CWX stuck-in-TX after macro — releases TX cleanly when the queue drains.
- Windows 48 kHz L-R audio pan — restored to match macOS / native-rate paths.
- Protocol order: send
client program/low_bw_connectbeforeclient guito match SmartSDR-for-Windows. - TCI volume/drive/rx_volume dispatch wired through.
- Plus a long list of smaller fixes across CW macros, MIDI toggles, FreeDV reporter, slice capacity clamping, popout window chrome, AmpApplet telemetry, and more.
Infrastructure
- Buffered async file logging — log writes no longer block the GUI thread on slow disks or network shares.
- Qt 6.7+ GPU rendering requirement documented.
- macOS .icns generated at build time via CMake — no committed binary, no hidden CI-only step.
- Bumped
actions/cache4 → 5, refreshed Supported Hardware list, documentedlibopengl0build dep on Debian/Ubuntu.
Contributor credits
This release wouldn't exist without the community. Big thanks to:
- @jensenpat — macOS
.icnsbuild-time generation, FlexControl wheel modes, popout window frameless lifecycle, plus the long tail of fixes through the 0.9.x cycle (Hamlib NET-rigctl interoperability, Windows spot-client thread affinity crash, hardware-PTT mic_selection, filter widen/narrow mode-correctness, AetherSweep Phase 2) - @chibondking (CJ Johnson) — Windows UI scaling settings path, plus the broader 0.9.x contribution stream (editable CW value fields, cwDelay optimistic-update, UI Scale reset-to-100% fix, macOS relaunch via
open -n, PGXL OPERATE/STANDBY sync) - @rfoust (Robbie Foust) — RX output panel rebuild + canonical meter ballistics, DAX IQ Windows/non-PipeWire-Linux fix, TCI volume/drive/rx_volume command dispatch, audio shutdown null-guards
- @aethersdr-agent — AetherClaude, the project's autonomous coding agent. Implemented parallel pull requests on
aetherclaude-eligibleissues including #2550 (the FlexLib spot background_color fix), with diagnoses that landed independently and correctly - @s53zo — MIDI VFO jog-wheel stabilization across the FlexControl path
- @M7HNF-Ian — SpotHub auto-reconnect after Wi-Fi drops, TCI lifetime fix, HiDPI gauge clipping fixes, Spot Lines toggle
- @NF0T — RADE in the official Windows installer...
AetherSDR v0.9.8 — Aetherial Audio Channel Strip RX + community-driven reliability sweep
Aetherial Audio Channel Strip RX + community-driven reliability sweep
A focused 24-hour sweep around the Aetherial Audio Channel Strip's RX
side and a long list of community-contributed fixes. The RX panel
gains DESS, full final-output / waveform stages, ADSP cluster bypass,
and parity with the TX layout. Hamlib NET-rigctl interoperability is
unblocked end-to-end — Not1MM, MacLoggerDX, fldigi, and any other
standard rigctld client can now drive AetherSDR's frequency, mode,
filter passband, RF power, PTT, and CW. The release also clears two
silent Windows footguns (UI Scale on Windows was completely broken;
spot clients crashed on disconnect cascade), and lands a CW-knob UX
upgrade plus a dialog chrome refit on the AetherDSP Settings window.
Big thanks to @chibondking (CJ Johnson — editable CW value fields,
cwDelay optimistic-update, UI Scale Windows + reset-to-100% fix, macOS
relaunch via open -n, PGXL OPERATE/STANDBY sync), @jensenpat
(spot client thread affinity Windows crash, hardware-PTT mic_selection
fix, filter width indicator, mode-correct widen/narrow shortcuts,
Not1MM rigctld interop), @rfoust (Robbie Foust — status bar
separator dot fix, audio shutdown null-guards), and @s53zo (MIDI
VFO jog-wheel stabilization). Also crediting @ct1drb for the
original orphaned rigctld pipe-separator fix that #2438 cherry-picked.
New features
Aetherial Audio Channel Strip — RX side (#2425)
- The Channel Strip now has a fully-built RX path alongside the TX
path. RX side mirrors the TX layout: AGC-G (formerly AGC-T), EQ,
De-Esser, Compressor, Tube/Saturator, PUDU, Final Output, and
Waveform tiles, all wired through the inline RX DSP pipeline in
AudioEngine. - The CHAIN status row's ADSP tile is now a Stage-style toggle that
bypasses the entire client-side NR cluster (NR2 / NR4 / MNR / DFNR
/ RN2 / BNR) with a single click; an in-memory snapshot restores
the prior NR state on un-bypass. - ChannelStripPresets schema gains an optional
rxblock so saved
profiles capture both TX and RX state. Old preset files without
the block leave RX state untouched (forward-compatible). - New StripRxOutputPanel with peak/RMS meter, MUTE, BOOST. Strip-side
Waveform panel becomes side-aware so the same widget renders the
TX or RX scope tap based on aSide::Tx | Side::Rxflag.
Editable CW Delay / Speed / Sidetone / Pitch fields (#2429, chibondking)
- The four CW value labels in the PhoneCwApplet are now
QLineEdit
widgets. Click any value and type a number directly — SmartSDR
parity.QIntValidatorclamps to the valid range,editingFinished
drives the slider so the existing slider→model command path fires
unchanged.hasFocus()guards on the slider valueChanged path AND
onsyncCwFromModelkeep mid-edit input from being clobbered by
radio echoes.
Hamlib NET-rigctl / Not1MM interoperability (#2438, jensenpat, closes #2048 #2108)
- Pipe separator (
|) — rigctld's wire convention. AetherSDR only
recognised;, so every pipe-prefixed command returnedRPRT -4.
Cherry-picks the orphaned PR #2051 fix from @ct1drb with full
attribution. - Multi-line bare
bsend_morse — Hamlib spec allows the morse text
on the next line. Per-connectionm_pendingMorseLineflag arms the
next handleLine call to consume morse text verbatim. Required by
Not1MM contest CW. - RFPOWER
get_level/set_level— was returningRPRT -11(silent
failure). Wires through toTransmitModel::setRfPower / rfPower()
with proper 0.0–1.0 ratio ↔ 0–100 percent conversion.dump_state
set_level mask was hardcoded to KEYSPD only — now correctly reflects
the full RFPOWER + KEYSPD set. - Per-mode filter passband placement —
cmdSetModewas applying the
USB convention to every non-LSB mode, soM CW 250produced a
155 Hz filter centered at 172 Hz instead of a 250 Hz filter centered
on 0. Mirrors the canonical mode→filter-edge mapping from
VfoWidget::applyFilterPreset.
AetherDSP Settings dialog refit + VFO DSP launchers
- AetherDSP Settings dialog gets the standard frameless 18 px gradient
title bar (matching NetworkDiagnosticsDialog and AetherialAudioStrip)
with grip glyph, min/max/close trio, drag-to-move, double-click to
maximize, 8-axis resize. - New
setDialogMode(true)on AetherDspWidget bumps every inline
font-size to 13 px to match the VFO DSP toggle row, applies a
parallel 60×24 / 70×26 toggle-button geometry. Applet path leaves
this off. - Per-slice VFO DSP grid gains an
ADSPbutton (opens AetherDSP
Settings — same entry point as the Settings menu) and an
AetherVoicebutton (toggles the Aetherial Audio Channel Strip).
Bug fixes
Spot client thread affinity Windows crash (#2420, jensenpat, fixes #1929 #2418)
QTcpSocket/QUdpSocket/QWebSocketcreate an internal
QSocketNotifierwhose Win32 message-loop affinity binds to the
construction thread, not the QObject's current thread. Constructing
on main-thread thenmoveToThread()toSpotClientsleft the
notifier bound to main-thread; disconnect-cascade socket events
tripped a cross-threadsendEventassert. Each client now defers
socket creation to aninitialize()slot dispatched on the worker
thread viaQt::QueuedConnectionso internal notifiers bind there.
Audio callbacks during shutdown (#2413, rfoust)
- Quit-time crash on macOS where
WanConnection::~WanConnection
triggered a TLS disconnect cascade that emitted
radioTransmittingChanged(false)afterm_audiowas already null
but beforeQObject::~QObjecthad auto-disconnected the connected
lambdas. Surgical null guards on the three TX-state callbacks
(moxChanged,txAudioGateChanged,radioTransmittingChanged)
match the existingif (m_audio && ...)pattern used elsewhere in
the file.
Hardware PTT into radio with mic_selection=PC (#2431, jensenpat, fixes #2373 #2200)
- The interlock gate was forcing
setTransmitting(false)whenever
m_txRequestedwas false — even when the radio reported our handle
as TX owner. Hardware-keyed PTT (mic-line, ACC footswitch, RCA
TXREQ) had no bypass. PC mic audio with hardware PTT had likely
never worked through this branch. Parses the radio's interlock
source=field (SW / MIC / ACC / RCA / TUNE per FlexLib v4.2.18
ParsePTTSource) and addsMIC|ACC|RCAto the bypass list. SW
source still requiresm_txRequestedso SSB optimistic-off
responsiveness is preserved.
UI Scale not applied on Windows; reset to 100% silently ignored (#2432, chibondking)
- Two unrelated bugs in
main.cpp's pre-Qt settings read. (1) The
pre-Qt path was hardcoded to~/.config/AetherSDR/(Linux
convention); on Windows AppSettings actually writes to
%APPDATA%/AetherSDR/, so the file was never found and
QT_SCALE_FACTORnever set. Adds aQ_OS_WINbranch using
qEnvironmentVariable("APPDATA"). (2) Theif (pct != 100)guard
meant a child process inheritingQT_SCALE_FACTORfrom a scaled
parent kept using it after the user reset to 100%. Always-set fix
writes1.00so the inherited value is overridden.
macOS relaunch via open -n on UI Scale restart (#2434, chibondking)
applyUiScale()was callingQProcess::startDetachedon
applicationFilePath(), which on a.appbundle launches
Foo.app/Contents/MacOS/Foodirectly — bypassing Launch Services.
The relaunched instance shows as a separate dock entry, loses
proper activation policy, and on notarized/sandboxed builds can
fail entirely. Walks up to the bundle root and launches via
open -n <bundle>with--argspass-through.
MIDI jog-wheel VFO tuning stabilization (#2422, s53zo, fixes #2421)
- Three independent failure modes on touch-sensitive jog wheels (e.g.
Hercules DJControl Starlight). MIDI Learn could bind the touch
sensor instead of the movement CC. Saved bindings without the
relative flag interpreted unit-pulse 1/127 as absolute endpoints,
turning each detent into ~±63 steps. Tuning targets read
SliceModel::frequency()which lags behind in-flight tune commands,
making rapid spins jump backward. Fixed in three layered passes
with a 250 ms idle-timer-cleared in-flight tune target.
VFO filter width indicator showing 0.1 kHz too low (#2435, jensenpat, fixes #2197)
updateFilterLabel()computed rawfilterHigh - filterLow, which
for SSB/digital modes is ~100 Hz less than the named preset width
due to the intentional low-cut. Bug had been reported three times
(#794, #1225, this issue) — the structural fix promotes
RxApplet::formatFilterWidthto public static and has VfoWidget
call it directly. Single source of truth prevents the next swap.
Mode-correct filter widen/narrow shortcuts (#2436, jensenpat, fixes #2208)
- The
filter_widen/filter_narrowshortcuts (also bound to MIDI
global.filterWiden/global.filterNarrow) only adjusted the
upper edge by ±100 Hz. On LSB / CWL / DIGL / RTTY the upper edge is
fixed near 0, so "widen" actually collapsed the passband. New
RxApplet::stepFilterWidth(direction)walks the active mode's
preset list and routes throughapplyFilterPresetso all modes get
mode-correct edge geometry.
PGXL OPERATE/STANDBY button stuck on OPERATE (#2437, chibondking)
- AmpApplet button was only updated via the direct PGXL TCP path; if
that lagged, the button stayed on the old label. The click handler
readsm_operateBtn->text()to decide toggle direction, so a
stuck OPERATE button emittedoperate=0on click — sending another
standby command instead of returning to OPERATE. Wires
RadioModel::ampStateChanged(authoritative) to also call
AmpApplet::setState.
Status bar separator dots for unsupported optional sections (#2412, rfoust)
- TGXL and PGXL separator dots stayed visible even when the indicators
were hidden, leaving stray· ·clusters in the bottom status bar
on radios without those accessories....
AetherSDR v0.9.7 — CW keying overhaul + reliability sweep
CW keying overhaul + reliability sweep
A focused follow-up to v0.9.6 with two themes: a substantial CW operator
upgrade — keyboard and MIDI-mapped straight key + iambic paddles, full
break-in / QSK respect on both paths, netCW timing fixes, and Apollo-era
Quindar tones on PTT engage/disengage — and a reliability sweep covering
SpotHub auto-reconnect, a TCI crash on quit, the long-standing waterfall
TX trail, hardware PTT regressions, and DAX RX latency.
Big thanks to @jensenpat (CW keyboard / MIDI controls, compression
meter gating, Windows MSVC runtime), @M7HNF-Ian (Spot Lines,
HiDPI gauge clipping, TCI crash on quit, SpotHub auto-reconnect),
@filemakers (connect-to-last-radio opt-out checkbox), @NF0T
(RADE TX policy naming + tests), @chibondking (live voltage gauge),
plus issue reporters @vu2cpl (TCI crash with full call stack),
@luigiverdicchio1-prog (SpotHub failed-reconnect repro), @LU5DX
and @rnash2 (spectrum amplitude scale issue — under investigation).
New features
CW keyboard + MIDI controls (#2361, #2391, jensenpat)
- Three new shared shortcut + MIDI actions:
Trigger straight key,
Trigger CW Left Paddle,Trigger CW Right Paddle. Same action IDs
and display names for keyboard shortcuts and MIDI mappings (cwkey/
cwdit/cwdah);MidiSettingsmigrates legacy dotted IDs
(cw.key/cw.dit/cw.dah) on read. - Straight key is a true momentary control: keyboard press + MIDI gate-on
assert the netCW key path, release + gate-off release it. Paddles feed
the local iambic keyer when running so sidetone and on-air timing stay
aligned with WPM; falls back to a held-key path otherwise. - Both paths now honor the radio's
break_insetting fully — with
break_in=1(QSK), key edges trigger TX andbreak_in_delayholds
the relay between elements; withbreak_in=0, keys are queued and the
operator engages PTT manually (Space PTT, MOX, hardware PTT). The
previous auto-PTT envelope masked break-in OFF and killed QSK hang
time on release. - New clickable red TX status badge in the status bar acts as an
emergency transmit cancel — checks Multi-Flex ownership, clears all
local CW state, forces sidetone key-up, and sendscw key 0/
cw ptt 0/transmit tune 0/xmit 0. - Slider focus lease no longer blocks momentary CW shortcuts or Space
PTT — clicking the CW delay slider previously froze J/K/L paddle
keying and Space PTT for 2+ seconds while the lease's arrow-key
capture timer expired. - Pre-existing typo fix: J tile in the on-screen keyboard widget was
bound toQt::Key_I, so binding a shortcut to J in the editor
selected I.
Quindar tones — Apollo-era K/BK on PTT (#2334, fixes #2262)
- Optional 2525 Hz "K" / 2475 Hz "BK" tones on PTT engage / disengage,
modeled after Apollo CapCom audio. Lock-free DSP module wired between
PC mic gain and the final TX limiter so tones are mixed into the
outgoing audio. Local sidetone via a dedicated 48 kHzQAudioSink
(mutually exclusive with CW mode at the mode level — Quindar and CW
share the same sidetone bus). - Added as the QUIN chip in the Final Output Stage panel of the
Aetherial Audio Channel Strip with a frameless editor dialog
(test-tone buttons + Done in the same row as the title bar). - Disabled by default; opt-in via the chip toggle.
netCW keying fix + trace logging (#2336, fixes a long-tail of issues)
- Fixes netCW timing for both straight-key and iambic CW. Adds detailed
aether.cwtrace category logging across MIDI / keyboard input,
netCW UDP scheduling, VITA stream/index details, and TCP fallback /
backstop paths so future timing regressions are diagnosable from logs.
Spot Lines toggle in SpotHub (#2349, M7HNF-Ian)
- New "Spot Lines" toggle in the SpotHub Display settings draws vertical
lines from the spectrum up to each spot label. Off during contests to
reduce visual clutter; on for casual ops to keep label-to-frequency
mapping legible at a glance.
Network Diagnostics live logs tab (#2333)
- New tab in the Network Diagnostics dialog with live tail of the same
logs the diagnostics report references, scoped to the diagnostic
categories (aether.connection,aether.dxcluster,aether.cw,
etc.). Lets users diff what they're seeing against what was logged
without leaving the dialog.
Connect-to-last-radio opt-out checkbox (#2390, filemakers)
- New "Connect to last radio on start up" checkbox on the connection
dialog; defaults to ON so existing users keep current behavior. When
unchecked, AetherSDR no longer auto-connects on startup, on
broadcast-discovery, or on routed-radio probe — useful for operators
who want to pick a radio manually each session. The dialog
auto-launches at startup when opt-out is enabled so the user has a
clear path to pick a radio.
Bug fixes
SpotHub auto-reconnect after failed connection attempt (#2394, M7HNF-Ian, fixes #2380)
- SpotHub (DX cluster / RBN) didn't automatically reconnect after a
Wi-Fi drop or any failed connection attempt — Qt'sQAbstractSocket
only emitsdisconnected()on Connected → Unconnected transitions,
so when the socket failed duringConnectingState(host blocked,
refused, or timed out), the reconnect timer was never armed. Extracts
ascheduleReconnect()helper called from all three failure paths
(live drop, socket error, connect timeout) with guards against
double-scheduling. A per-call epoch counter prevents stale timeouts
from a previous attempt aborting a later successful one. Backoff
sequence unchanged: 5 s → 10 s → 20 s → 40 s → 60 s.
TCI crash on quit when TciServer outlives RadioModel (#2386, M7HNF-Ian, fixes #2385)
TciServerwas constructed as aQObjectchild ofMainWindow, so
Qt deleted it during~QWidget::deleteChildren()— which runs after
MainWindow's value members (includingm_radioModel) have already
destructed.~TciServer()→stop()→releaseDaxForTci()then
dereferenced freed memory. EXC_BAD_ACCESS @0x38, 100% reproducible
on quit when a radio was connected. Reported by VU2CPL with full call
stack. Fixed by explicitly tearing downm_tciServerin
~MainWindow()after the audio thread is stopped but while
m_radioModelis still alive, plus a belt-and-braces
QPointer<RadioModel>so the existing null guards in
releaseDaxForTci()catch any future regression automatically.
Waterfall unfreezes on radio interlock state, not MOX edge (#2368, fixes #1927)
- Waterfall freeze/unfreeze previously gated on the local MOX edge,
which fired the instant the user released PTT — the radio kept
streaming TX-contaminated tiles for theUNKEY_REQUESTEDwindow, and
those rows then took 10–23 s to scroll off the visible waterfall.
Now driven byRadioModel::radioTransmittingChanged(interlock
state=TRANSMITTING), so the freeze is held until the radio
actually leaves TX. Multi-Flex bonus: any client TXing now triggers
the freeze, not just our client.
Honor cw break_in for keyboard CW keying (#2391)
RadioModel::sendCwKeyand the iambic keyer'sonPaddleEventboth
unconditionally wrapped each key/squeeze in acw ptt 1...cw ptt 0
envelope. Made break-in OFF a no-op (auto-PTT forced TX anyway) and
killed the radio's break_in_delay hang time with break-in ON
(force-dropped PTT after every element). Stripped the auto-PTT in
both paths so the radio's break-in setting decides TX behavior,
matching SmartSDR semantics.
Spot list double-click switches mode (#2372, fixes #2298)
- Double-clicking a spot in the Spot List now switches the radio's
mode along with the frequency. Previously only the frequency moved,
leaving the user in the wrong mode for the spotted signal.
Spot trigger includes pan= for external CAT clients (#2369, fixes #2366)
- The spot click protocol now includes
pan=<panId>so external CAT
clients (N1MM Logger, etc.) consuming AetherSDR's spot triggers can
route the click to the correct panadapter in multi-pan setups.
Compression meter gates on radio TX state (#2363, jensenpat)
- The TX compression meter now displays only while the radio reports
state=TRANSMITTING. Previously it could read live during RX from
stale interlock state, confusing operators about what compression
was actually applied to their signal.
Voltage gauge label shows live radio voltage (#2362, chibondking)
- The voltage gauge label now reflects the live voltage value reported
by the radio instead of the static "VOLTS" placeholder.
Minimal mode revert on macOS when entered while maximized (#2367, fixes #2365)
- Entering minimal mode while the window was already maximized on
macOS would revert to a non-minimal layout immediately on toggle.
Layout / state ordering corrected so the entry sticks regardless of
the prior maximized state.
MidiControlManager: drop dead paramAction signal (#2370)
- Cleanup follow-up after #2336 introduced
paramActionTrace—
paramActionwas still emitted but had zero connectors. Removed
the orphan signal + matching declaration.
Infrastructure
DAX RX native pw_stream source on Linux (#2312, fixes #1008)
- DAX RX latency on Linux drops from ~400 ms → ~200 ms via a native
PipeWirepw_streamsource path, replacing the previous PulseAudio
client. Brings DAX RX latency in line with macOS / Windows.
RADE TX policy naming + tests (#2353, NF0T, fixes #2343)
- Renames the RADE TX policy enum to align with the issue tracking
language (HostedDaxBridgeetc.) and adds unit tests covering each
(reason, platform, mode) → (allowed, note)decision row.
HiDPI gauge clipping (#2346, M7HNF-Ian)
- HGauge tick labels and TxApplet value labels were clipping on HiDPI
displays. Layout / paint regions updated to honor device-pixel ratio.
Windows portable ZIP includes MSVC runtime (#2364, jensenpat)
- Windows portable ZIP now bun...
v0.9.6 — Aetherial Audio Channel Strip + AetherSweep Phase 2
Aetherial Audio Channel Strip + AetherSweep Phase 2
Headline additions: a unified Aetherial Audio Channel Strip that brings
every TX DSP stage (gate, EQ, compressor, de-esser, tube, AetherVoice,
reverb, and a brand-new Final Output Stage with brickwall limiter) into a
single editable window with a savable preset library — and AetherSweep
Phase 2, a polish pass on the in-panadapter SWR analyzer with log scale,
threshold-band shading, interpolated bandwidth at SWR ≤ 1.5 / 2.0, a
resonance caret, and band-change-aware auto-stop. Network Diagnostics
gained trend graphs and per-series gutter hints. RADE finally ships in
the official Windows installer.
Big thanks to @jensenpat (oscillator reference fix, AetherSweep
Phase 2, Connect-by-IP recents, minimal mode polish, Windows installer
packaging), @NF0T (RADE on Windows CI/installer, RADE mic meter
fix), @rfoust (Network Diagnostics trend graphs), and
@AetherClaude (stderr non-draining-pipe deadlock) for landing the
bulk of this release.
New features
Aetherial Audio Channel Strip (#2307, #2326)
- New unified TX DSP window covering every stage in the chain: gate, EQ,
compressor, de-esser, tube, AetherVoice (the exciter formerly known as
PooDoo), Freeverb, plus a brand-new Final Output Stage with brickwall
limiter, output trim, DC block, and a 1 kHz test tone. - Savable preset library at
~/.config/AetherSDR/ChannelStrip.settings
(separate fromAetherSDR.settings). Captures every TX DSP knob, the
user's chain order, and final-limiter parameters. Save / Delete /
Export Preset / Export Library buttons in the strip's preset row. - Master/Aux BYPASS button stays in lock-step between the docked Chain
applet and the strip via a shared engine-level snapshot — flipping it
in either place updates both. - Two new 4th-row panels: Aetherial Waveform — TX (1–20 s scope window
with SCOPE/ENVELOPE/HISTORY modes) and Final Output Stage (peak-hold
meter with GR overlay + draggable amber ceiling triangle, mouse-wheel
±0.1 dB). - Logo / title rebrand: PooDoo™ exciter → AetherVoice™ "Aetherial
Voice Processor" with Body / Clarity emphasis controls. Docked tile
(PUDU) renamed toEVOon the chain widget; container button
renamedVUDU. - Double-click any TX chain tile launches the Channel Strip — replaces
the legacy easter-egg launch nub on the Chain applet and the
per-stage TX floating editors (ClientDeEssEditor,
ClientReverbEditor, etc.). - FreeVerb tile in the docked applet panel now shows the same
decay-tail viz as the Channel Strip's reverb panel, signal-driven by
a newAudioEngine::clientReverbStateChangedsignal (no polling).
AetherSweep Phase 2 (#2320, jensenpat)
- Logarithmic SWR scale for cleaner low-ratio detail; threshold-band
shading for SWR 1.0–1.5 (green), 1.5–2.0 (amber), and >2.0 (red). - Resonance caret + dot at the best measured SWR point; visual
start/end notches mark sweep endpoints. - Interpolated bandwidth brackets at SWR ≤ 1.5 and ≤ 2.0, with a
concise BW readout in the corner label. - Resonant frequency display trimmed to kHz precision; corner readout
switched from "latest sample" to best SWR + resonance frequency. - Cleared sweep plots when the swept TX slice changes bands; if a band
change happens while a sweep is running, the sweep stops and clears
without restoring the old freq/pan range so cleanup doesn't fight
the user's new band.
Network Diagnostics trend graphs (#2309, rfoust; #2316)
- Per-metric trend plots with Timeframe selector (1 min / 5 min /
15 min / 1 h / 1 d / 1 w). - Logarithmic Y-axis on the Rates tab — 0 / 1 / 10 / 100 / 1k kbps
decades all visible at once instead of being squashed at the
baseline. - Per-series last-sample hints in the left gutter — small
color-coded values that always show the latest reading for each
visible stream, with a 6 px-tall solid centerline alpha gradient
to keep the labels legible against the trace. - Frameless chrome with draggable title bar + 8-axis resize matching
the rest of AetherSDR's floating windows.
RADE in the official Windows installer (#2324, NF0T)
ENABLE_RADE=ONfor both the Windows CI job and the official
installer workflow. Vendored RADE-prepared Opus + neural-net
weights are statically linked, so no new DLLs ship —AetherSDR.exe
grows ~8–12 MB to match the AppImage.- New
Build Opus (RADE dependency)CI step provides clean failure
attribution and matches the AppImage workflow's pattern. Closes
reports of "RADE absent from Windows installer".
Connect by IP recents dropdown (#2296, jensenpat)
- Connect-by-IP field is now a combo box pre-populated with the last
five addresses (stored asRecentDirectIpAddresses). Successful
connect promotes the address to the top of the list.
Black slider auto-offset (#2328)
- Spectrum Overlay menu's Black slider now drives a noise-floor target
offset while AUTO is engaged: 50 = at the noise floor (today's
behaviour); lower = darker (push threshold above the floor); higher
= lighter. Manual mode keeps existing semantics. Both stored
values persist independently so toggling AUTO swaps the slider
position without losing either preference.
Minimal mode polish (#2290, jensenpat; #2299)
- Title bar drag now reaches the gutter and other previously-dead
zones via sub-pixel hit testing. Exit paths from minimal mode
consolidated; layout stops fighting on toggle.
Aetherial Noise Reduction docked applet (#2297)
- Client-side NR controls live in their own docked applet under
PooDoo Audio (RX); the redundant DSP sub-panel was removed from
the Spectrum Overlay menu for a cleaner DSP surface.
Bug fixes
Oscillator reference status no longer goes stale (#2329, jensenpat)
- New
RadioModel::oscillatorChanged()signal drives the status-bar
reference label and Radio Setup combo immediately from oscillator
state, instead of relying on event ordering with GPS status.
Eliminates the case where the status bar got stuck on the previous
reference if a GPS update never arrived after the oscillator
transition. - Radio Setup dropdown preserves currently-selected/actual options
during presence transitions, so transient flag blips no longer
drop the active option from the combo. RenamedExternal→
External 10 MHzto match the FlexLib API description. - Status-bar tooltips now show desired setting, actual source, lock
state, and GPS/external details.
RADE mic level meter + gain slider (#2292, NF0T)
- The RADE TX mic level meter now updates while the modem is active,
and the gain slider is enabled instead of stuck at zero. Fixes
"no apparent way to set RADE mic level" reports.
Stderr non-draining pipe deadlock (#2300, AetherClaude)
- When stdout/stderr was redirected to a pipe with no reader, the
audio worker thread could deadlock writing log lines. Replaced
blocking writes with a non-blocking path that drops on the floor
rather than stalling the thread.
Windows installer runtime packaging (#2303, jensenpat)
- Tightened Windows runtime-DLL bundling for a smaller installer and
fewer "missing DLL" reports on first launch.
Infrastructure
v0.9.5.1 release-notes expansion (#2288, #2289)
- The CHANGELOG entry for v0.9.5.1 was expanded post-release to
cover all post-v0.9.5 fixes (#2113 reachability sweep, the four
rfoust polish PRs, NR2 audio-thread + Qt-log hotfixes) with full
contributor shoutouts.
v0.9.5.1 — Stability & polish hotfix sweep
Stability & polish hotfix sweep
A focused follow-up release that lands the TCI TX policy hotfix plus six
post-v0.9.5 fixes already in main: SmartLink WAN reconnect after radio
drops, sequenced WAN disconnect teardown, RX slice-tab reset between
radios with different slice counts, macOS panadapter pop-out live
updates and dock-splitter layout, NR2 wisdom-generation safety on the
audio thread, and a Qt log-handler serialization fix that resolves a
macOS tune-time crash.
Big thanks to @rfoust (four SmartLink / disconnect / macOS polish
fixes) and @jensenpat (NR2 audio-thread safety + Qt log
serialization) for landing the bulk of this release.
Bug fixes
TCI TX silent on Windows / Linux non-PipeWire (#2276)
evaluateDaxTxPolicy()now always allowsDaxTxRequestReason::TciTxAudio
regardless of platform / hosted-DAX availability. TCI receives audio
over WebSocket and feeds it into a dedicateddax_txstream that's
independent of SmartSDR DAX2 (which owns the Windows DAX audio
devices, not the radio'sdax_txstream slot — multiple GUI clients
can each register their own).- Test assertions in
tests/radio_status_ownership_test.cppflipped to
match the corrected policy and a new Linux-non-PipeWire test case
added.
SmartLink reconnect after WAN drop (#2282, rfoust)
MainWindownow owns a WAN reconnect timer that re-requests a
SmartLink radio connection using the last selected WAN radio when
RadioModelreports an unexpected WAN disconnect, instead of
leaving the app stuck on the "Radio disconnected — waiting for
reconnect" popup.SmartLinkClient::reconnect()refreshes Auth0 credentials via the
saved refresh token before reconnecting, avoiding reuse of an
expiredid_token. Auth-refresh failure stops the retry loop and
shows a sign-in-required status instead of retrying forever.RadioModel::forceDisconnect()now handles WAN connections so
missed pings transition the app to disconnected/reconnecting
promptly. Ping watchdog logs and forces disconnect once per outage
rather than every second.PanadapterStack::prepareShutdown()releases QRhi GPU resources
before main-window teardown to avoid the macOS Metal teardown crash
that could fire after a stale-state Disconnect.
SmartLink disconnect teardown (#2278, rfoust)
- WAN disconnect previously closed the WAN socket after disconnecting
RadioModel's signals and nulledm_wanConndirectly, skipping
RadioModel::onDisconnected()cleanup entirely. Panadapters,
slices, meters, and streams stayed alive in the model after the user
clicked Disconnect. - Now runs the normal model teardown path on intentional WAN
disconnect, so WAN sessions emitconnectionStateChanged(false)and
clear model state the same way LAN disconnects do.
Reset RX slice tabs on disconnect between radios with different slice counts (#2254, rfoust)
RxApplet::clearSliceButtons()tears down generated slice tab buttons
and restores the static slice badge on disconnect. Stale A–H buttons
no longer linger after switching from a high-slice radio to a
smaller one.MainWindow'sinfoChangedinitializer is now per-connection rather
than one-shot, so each radio rebuilds its slice row from its own
maxSlices. Slice button click connections are guarded against
duplicate signal handlers across reconnects.
Qt log handler serialization fixes macOS tune-time crash (#2284, jensenpat)
- The global
qInstallMessageHandlercallback wrote through a single
QFile*without synchronization, and concurrentqCInfo/qDebug
output from main + worker threads corrupted Qt's internal file
write-buffer state. The tune-policy diagnostic line happened to be
the log call that exposed the corruption — the failing object was
the logging sink, not the Flex tune command path. - Now serializes the handler with an intentionally leaked mutex
(mirroring the existing shutdown-safe treatment of the redaction
regexes) and replaces per-messageQTextStreamwrapping with a
direct UTF-8QFile::write()/flush()path. No change to radio
command ordering or panadapter policy.
macOS panadapter pop-out refresh + multi-pan dock layout (#2280, rfoust)
- Detached panadapter windows on macOS no longer show a static/stale
spectrum image. Cross-window reparenting now resets the native
QRhi/Metal surface and re-requests pan dimensions from the radio
after every float/dock cycle. - Saved floating-window state is no longer restored after later
user-added pans, so adding a second panadapter does not spawn an
unwanted blank floating window. rebuildDockedSplitter()keeps the main-window splitter compact
when multiple pans float/dock — no more empty placeholder slots.
NR2 wisdom generation no longer freezes the audio thread (#2275, jensenpat)
AudioEngine::needsWisdomGeneration()previously only checked
whetheraethersdr_fftw_wisdomexisted. If the file was stale or
incompatible (e.g.fftw-3.3.10header on a build that uses FFTW
3.3.11),setNr2Enabled()ran full FFTW wisdom generation on the
audio worker thread, blocking RX audio and the WAVE scope for
several minutes.- Adds
SpectralNR::loadWisdom()for import-only validation, makes
needsWisdomGeneration()return true when the file exists but
cannot be imported, and routes generation through the existing
background progress dialog instead of the audio thread. If wisdom
import fails at enable time, NR2 falls back to runtime
FFTW_MEASUREplans rather than hanging audio.
v0.9.4 — AetherSweep, ShackSwitch, and multi-client startup hardening
[v0.9.4] — 2026-05-01
AetherSweep, ShackSwitch, and multi-client startup hardening
A heavy community-contribution release. Headline feature is AetherSweep
(jensenpat) — an in-panadapter SWR sweep analyzer that walks the current TX
band, plots SWR live on the spectrum surface, and handles TGXL bypass +
PGXL checks. ShackSwitch support (nigelfenton) lands as a
new Peripherals tab + dedicated applet, integrating any builder's open-source
Arduino antenna switch over the Antenna Genius protocol.
A trio of substantial reliability fixes from jensenpat addresses long-standing
multi-client startup issues — when SmartSDR or DAX is already connected,
AetherSDR's panadapter creation, slice ownership, and PC audio stream
acquisition now all hold up under the racey status interleavings the
ShackSwitch and DAX users were hitting. Plus a focused mix of platform
fixes: macOS DMG dark-theme on pop-out windows (Chaosuk97), Windows
without-Qt6::SerialPort build (NF0T), NRL gating correctness on 6000-series
radios.
Features
AetherSweep — in-panadapter SWR analyzer (#2202, #2220, #2230, jensenpat)
- New Start/Clear Sweep buttons under the ANT slice menu, plus a 1-10 W
sweep-power slider with cross-panel sync. Persisted as
SwrSweepPowerWattsand defaults to 1 W. - Walks the current TX band stepping a tune carrier in 20 kHz increments
with edge guards, sampling fresh SWR + forward-power meter data per step,
and overlays the curve on the panadapter directly under the slice flag. - Per-band-edge guard, max-260-points cap, and 60 m channelized-band
refusal. Refuses to start when split is active, when transmitting,
when the band is wider than the radio's max pan width, or when a PGXL
amplifier is in OPERATE mode (forces user to STANDBY first). ⚠️ Third-party amplifiers are not auto-detected. AetherSweep
only checks for Power Genius XL status — it has no way
to talk to ACOM, SPE, Elecraft KPA, OM Power, or other linear amps.
If you have a non-PGXL amplifier, manually place it in BYPASS or
STANDBY before starting an SWR sweep. The sweep will run a tune
carrier through whatever path the radio sees, and a non-bypassed
external linear will amplify that carrier into your antenna.- Full TGXL handling: snapshots OPERATE/BYPASS state, places TGXL into
BYPASS to read raw antenna SWR, restores original state on completion
or abort. Reads radio-side SWR while TGXL is bypassed (TGXL stops
emitting RL meter packets in bypass — #2229). - 5-phase state machine with explicit timeouts: WaitingForTgxlBypass,
TgxlBypassSettle, Sweeping, StoppingTune, RestoringTgxl. - Esc to abort. Inputs locked during sweep so the user can't accidentally
retune mid-pass. Disconnect mid-sweep cleanly stops the carrier and
releases TGXL. - Optimistic
setTunePower()update so the sweep's chosen power lands
immediately rather than racing the radio's status echo. - Sweep result label shows source —
RADIOfor direct measurement,
TGXL BYPASSfor tuner-bypassed measurement.
ShackSwitch antenna switch integration (#2214, #2227, nigelfenton)
- New Peripherals tab in Radio Setup with auto-discovery and manual-IP
connect for ShackSwitch devices via the Antenna Genius (AG) UDP/TCP
protocol on port 9007. - New ShackSwitchApplet — compact panel with up to 8 labelled
antenna-port buttons, click-to-switch, active-port highlight. SO2R
dual-radio mode shows Input A / Input B side-by-side with conflict
detection. Single-radio mode (4-port R4 hardware) hides Input B
automatically. - Dummy-load / deselect (clicking the active port deselects it) and
per-port labels driven by the device's own configuration. - Integration is invisible to users without ShackSwitch hardware —
detected by thename="ShackSwitch"field in the AG broadcast beacon. - Web UI launcher button opens the device's local web interface.
- Reference hardware: ShackSwitch v2.0 (Arduino Uno Q, SO2R, 8-port) and
ShackSwitch R4 (Arduino Uno R4 WiFi, single-radio, 4-port).
Bug fixes
Multi-client startup panadapter creation (#2222, jensenpat)
- AetherSDR's startup pan creation now holds up cleanly when SmartSDR,
DAX, or another GUI/audio client is already connected. The radio
replays status for all current pans/slices/streams on connect; without
this fix, AetherSDR could correctly reject other clients' objects but
then fail to instantiate its ownPanadapterModelif ownership status
arrived out of order. - Adds
display panafall create x=100 y=100(FlexLib v4.2.18 syntax)
with capability-based fallback to legacypanadapter create. - New
ensureOwnedPanadapter()factory; deferred-status replay queue
fordisplay panframes that arrive withoutclient_handle; waterfall
ordering recovery viapanadapter=...parent ID lookup. - Routes failure cases through the existing
panadapterLimitReached/
sliceCreateFailedstatus-bar signals so radio resource exhaustion
is visible instead of looking like a startup hang.
PC audio remote stream ownership (#2226, jensenpat)
- Fixes PC Audio failure when SmartSDR / DAX is already running — the
sharedremote_audio_rxpipe was being silently removed because
AetherSDR was parsing thestream createresponse body as decimal
instead of hex."4000009"(no0xprefix) was becoming
0x003D0F09instead of0x04000009, so the create-response stream
didn't match the status-reported stream and AetherSDR removed the
real one. - Extracts a new
RadioStatusOwnershiphelper (header-only, fully
unit-tested) that handles ownership decisions for both panadapters
and remote audio streams — defer when noclient_handle, claim
when ours, ignore when another client's. - Stream-acquisition state machine now tracks create-pending,
remove-requested, and adopted-from-status separately so toggling
PC Audio doesn't race the create response. - Adds
radio_status_ownership_testwith 25 assertions covering all
the ownership decisions and the headline parse bug. - Fixes #2037, #1418, #1473.
TGXL meter goes silent during bypass (#2229, #2230)
- AetherSweep aborted with "no fresh TGXL SWR meter data" whenever the
TGXL was in OPERATE before sweep start. The TGXL stops emittingRL
(return-loss) meter packets while in BYPASS — bypass relays are
passive wire-through, no measurement engine. - Switches the meter source to RADIO while the TGXL is bypassed; the
radio's own SWR coupler measures the same physical signal through
the bypassed relays. UI label still showsTGXL BYPASSsince
that's what describes the configuration.
Pop-out applet panel white background on macOS (#2190, Chaosuk97)
- macOS DMG builds rendered floating windows with a white background
even though the dark-theme stylesheet was applied — the CI-built
libqcocoa.dylibenforcedQt::WA_StyledBackgroundmore strictly
than Homebrew's Qt 6.11.0 build. - Adds
setAttribute(Qt::WA_StyledBackground, true)on all three
floating-window classes (FloatingContainerWindow,PanFloatingWindow,
MainWindow::floatAppletPanel). Cross-platform safe: the attribute
is harmless on Linux/Windows where it was a no-op, and now the
pop-out applet panel correctly themed on every platform (was
defaulting to system theme on Linux/Windows too — latent bug fixed
as a side effect).
Windows build without Qt6::SerialPort (#2195, NF0T)
- Compile error introduced by #2147: the
<QElapsedTimer>include was
guarded by#ifdef HAVE_SERIALPORTwhilem_debounceTimeris declared
under#if defined(HAVE_SERIALPORT) || defined(Q_OS_WIN). Mismatch
broke the Windows-without-SerialPort build configuration. Widens the
include guard to match.
NRL DSP filter visible on 6000-series radios (#2219)
- Fixes regression from #2184 where NRL was incorrectly grouped with
the 8000-series-only firmware DSP filters (NRS, RNN, NRF). NRL is
available on 6000-series too — only NRS/RNN/NRF require BigBend /
DragonFire hardware. Fixes #2198.
Acknowledgements
Massive contributor batch this cycle:
- jensenpat — AetherSweep (3 PRs: feature + power-control polish + TGXL
meter fix), multi-client panadapter startup, PC audio ownership. This
release wouldn't be the leap it is without his work. - nigelfenton — ShackSwitch integration (3 PRs across the cycle:
protocol fix, full integration, callsign-detection cleanup). - NF0T — Windows build fix.
- Chaosuk97 — macOS DMG dark-theme fix.