Skip to content

[docs] Document AetherSDR audio pipeline#2571

Merged
ten9876 merged 2 commits into
aethersdr:mainfrom
jensenpat:aether/audio-pipeline-docs
May 12, 2026
Merged

[docs] Document AetherSDR audio pipeline#2571
ten9876 merged 2 commits into
aethersdr:mainfrom
jensenpat:aether/audio-pipeline-docs

Conversation

@jensenpat

@jensenpat jensenpat commented May 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds a new docs/audio-pipeline.md source-of-truth for AetherSDR audio routing and updates the existing architecture/TX docs to point at it instead of carrying stale summaries.

The new document traces:

  • RX speaker audio from PanadapterStream decode through RX NR, client RX DSP, resampling, gain/trim, metering, scopes, buffering, and speaker writes
  • PC mic voice TX capture negotiation, resampling/downmix behavior, ordered voice DSP, monitor taps, PC mic gain, Quindar insertion, final limiting, metering, scopes, Opus packetization, and VITA fallback
  • Opus remote_audio_tx 24 kHz stereo Int16 framing, 10 ms packet cadence, PCC 0x8005, and pacing queue behavior
  • RADE TX/RX branch points, float32 PCM handoff, LPCNet/RADE/FARGAN rate conversion, decoded speech buffering, and VITA modem packetization
  • DAX/TCI TX low-latency and radio-native routes, including the client voice DSP bypass and PCC 0x03E3 / 0x0123 packet formats
  • Meter and scope tap locations, units, and channel policies
  • Every known L/R average, mono duplication, 24/44.1/48 kHz resampling/downsampling point, and Int16/float32 format conversion found while tracing the code

It also explicitly documents current edge cases:

  • Stereo mic sources with signal on only one side can lose 6.02 dB when Resampler::processStereoToStereo() averages L/R with a silent channel.
  • The current PC mic voice meter uses the left channel only, so right-only devices can show a silent or incorrect meter.
  • DAX radio-native TX also averages float32 stereo to mono with (L+R)/2, so one-sided stereo DAX/TCI input can lose 6.02 dB there too.

Docs Updated

  • Added docs/audio-pipeline.md
  • Updated docs/architecture-pipelines.md to make the TX/DAX/RADE routing summary match the current code and link to the new audio pipeline doc
  • Updated docs/tx-audio-signal-path.md to clarify that the AetherialAudio voice strip applies to PC mic voice TX, while DAX/TCI and RADE bypass that voice chain

Validation

  • git diff --check

No app build was run because this is a documentation-only change.

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

@jensenpat jensenpat changed the title Document AetherSDR audio pipeline [docs] Document AetherSDR audio pipeline May 11, 2026
@jensenpat jensenpat marked this pull request as ready for review May 11, 2026 03:48

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this — really thorough docs, and a useful contributor reference for the audio code. Spot-checked the concrete claims against the source and they hold up:

  • Resampler::processStereoToStereo() does average L/R and duplicate (src/core/Resampler.cpp:127).
  • PCC codes 0x03E3 / 0x0123 / 0x8005 match src/core/PanadapterStream.h:126-128.
  • Default TX chain Gate → EQ → DeEss → Comp → Tube → Enh (PUDU) → Reverb matches defaultChain() in src/core/AudioEngine.cpp:1771.
  • Final limiter ceiling default -1.0 dBFS matches src/core/ClientFinalLimiter.h:86.
  • Opus 24 kHz / 10 ms / 240 frames matches src/core/OpusCodec.h:48-51.
  • m_rxBufferCapMs default 200, clamped 50..1000, matches src/core/AudioEngine.h:114,599.
  • RADE TX 24→16 kHz mono → encode → 8→24 kHz stereo and RX 24→8 kHz mono → decode → 16→24 kHz stereo match src/core/RADEEngine.cpp:59-62,142,191,212,276.
  • The note that applyClientRxDspFloat32() is currently a dispatcher stub matches the TODO bodies in src/core/AudioEngine.cpp:1688-1701; the live RX strip is indeed inlined in writeAudio().

A few small notes (suggestions, not blockers):

  • The PR body and audio-pipeline.md Executive Summary explicitly call out three current edge cases (one-sided stereo (L+R)/2 loss in processStereoToStereo(), left-channel-only PC mic meter, DAX radio-native one-sided loss). These are real and worth tracking — consider opening a follow-up issue so they don't get lost in the docs.
  • tx-audio-signal-path.md renames "PooDoo™ Audio" to "AetherialAudio" — please double-check that's the canonical user-facing name in current GUI strings; if the menu/tab still reads "PooDoo" anywhere, the doc rename will read inconsistently.
  • Minor: "RADE TX/RX branch points" wording in the architecture-pipelines.md ASCII diagram is slightly cramped — readable, but a future pass could split the RADE/DAX boxes onto separate sub-flows for clarity. Not worth churning this PR.

Docs-only, no risk to runtime behavior, and the path/stage table at the bottom is going to save a lot of code-spelunking on future audio changes. Nice work.

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Claude here, reviewing on Jeremy's behalf.

Verdict

