Commit Graph

965 Commits

Author SHA1 Message Date
sjg f9492633d9 [fix](trx-frontend): add footer project link and safari favicon fix
Add the trx-rs GitHub link in the footer and make favicon handling more explicit for Safari.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 11:03:47 +01:00
sjg f8507698f4 [fix](trx-frontend): hide signal visuals for non-sdr
Hide the combined waterfall and spectrum block when filter controls are unavailable so non-SDR rigs do not show those visuals.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:59:09 +01:00
sjg 99c6ff0e87 [fix](trx-frontend): unify signal markers and clamp axis labels
Render the BW and tuned-frequency markers on a shared overlay and keep spectrum axis labels bold and inside their box.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:54:15 +01:00
sjg 00a453f18c [perf](trx-server): set opus complexity to 5 and raise default bitrate to 256k
Set opus encoder complexity from default (9-10) to 5 for both cpal and
SDR audio paths, significantly reducing encoding CPU usage with minimal
quality impact at these bitrates. Raise default bitrate from 192 kbps to
256 kbps for higher fidelity stereo audio.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:42:00 +01:00
sjg e3c7231650 [fix](trx-frontend): group signal visuals in main tab
Wrap the waterfall and spectrum in a shared main-tab block so lower sections and other tabs keep consistent spacing.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:37:53 +01:00
sjg 6e8b23052d [fix](trx-frontend): unify markers and active theme toggle
Keep the waterfall and spectrum markers visually continuous and style the theme toggle to match the active theme.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:35:13 +01:00
sjg bfbf18ae21 [fix](trx-frontend): add room in rds overlay
Increase the RDS overlay padding and width so the waterfall badge has more breathing room.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:32:41 +01:00
sjg da2cc91925 [fix](trx-frontend): restore sdr frequency accent and waterfall gap
Keep the SDR frequency input accented without extra VFOs and restore the bottom spacing below the waterfall.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:31:35 +01:00
sjg 93108c1248 [fix](trx-frontend): tighten two-state step scale toggle
Resize the step scale control so it reads as a balanced two-option toggle instead of a leftover segmented control.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:27:11 +01:00
sjg 816780aa6b [fix](trx-frontend): compact wfm controls layout
Align the WFM options into a concise control strip with consistent sizes and spacing in the main window.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:25:52 +01:00
sjg 3ea516d27c [fix](trx-frontend): clarify tune step labels
Rename the tune-step scale labels so the divisor toggle reads clearly in the frequency controls.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:22:56 +01:00
sjg ec1ea49092 [fix](trx-frontend): show bw label only during resize
Lift the bandwidth label slightly and render it only while the bandwidth edges are being dragged.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:20:48 +01:00
sjg a2872dece5 [fix](trx-frontend): mirror spectrum controls on waterfall
Remove the gap under the waterfall and extend tuning markers plus wheel, click, and bandwidth drag interactions to the overview canvas.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:18:29 +01:00
sjg 740d678357 [fix](trx-frontend): increase spectrum headroom and match heights
Add 10 dB of spectrum headroom and keep the overview waterfall the same height as the spectrum plot.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:14:22 +01:00
sjg 626d5e2ec5 [perf](trx-backend-soapysdr): quadrature NCO and decimated stereo detection
Replace per-sample sin_cos(pilot_phase) with a quadrature NCO that
advances via complex rotation (4 muls + 2 adds vs transcendental).
Renormalize every 1024 samples to prevent magnitude drift.

