Waterfall blanks/flickers during TX only when AetherSDR is the active window
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- cpp, macos
- Domain
- desktop, performance
Research direction
Start by tracing PanadapterStream::processPacket() for PCC 0x8004, SpectrumWidget::updateWaterfallRow(), and SpectrumWidget::paintEvent(), comparing packet and frame behavior during focused and unfocused TX. Then inspect AudioEngine and QAudioSource lifecycle alongside the waterfall render timer. Done means the waterfall remains continuous during WSJT-X TX, with no dropped frames and no unnecessary QAudioSource activity in DIGI/DAX mode.
Written by the indexing model from the issue text.
Description
Request preparation
- I used an AI assistant to help structure this request
- I checked for existing issues covering the same feature
What would you like?
https://github.com/user-attachments/assets/aba34e71-d7d9-44ad-8909-244d14a60516
Waterfall blanks/flickers during TX only when AetherSDR is the active window
Labels: bug, spectrum, audio
What happened
During a WSJT-X transmission sequence (FT8/FT4), the waterfall in
SpectrumWidget flickers on and off — alternating between scrolling
normally and going fully blank — but only while the AetherSDR window
is in the foreground. When WSJT-X is the active window during the
same TX phase, the AetherSDR waterfall continues scrolling without
interruption. After TX ends and the radio returns to RX, the waterfall
recovers immediately regardless of which window is active.
Videos attached by reporter demonstrating both cases.
What I expected
The waterfall should scroll continuously throughout the full TX/RX
cycle regardless of which application window has focus. SmartSDR on
Windows scrolls the waterfall uninterrupted during TX.
Steps to reproduce
- Set up WSJT-X with DAX or VOX PTT targeting the FlexRadio.
- Connect AetherSDR to the same radio. Confirm waterfall is scrolling
normally in RX. - Click the AetherSDR window so it is the active foreground window.
- Wait for WSJT-X to begin a TX sequence (or trigger MOX manually).
- Observe: waterfall alternates between scrolling and blanking
during the TX phase. - Click the WSJT-X window so AetherSDR loses focus.
- Trigger another TX sequence.
- Observe: AetherSDR waterfall scrolls normally — bug does not
occur while AetherSDR is in the background.
Environment
- OS: MacOS 26.3.1 (a) (25D771280a)
- Radio: FlexRadio 6400
- Firmware: v1.4.5.39794
- AetherSDR: v0.9.1
- External software: WSJT-X 3.1.0 improved plus, using DAX or VOX PTT
Root cause analysis
The window-focus correlation is the critical clue. When AetherSDR is
the active window, Qt delivers keyboard events, mouse events, and
possibly repaint requests to it. Three plausible mechanisms:
Hypothesis A — QAudioSource mic capture activated by window focus (most likely)
When AetherSDR becomes the foreground window, Qt may activate or
prioritize the QAudioSource microphone capture pipeline
(AudioEngine::onTxAudioReady()). If QAudioSource is running in the
same thread as the VITA-49 UDP socket (PanadapterStream), or if its
callback fires at a rate that saturates the event loop, waterfall tile
processing (updateWaterfallRow()) can be delayed or dropped entirely.
Check: Is QAudioSource started unconditionally on connect, or only
when TX is active? If it is always running and polling, switching window
focus may push it into an active-read state.
Hypothesis B — Main thread event loop saturated by focus/repaint events
QEvent::WindowActivate and QEvent::ApplicationActivated cause Qt to
re-render the entire widget hierarchy. If SpectrumWidget::paintEvent()
is slow (large waterfall pixmap blit), and focus changes re-trigger
paints at high rate during TX, the UDP receive callbacks in
PanadapterStream may be starved while the main thread is busy painting.
Check: Profile paintEvent() duration. Add a frame-drop counter to
updateWaterfallRow() — if drops spike when AetherSDR is focused during
TX, this is the mechanism.
Hypothesis C — TX audio thread competing with waterfall render timer
WSJT-X drives PTT via CAT/rigctld or VOX. When AetherSDR is focused,
user input (keyboard, mouse) may trigger QAudioSource to start reading
mic audio for TX even in DIGI/DAX mode. The TX audio thread and the
waterfall render timer (QTimer firing update() on SpectrumWidget)
may be competing for the Qt event loop.
Suggested fix
Step 1 — Confirm packet arrival rate:
Add a temporary qDebug() counter to
PanadapterStream::processPacket() for PCC 0x8004. Log packets/second
before and during TX, with and without AetherSDR focused. If the rate
drops during TX+focus, the issue is upstream of SpectrumWidget.
Step 2 — Check QAudioSource lifecycle:
In AudioEngine, verify that QAudioSource is only started when TX is
actually active (xmit 1 received), not on window focus or connection.
If it is always open, consider stopping it when TransmitModel reports
TX inactive.
Step 3 — Move waterfall rendering off the main thread:
If updateWaterfallRow() is called directly from the VITA-49 receive
thread via a direct signal connection, ensure the connection type is
Qt::QueuedConnection so waterfall updates are queued to the main
thread without blocking the UDP reader.
Step 4 — Suppress QAudioSource during DIGI/DAX mode:
When the active slice mode is DIGU/DIGL and DAX TX is in use, the
QAudioSource mic path should be fully idle. Confirm
AudioEngine does not open the mic device in this case.
Acceptance criteria
- Waterfall scrolls continuously throughout a WSJT-X TX phase with
AetherSDR as the foreground window - No dropped waterfall frames (PCC
0x8004) observable in debug
logging when AetherSDR is focused during TX -
QAudioSourceis confirmed not active during DIGI/DAX TX when
mic input is not needed - Behavior is identical whether AetherSDR or WSJT-X is the active
window - No regression in SSB/CW TX waterfall behavior
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aethersdr/AetherSDR
-
audio documentation good first issue maintainer-review
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
bug CW maintainer-review safety
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
docs(agents): family PRs must stay in the family tree (shared applet/pan/model edits stall review) Opendocumentation enhancement maintainer-review
Difficulty 1/5 1-3 hours Newbie friendliness 90/100
-
bug good first issue GUI maintainer-review priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 86/100
All issues in aethersdr/AetherSDR
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
Sensor initialization takes very long when `--initial-sim-time` is set to current UNIX timestamp Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
gazebosim/gz-sensors#662 · 1 comment ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
LadybirdBrowser/ladybird#12123 ·