Summary
On Windows (v26.6.3, current release), sending a CWX message produces an intermittent stutter — individual Morse elements are dropped or clipped roughly every few character groups, with audible clicks. Overall message timing stays correct (so #3202's drift-correction is working), but per-element edges slip under load.
This looks like the residual Windows case after #2980 (macOS stutter, fixed by #3202) and #2694 (Windows sidetone latency/distortion).
Environment
- AetherSDR v26.6.3 (current release), Windows 11
- CWX send (typed buffer / contest macro), 20 wpm, PC-audio sidetone
- An active panadapter + waterfall (this matters — see root cause)
Symptom
Expected: continuous local sidetone matching the sent text.
Actual: intermittent dropped/clipped elements under spectrum load.
- The sidetone plays the message but occasionally drops/clips an element (a dit, or the gap inside a character) — heard as a break or click, roughly every 4–5 character groups on a long message.
- Load-dependent: worse with a busy waterfall / higher VITA-49 packet rate.
- Cumulative timing stays correct — the message doesn't slow down or desync overall.
Root cause (from source)
CwxLocalKeyer is parented to MainWindow (GUI thread) and gates the sidetone by toggling key state on a QTimer, emitting keyStateChanged(bool) per element edge. MainWindow_Session.cpp routes that through a GUI-thread lambda → CwSidetoneGenerator::setKeyDown(), and CwSidetoneGenerator::process() (audio thread) reads m_keyDown once per block.
So the key gate is timed on the GUI thread, even though the samples are produced on the audio thread. Under panadapter paint + VITA-49 burst load the event loop coalesces both the timer and the slot, so an edge lands late and that element is gapped. The #3202 drift-correction keeps cumulative timing right but cannot fix per-edge jitter — and its own comment reasons specifically about macOS coalescing.
Reproduction
- Connect with a panadapter + waterfall active (load on the GUI/VITA path).
- Send a long CWX message at 20 wpm (a contest macro, or
CQ CQ CQ TST repeated).
- Listen to the PC-audio sidetone → intermittent dropped/clipped elements; worse with a busier waterfall.
Also reproduced deterministically and hardware-free by driving the client's input with a synthetic VITA-49 spectrum source while the client's own CWX keyer sends — confirming the stutter is purely client-side timing, correlated with VITA-49/GUI load (the radio is out of the loop entirely).
Suggested fix
- Robust: render the sidetone envelope sample-accurately in the audio path — derive key on/off from the element schedule against the audio sample clock — so edge timing no longer depends on event-loop delivery.
- Smaller / lower-risk: run
CwxLocalKeyer on a dedicated high-priority thread (off the GUI loop) and set the gate via a direct connection, removing the GUI coalescing the comment names.
Related
#2980 / #3202 (macOS stutter + drift-correction), #2694 (Windows sidetone latency/distortion), #2754 (CharGap), #2181 (audio gate during CWX), #3271 (drift regression test).
Summary
On Windows (v26.6.3, current release), sending a CWX message produces an intermittent stutter — individual Morse elements are dropped or clipped roughly every few character groups, with audible clicks. Overall message timing stays correct (so #3202's drift-correction is working), but per-element edges slip under load.
This looks like the residual Windows case after #2980 (macOS stutter, fixed by #3202) and #2694 (Windows sidetone latency/distortion).
Environment
Symptom
Expected: continuous local sidetone matching the sent text.
Actual: intermittent dropped/clipped elements under spectrum load.
Root cause (from source)
CwxLocalKeyeris parented toMainWindow(GUI thread) and gates the sidetone by toggling key state on aQTimer, emittingkeyStateChanged(bool)per element edge.MainWindow_Session.cpproutes that through a GUI-thread lambda →CwSidetoneGenerator::setKeyDown(), andCwSidetoneGenerator::process()(audio thread) readsm_keyDownonce per block.So the key gate is timed on the GUI thread, even though the samples are produced on the audio thread. Under panadapter paint + VITA-49 burst load the event loop coalesces both the timer and the slot, so an edge lands late and that element is gapped. The #3202 drift-correction keeps cumulative timing right but cannot fix per-edge jitter — and its own comment reasons specifically about macOS coalescing.
Reproduction
CQ CQ CQ TSTrepeated).Also reproduced deterministically and hardware-free by driving the client's input with a synthetic VITA-49 spectrum source while the client's own CWX keyer sends — confirming the stutter is purely client-side timing, correlated with VITA-49/GUI load (the radio is out of the loop entirely).
Suggested fix
CwxLocalKeyeron a dedicated high-priority thread (off the GUI loop) and set the gate via a direct connection, removing the GUI coalescing the comment names.Related
#2980 / #3202 (macOS stutter + drift-correction), #2694 (Windows sidetone latency/distortion), #2754 (CharGap), #2181 (audio gate during CWX), #3271 (drift regression test).