Decimate stereo detection logic (pilot coherence, lock, drive,
hysteresis) to run every 16 composite samples instead of every sample.
Accumulate pilot_mag and pilot_abs over the window and process averaged
values, scaling the IIR coefficients accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:07:16 +01:00
sjg 52aeb7b694 [fix](trx-frontend): remove top bar overlap with waterfall
Keep the top bar above the waterfall and remove the rounded logo box styling.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 10:02:32 +01:00
sjg a9aee190d3 [fix](trx-frontend): move logo bar content into top bar
Move the logo/header cluster into the top bar on the left side.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:56:39 +01:00
sjg 0c35051630 [perf](trx-backend-soapysdr): eliminate per-sample sin_cos and atan2 calls
Derive sin/cos of PLL phase error directly from I/Q arms (q/mag, i/mag)
instead of calling atan2 + sin_cos. Use double-angle identity to compute
38 kHz carrier (sin2θ = 2·sinθ·cosθ, cos2θ = 2·cos²θ-1) from the
rotated pilot sin/cos, eliminating the second sin_cos call entirely.
Drop Butterworth from 6th to 4th order (resampler Blackman-Harris now
handles stopband). Use power-of-2 bitmask for ring buffer indexing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:52:51 +01:00
sjg 4f99c23e7a [perf](trx-backend-soapysdr): reduce polyphase resampler phases from 128 to 64
Halves the coefficient bank from 128×32 to 64×32 (16 KB → 8 KB) for
better L1 cache utilization while maintaining sufficient fractional
sample resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:47:13 +01:00
sjg 7eb88b6669 [perf](trx-backend-soapysdr): use circular buffer for wfm resampler history
Replace shift_append (O(N) rotate_left per sample) with a circular buffer
index for O(1) writes. The polyphase resampler now reads from the ring
buffer directly, eliminating 3 × 32-element memmoves per composite sample.
Remove unused dot_product functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:46:35 +01:00
sjg 132cd5b950 [perf](trx-backend-soapysdr): batch wfm discriminator with avx2 atan2
Pre-compute all FM discriminator outputs using demod_fm_with_prev which
processes 8 samples at a time via AVX2 atan2, then iterate the scalar
results through the rest of the stereo pipeline. Eliminates per-sample
f32::atan2 calls from the inner loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:42:49 +01:00
sjg 36d0e7e862 [perf](trx-backend-soapysdr): reduce wfm resampler taps from 64 to 32
With Blackman-Harris window and proper cutoff (~0.24), 32 taps still
provides 60+ dB stopband rejection. Halves the per-sample MAC count
from 192 to 96 across the three resampler channels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:41:26 +01:00
sjg 380231a68f [perf](trx-backend-soapysdr): improve wfm stereo resampler and pilot rejection
Increase polyphase resampler phases from 32 to 128 for finer fractional
sample positioning. Replace Hamming window with Blackman-Harris for ~92 dB
stopband rejection. Add pilot notch on composite signal before diff demod
to prevent 19 kHz × 38 kHz intermod products in the stereo difference
path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:37:11 +01:00
sjg 700e5c9fab [perf](trx-backend-soapysdr): increase wfm resampler taps and filter order
Increase polyphase resampler taps from 16 to 64 for sharper anti-alias
stopband rejection. Upgrade sum/diff lowpass filters from 4th-order to
6th-order Butterworth (three biquad stages) for ~36 dB/octave rolloff,
improving stereo separation by better rejecting the 38 kHz subcarrier
residuals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:19:11 +01:00
sjg 1ba9c9dd3e [fix](trx-backend-soapysdr): widen wfm audio bandwidth to 18 kHz
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:11:50 +01:00
sjg 4994a869f9 [fix](trx-backend-soapysdr): compute resampler cutoff from actual rate ratio
The fixed WFM_RESAMP_CUTOFF of 0.94 passed frequencies up to 94 kHz at
200 kHz composite rate, while the output Nyquist is only ~24 kHz. The
38 kHz demod products in the stereo diff path were only ~31 dB attenuated
by the Butterworth and aliased back into 10-20 kHz audio, causing treble
corruption in stereo mode. Now the cutoff is computed as
audio_rate / composite_rate, properly anti-aliasing the polyphase
resampler output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 09:07:07 +01:00
sjg a5e66ed287 [fix](trx-backend-soapysdr): revert wfm resampler taps back to 16
32 taps caused audio silence on real signals. Revert to 16 taps
which works correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 02:20:42 +01:00
sjg edb456e843 [fix](trx-backend-soapysdr): replace avx2 atan2 with high-precision polynomial
Replace the low-accuracy 0.273 linear atan approximation with a
7th-order minimax polynomial (max error ~2.4e-7 rad vs ~0.004 rad).
Use branchless |y|>|x| argument reduction instead of y/x division
with quadrant fixup, avoiding division-by-zero and NaN branches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 02:10:02 +01:00
sjg cb4b81ca94 [fix](trx-backend-soapysdr): use precise atan2 in wfm discriminator and pll
Replace fast_atan2 polynomial approximation with f32::atan2 in the WFM
stereo decoder's FM discriminator and pilot PLL. The approximation
introduced harmonic distortion (~0.22 deg error) that manifested as
treble artifacts on strong/overdeviated broadcast signals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 02:04:06 +01:00
sjg 8f6a5af4ec [fix](trx-backend-soapysdr): hard-limit iq magnitude before wfm discriminator
Normalize IQ samples exceeding unit magnitude before the FM
discriminator. The discriminator only uses phase, so clamping
amplitude prevents overdeviated signals from producing clipped
composite baseband without losing frequency information.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:58:16 +01:00
sjg 13de90d664 [fix](trx-backend-soapysdr): increase wfm resampler taps from 16 to 32
Doubles the polyphase FIR length for the composite-to-audio rate
converter, improving stopband rejection from ~25 dB to ~50 dB.
This reduces treble distortion from imaging artifacts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:55:59 +01:00
sjg 8d0dc17317 [chore](trx-backend-soapysdr): remove unused smoothstep01
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:49:27 +01:00
sjg 815efdb1ae [fix](trx-backend-soapysdr): match sum/diff filters and simplify stereo blend
- Set STEREO_DIFF_BW_HZ = AUDIO_BW_HZ so both filter paths have
  identical group delay (improves multitone separation by ~10 dB).
