Skip to content

[bug] Fix Slice audio loss after band changes#2128

Merged
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/issue-2064-audio-reassert
Apr 28, 2026
Merged

[bug] Fix Slice audio loss after band changes#2128
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/issue-2064-audio-reassert

Conversation

@jensenpat
Copy link
Copy Markdown
Collaborator

Fixes #2064

Summary

This PR fixes the reported Slice B audio loss after changing bands in a two-slice setup. After Aether sends the radio-authoritative display pan set <pan> band=<key> command, it now waits briefly for the Flex band stack restore to settle, then reasserts audio_mute=0 for any unmuted slice on that pan.

Problem

The issue report describes a Windows 10 FLEX-6400 setup with two panadapters/slices. Slice B remains visually unmuted after a band change, but its audio goes silent until the user manually clicks the speaker icon muted and then unmuted again.

The Slice Troubleshooter snapshot captured while the problem was active showed:

  • PC audio enabled
  • RX stream active
  • Audio engine not muted
  • Slice B audio mute reported as No
  • Slice B audio gain was up and the speaker route was correct

That means the app model and UI still believed Slice B was unmuted. The failure was below the UI state: the radio-side audio contribution for that slice was no longer being mixed/routed even though no audio_mute=1 status was reflected in Aether.

Root Cause

Band buttons intentionally use display pan set <pan> band=<key> so the Flex firmware remains authoritative for band-stack state: frequency, mode, filters, pan geometry, antenna selection, and related slice properties.

That command can also make the radio tear down and rebuild slice audio routing during the band transition. In the failing case, the radio appears to leave the slice out of the audio mix without sending an audio_mute status change. Since Aether's model already says audioMute() == false, calling SliceModel::setAudioMute(false) would no-op and would not send anything to the radio. The manual mute/unmute workaround works because it forces a fresh slice set <id> audio_mute=0 command after the transition.

Fix

After a successful band-stack command, Aether now schedules a 300 ms deferred reassertion:

  • Only runs when more than one slice exists
  • Only touches slices on the pan whose band changed
  • Skips slices the model says are intentionally muted
  • Sends slice set <id> audio_mute=0 directly, bypassing the no-op setter path

This preserves user-muted slices while giving the radio the same explicit nudge that the manual mute/off toggle provides.

Validation

  • git diff --check
  • cmake --build build -j10

Local app bundle from the validated build:
/Users/patj/.codex/worktrees/3b89/AetherSDR/build/AetherSDR.app

👨🏼‍💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat

@jensenpat jensenpat changed the title Fix Slice B audio loss after band changes [bug] Fix Slice audio loss after band changes Apr 28, 2026
@jensenpat jensenpat marked this pull request as ready for review April 28, 2026 14:46
@jensenpat jensenpat requested a review from ten9876 as a code owner April 28, 2026 14:46
Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch and clean fix, @jensenpat. The root cause analysis is thorough -- the radio silently dropping the slice from the audio mix without reflecting it in status is a tricky one, and the deferred reassertion mirrors exactly what the manual mute/unmute toggle does. A few observations:

Looks good:

  • Scoping to slices.size() > 1 avoids unnecessary commands on single-slice setups.
  • Skipping audioMute() == true slices correctly preserves user-muted state.
  • Bypassing SliceModel::setAudioMute() and sending the command directly is the right call -- the setter would no-op since the model already believes it's unmuted.
  • The null guard on slice in the loop is defensive but harmless given m_slices shouldn't contain nulls.
  • Files changed are strictly within scope of the stated fix.

One thing to consider:

The QTimer::singleShot(300, this, ...) lambda captures panId by value (good), but captures this implicitly. If MainWindow is destroyed during the 300 ms window (e.g., rapid disconnect), the timer fires on a dangling this. In practice this is extremely unlikely since MainWindow is the top-level widget and outlives most operations, and Qt's parent-based timer cancellation covers it when the timer's receiver (this) is passed as the context object -- which it is here. So this is safe as written.

The 300 ms delay is a reasonable empirical choice. If testers find radios that take longer to settle (e.g., older firmware), this could be bumped or made configurable, but I wouldn't over-engineer that now.

Declaration placement nit (non-blocking):

reassertUnmutedSliceAudioForPan is declared in the private slots: section of MainWindow.h, but it's a regular private method, not a slot. It works fine either way, but strictly it belongs in the private: methods section. Not worth a respin.

Overall this is a clean, minimal fix for a real user-facing bug. Thanks for the contribution and the detailed write-up.

@ten9876 ten9876 merged commit 990ce35 into ten9876:main Apr 28, 2026
5 checks passed
@jensenpat jensenpat deleted the aether/issue-2064-audio-reassert branch April 29, 2026 04:53
ten9876 added a commit that referenced this pull request Apr 29, 2026
Community-driven release.  WAVE Phase 2 visualization (#2124),
DAX-aware TCI multi-stream routing for FlexRadio firmware 4.2.18
(#2140), TCXO frequency-offset calibration (#2119), VFO marker
tri-state UX (#2141), v4.2.18 discovery beacon parsing (#2138).
Bug fixes from the community: r8b heap corruption (#2114, NF0T),
serial PTT triple-fix (#2125, chibondking), slice-audio mute on
band change (#2128, jensenpat), CWX Live toggle (#2122, jensenpat),
connect-radio dialog polish (#2121, jensenpat).

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
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.

no Audio slice B

2 participants