Conversation
rade_tx_v2_process()/rade_tx_v2_eoo() now filter through one continuous rade_bpf state (300-2700Hz, matching radae_v2.py's RADEv2Transmitter and the model's training conditions), reusing the existing generic rade_bpf module already used by V1 Tx and V2 Rx. New RADE_NO_TX_BPF flag bit and --no_bpf option on rade_tx_wav; filter on by default via rade_api.c. Also fixes radae_tx.c's EOO tail-padding memset, which only zeroed sizeof(pointer) (8 bytes) rather than the actual buffer. CI: temporarily points the radae checkout at dr-tx-bpf (companion PR drowe67/radae#80) instead of main, since that PR's tx2.py default-on SSB BPF is needed for rade_c_v2_tx-style ctests to pass. Revert to main once that PR merges. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PzNQqmYXwUStAMrN4a5GFy
Each RX loop iteration consumes rade_nin() samples (one OFDM symbol), not a full modem frame (Nmf = 2 symbols for V2) -- the old wording mislabeled the granularity. Tx-side counters (radae_tx.c, rade_tx_wav.c) are unaffected, they genuinely process one whole modem frame per call. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PzNQqmYXwUStAMrN4a5GFy
OTC hardware verification, C vs Python Tx/Rx (260905,
|
| Run | Engine | C/No (dB-Hz) | PNR3k (dB) | EOO | V1 loss1/loss2/Δ | V2 loss1/loss2/Δ |
|---|---|---|---|---|---|---|
| otc-09 | C | 73.21 | 38.44 | ✓ | 0.110/0.111/0.001 | 0.082/0.084/0.002 |
| otc-10 | C | 73.30 | 38.53 | ✓ | 0.110/0.113/0.004 | 0.082/0.084/0.002 |
| otc-11 | C | 74.26 | 39.49 | ✓ | 0.110/0.111/0.001 | 0.082/0.085/0.003 |
| otc-12 | Python | 74.49 | 39.72 | ✓ | 0.110/0.111/0.001 | 0.082/0.084/0.002 |
| otc-13 | Python | 74.97 | 40.19 | ✓ | 0.110/0.111/0.001 | 0.082/0.084/0.002 |
| otc-14 | Python | 74.36 | 39.58 | ✓ | 0.110/0.111/0.001 | 0.082/0.084/0.002 |
loss1 = genie decode vs true input, loss2 = practical Rx vs true input, Δ = extra loss the real channel adds on top of genie (loss2 − loss1). Both engines land in the same tight band, and EOO fires reliably in all six runs with the new SSB BPF (data + EOO, both languages) in place.
As expected, the BPFs didn't change much. EOO was detected OK in all tests
…ring rade_get_stats() (modeled on codec2-dev's freedv_get_modem_extended_stats()) exposes per-symbol V2 receiver diagnostics -- sync state, delta_hat/ delta_hat_g, freq_offset, AGC gain, SNR estimate -- previously only available in the Python reference (rx2.py). Required persisting `gain` (was a local var in rade_rx_v2_process()) into rade_rx_v2_state. rade_rx_wav gains --write_state/--write_delta_hat/--write_delta_hat_g/ --write_freq_offset/--write_gain/--write_snr_est, streaming one value per OFDM symbol in the same per-symbol resolution and file formats as rx2.py's existing diagnostic log, so ota_test.sh's --v2_c path can drive the same plot_v2_logs() Octave plot as the Python path. Motivated by an OTA test (ota_01, PNR3k 0.57dB) whose whole-file loss average looked bad but sounded fine after the first second -- this diagnostic trace confirms it was a brief false-sync-then-reacquire transient (~85 symbols) dragging the average, not genuine post-lock quality. Validated against 4 real OTA recordings; also found the same transient in a second file (ota_02) and a clean single acquisition in two others (ota_03/04) at similar or lower SNR, suggesting it's a probabilistic near-threshold event rather than SNR-band-specific. Also fixes a stale/misleading model_file placeholder: rade_tx_wav.c, rade_rx_wav.c, radae_tx.c and radae_rx.c all hardcoded a V1 checkpoint filename passed to rade_open(), printed verbatim even in --v2 mode (the string is never read -- weights are always compiled in). Changed to "(unused, built-in weights)" to stop it looking like a real model load. All 24 rade_c_v2/ota_test_v2_c ctests still pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PzNQqmYXwUStAMrN4a5GFy
|
I've conducted some OTA tests between my home and various KiwiSDRs using this branch of the C code and the radae/ota_test.sh script with fine results. The loss metric doesn't work too well at low SNRs due to resyncs, but does give sensible results at high SNRs (ota_04). On the one sample tested (Brian), my personal preference is V2 to V1. This test shows the V2 code is working over a range of real world channel conditions. On one example, V1 wouldn't sync but V2 produced usable decoded speech. Note that ota_test.sh gives calibrated/comparable results between V1/V2 and SSB - a much better test protocol than ad-hoc testing which the PLT has already agreed isn't a reliable basis for comparison. It also removes any possible application-bug issues, as it just uses cmd line tools for the sample I/O.
(V1/V2 SNR = mean over the receiver's own synced-state period, not the whole file. † ota_02: V1 essentially never locked — only 4/90 logged status lines show "sync" state, hence the 0.31s decode. * that V1 SNR figure is from those same 4 lines, not a reliable average. V2 stayed locked and decoded the full 9.47s on the same recording.) |
tmiw
left a comment
There was a problem hiding this comment.
Just some minor feedback, feel free to not change anything if that's desired.
| with: | ||
| repository: drowe67/radae | ||
| ref: dr-radev2 | ||
| ref: dr-tx-bpf |
There was a problem hiding this comment.
Does this need to be reset prior to merge?
There was a problem hiding this comment.
We'll set it back to radae/main eventually, but I have a little more work to go in dr-tx-bpf before we merge.
Add SSB BW (300-2700Hz) Tx filter, matching reference Python tx2.py Tx, and addressing #18 .
Companion PR: drowe67/radae#80