Strong merge. This is a genuinely useful piece of reference documentation that the project has been missing — comprehensive enough that future contributors won't have to grep four files to understand where audio averages, where it duplicates, and where it stays stereo. The path/stage table and the downmix/format-change table are the most valuable artifacts.

Disclosure: AI-generated via OpenAI Codex GPT-5.5 Pro, reviewed and tested by @jensenpat. I spot-checked four of the load-bearing technical claims against the actual code:

Claim Verification
Resampler::processStereoToStereo() averages L/R then duplicates Resampler.cpp:127 does (stereoIn[2*i] + stereoIn[2*i+1]) * 0.5; lines 138-139 duplicate single output to both channels
AudioEngine::resampleStereo() uses separate L/R resamplers to preserve pan AudioEngine.cpp:903-906 instantiates two Resamplers; 919-920 processes L and R independently; existing source comment at line 900 explicitly warns about the trap
DAX radio-native TX averages (L+R)/2 for stereo→Int16 mono conversion AudioEngine.cpp:4152 does exactly this
PC mic voice meter reads left channel only AudioEngine.cpp:3656 uses i += 2 stride over interleaved Int16 stereo

All four match the doc verbatim. The three "current known behavior" bullets at the top (one-sided stereo 6.02 dB loss, left-channel-only PC mic meter, DAX radio-native L+R averaging) are real bugs documented honestly rather than papered over — exactly the disclosure pattern reference docs should set.

What this adds that didn't exist

  • Comprehensive path/stage table — file/function, input format, output format, sample rate, channel handling, side effects, in one place
  • Downmix/duplication/resampling/format-change table — every stereo↔mono transition in the audio code annotated with which helper does the work
  • Meter tap table — pre/post stage, channel policy, units for every local and radio-side meter
  • Mermaid diagrams for each path — RX speaker, PC mic voice TX, RADE TX/RX, DAX TX routing — that any contributor can read without opening a debugger

The diffs to architecture-pipelines.md and tx-audio-signal-path.md correctly link out to the new doc and trim down stale summaries. The PooDoo™ → AetherialAudio rename in tx-audio-signal-path.md matches the current code (the AetherialAudioStrip class, the v0.9.6 unification, and the v26.5.1 CHANGELOG framing). Good consistency pass.

Follow-up worth filing as separate issues

The doc surfaces three current bugs as "known behavior." Each deserves its own GitHub issue so they get tracked rather than living only in the doc:

  1. Stereo mic 6.02 dB loss in Resampler::processStereoToStereo() — one-sided stereo input loses 6.02 dB when averaged with a silent channel. Affects PC mic capture path at non-24kHz rates.
  2. PC mic voice meter left-channel-only readAudioEngine.cpp:3656 i += 2 stride. A right-only mic device shows silent or incorrect levels.
  3. DAX radio-native TX 6.02 dB lossAudioEngine.cpp:4152 averages stereo to mono with the same one-sided-stereo penalty.

These are independent fixes; the doc doesn't need to wait on them.

Minor

  • The doc is 618 lines of new content. The auxiliary tables are the most valuable bit — recommend they stay current as the audio code evolves. Worth a CI hook eventually that flags PRs touching src/core/AudioEngine.cpp or src/core/Resampler.cpp for a "did you update docs/audio-pipeline.md?" reviewer prompt. Not in this PR's scope, just a thought.
  • The TCI / VirtualAudioBridge / PipeWireAudioBridge sections look accurate by class-name spot-check, but I didn't trace every code path inside them. If something there is subtly wrong, the table format makes it easy to fix in a follow-up.

CI

  • build SUCCESS
  • check-paths SUCCESS
  • check-windows SKIPPED (correct — docs-only)
  • No analyze (cpp) since no source files changed
  • CodeQL skipped (correct per the doc-only PR optimization landed in #2397)

Recommendation

Merge. Then file follow-up issues for the three documented bugs so they're in the tracker as actionable work, not just doc footnotes.

Thanks @jensenpat — the diagnostic discipline applied to documentation (tracing every L/R collapse, every resample boundary, every meter tap) is the same care you bring to fix PRs. The contributor notes at the end ("Treat Resampler::processStereoToStereo() as a mono-collapse helper") are the kind of "future-self warning" that prevents repeat mistakes.

73, Jeremy KK7GWY & Claude (AI dev partner)

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved — docs accurately reflect code, three documented bugs are real and now tracked separately.

@ten9876 ten9876 merged commit 3cf9de7 into aethersdr:main May 12, 2026
3 checks passed
ten9876 added a commit to jensenpat/AetherSDR that referenced this pull request May 12, 2026
Resolves add/add conflict in docs/audio-pipeline.md introduced when
aethersdr#2571 squash-merged to main while this PR was open. Both branches added
the file independently; this PR's version contains the post-fix
description ("canonical mono voice signal using Auto Left/Right/Average")
which supersedes aethersdr#2571's pre-fix description that was correct at the
time it was written.

Conflict resolved by taking the PR branch's content. Verified:
- 0 conflict markers remain
- post-fix "canonical mono voice signal" passage preserved (2 occurrences)
- pre-fix "averages L/R and then duplicates the result" language removed
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