- Zero out STEREO_SEPARATION_PHASE_TRIM (unnecessary with matched filters).
- Replace gradual blend ramp with binary blend: full stereo at pilot
  lock, mono when unlocked. The hysteresis thresholds already handle
  noisy signals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:48:16 +01:00
sjg 13576f73aa [test](trx-backend-soapysdr): add multi-tone wfm stereo separation test
Test L-only and R-only signals with tones at 400, 2000, 8000 and
14000 Hz to catch frequency-dependent group delay and phase trim
issues that the single 1 kHz test misses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:42:39 +01:00
sjg 33b218fce3 [perf](trx-backend-soapysdr): reduce frame emission overhead
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:41:34 +01:00
sjg 2ed4aaf46d [fix](trx-backend-soapysdr): tune wfm stereo filter bw and matrix gain
Restore AUDIO_BW_HZ to 15.8 kHz for cleaner mono path, widen
STEREO_DIFF_BW_HZ to 18 kHz for better high-frequency stereo detail,
and raise STEREO_MATRIX_GAIN from 0.30 to 0.50 (mathematically correct
unity gain for the L=(S+D)/2 stereo matrix).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:37:15 +01:00
sjg e7997f8492 [perf](trx-backend-soapysdr): use ring history for wfm resampler
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:34:50 +01:00
sjg a6c3a85c8d [fix](trx-backend-soapysdr): match wfm sum/diff filter cutoffs at 18 kHz
Raise both AUDIO_BW_HZ and STEREO_DIFF_BW_HZ to 18 kHz so the L+R and
L-R filter paths have identical group delay across the full audio band.
The previous mismatch (15.8 vs 14.5 kHz) caused frequency-dependent
phase errors in the stereo matrix that degraded real-world separation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:31:34 +01:00
sjg f9691fee1e [perf](trx-backend-soapysdr): vectorize wfm discriminator angle
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:30:41 +01:00
sjg 72219956d9 [perf](trx-backend-soapysdr): trim wfm resampler taps
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:21:50 +01:00
sjg b2ce62646c [fix](trx-backend-soapysdr): improve wfm stereo blend threshold
Raise the stereo blend floor from 0.55 to 0.75 at pilot lock and lower
the full-blend ceiling from stereo_detect_level 0.92 to 0.70.  This
gives real-world signals with moderate pilot strength much better L/R
separation (~17 dB immediately at lock vs ~5 dB before) and reaches
full unity blend sooner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:20:38 +01:00
sjg 926a02e043 [perf](trx-backend-soapysdr): streamline wfm decode loop
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:19:47 +01:00
sjg b42e557a25 [perf](trx-backend-soapysdr): pack iq fir filtering
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:17:16 +01:00
sjg 198efa2092 [perf](trx-backend-soapysdr): update fir overlap in place
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:13:10 +01:00
sjg 7a6467320b [perf](trx-backend-soapysdr): reuse fir scratch buffers
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:10:34 +01:00
sjg ca0f236f4a [perf](trx-backend-soapysdr): reduce mixer and buffer overhead
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:07:19 +01:00
sjg bec3fc72d3 [fix](trx-backend-soapysdr): widen wfm stereo image
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 01:03:05 +01:00
sjg 6f37f9c66b [fix](trx-backend-soapysdr): refine wfm stereo tracking
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 00:58:20 +01:00
sjg e84a0599fa [feat](trx-backend-soapysdr): add avx2 wfm hot paths
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 00:52:53 +01:00
sjg 3e88c3f5d9 [feat](trx-backend-soapysdr): speed up fir and widen wfm resampler
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 00:50:04 +01:00