Roadmap
The body of this page is rebuilt from the repository's canonical ROADMAP.md on every docs build by scripts/sync-roadmap.mjs. Edit ROADMAP.md at the repo root โ not this file.
ROADMAP.mdLast update: 2026-04-23 07:24:19Z ยท source of truth: ROADMAP.md
"If you can't demo it to another ham and have them say 'that's clearly better,' it doesn't ship."
This roadmap is phased, explicit, and testable. Every milestone lists:
- Scope โ what's in, what's out
- Deliverables โ concrete artifacts, files, binaries, docs
- Acceptance criteria โ measurable pass/fail gates (automated where possible)
- Testable success examples โ real-world demos a human operator can verify
- Stretch goals โ nice-to-haves if we have bandwidth
- Exit criteria โ the one-line "we can tag this release when..." check
If a proposed PR does not move at least one of these forward, it probably belongs on a branch, not in main.
Guiding Principlesโ
- Ship something useful every release. Even v0.1 should be genuinely better for hams than nothing.
- Testable > theoretical. If there is no acceptance criterion, there is no feature.
- Preserve the signal. We will refuse to ship any denoiser that measurably hurts CW transients or FT8/FT4 decode rates.
- Local-first, always. Zero cloud dependencies in core. No telemetry without explicit opt-in.
- Cross-platform from day one. Linux, macOS, Windows, Raspberry Pi 5.
- Latency is a feature. v0.1 < 100 ms, v0.3 target < 50 ms, v1.0 documented budget per mode.
- Community โฅ code. Docs, samples, and onboarding are first-class deliverables, not afterthoughts.
Latency Budget (reference)โ
| Stage | v0.1 target | v0.3 target | Notes |
|---|---|---|---|
| Audio capture (frame) | 10โ20 ms | 5โ10 ms | PortAudio / ALSA / JACK / WASAPI |
| Pre-emphasis + feature extraction | โค 5 ms | โค 2 ms | VOLK + liquid-dsp SIMD |
| ONNX inference (DFN3) | โค 30 ms | โค 15 ms | XNNPACK/CoreML/DirectML; INT8 stretch |
| Post-processing + overlap-add | โค 5 ms | โค 2 ms | โ |
| Output buffering | 10โ30 ms | 5โ15 ms | โ |
| End-to-end (p99) | < 100 ms | < 50 ms | Measured on M1 / i5-8xxx / RPi 5 |
RPi Zero 2 W ships with RNNoise (not DFN3) and has a separate, looser budget.
v0.1 โ Audio-Only Denoiser โ Virtual Cable
Theme: Prove the core value proposition with the smallest possible surface area. One executable, one model, one virtual cable, demonstrably better copy.
Scopeโ
In:
- Offline WAV denoising (CLI)
- Real-time audio-in โ audio-out (virtual cable friendly)
- DeepFilterNet3 primary model (ONNX, CPU)
- RNNoise fallback model (ONNX, CPU)
- Minimal Tk/Qt GUI: A/B toggle, device picker, record before+after, live telemetry
- Cross-platform: Linux / macOS / Windows / Raspberry Pi 5
Explicitly out:
- Any SDR / RF / IQ input (that's v0.2)
- GNU Radio flowgraph integration (v0.2)
- Mode profiles, adaptive notch (v0.3)
- Spectrogram UI (v0.4)
- Fine-tuning tooling (v0.5)
Deliverablesโ
rfwhisperPython package withpyproject.toml(installable viapip install -e .)rfwhisper denoiseโ offline WAV in โ WAV out + JSON reportrfwhisper denoise-liveโ real-time audio device โ audio devicerfwhisper audio listโ enumerate input/output devicesrfwhisper guiโ minimal cross-platform GUI (PySide6 or Tk)rfwhisper models fetchโ downloads pre-converted DFN3 + RNNoise ONNXmodels/deepfilternet3/model.onnx(or hosted with SHA-256 pinned in repo)models/rnnoise/model.onnx(or hosted with SHA-256 pinned)tests/audio/with acceptance harness (see below)docs/quickstart.md,docs/virtual-cable-setup.md(Win/Mac/Linux)- At least 5 seed samples in
samples/covering SSB, CW, FT8, VHF FM, powerline buzz
Acceptance Criteria (Pass/Fail)โ
| # | Criterion | Measurement | Threshold |
|---|---|---|---|
| A1 | Effective SNR gain on ham speech mix | Matched-filter correlation vs clean reference on tests/audio/ssb_mix_*.wav | โฅ +3 dB avg, โฅ +6 dB on powerline-dominant clips |
| A2 | No FT8 decode regressions | WSJT-X decoder run on raw vs denoised 15-min segment | Denoised decodes โฅ raw decodes, zero false decodes |
| A3 | No CW transient damage | RMS energy in keying-onset window (first 5 ms of dit) | Within ยฑ1 dB of raw |
| A4 | End-to-end latency (p99) | tests/audio/latency_probe.py with impulse train | < 100 ms on i5-8xxx / M1 / RPi 5 |
| A5 | Real-time factor (RTF) | DFN3 CPU-only on target hardware | RTF < 0.5 (headroom for other tasks) |
| A6 | No-op sanity (clean in โ clean out) | PESQ / STOI on clean speech | PESQ drop โค 0.3, STOI drop โค 0.02 |
| A7 | Cross-platform install | CI matrix build + smoke test | Green on ubuntu-22.04, macos-13, windows-2022 |
| A8 | Virtual cable routing docs | Manual verification checklist | A beginner can get audio routed to WSJT-X in โค 10 minutes |
All CI-enforceable criteria run in [.github/workflows/basic-ci.yml](https://github.com/jakenherman/rfwhisper/blob/main/.github/workflows/basic-ci.yml).
Testable Success Examplesโ
- "Weak 40m DX" demo โ A 60-second clip of an S3 DX station under S7 powerline buzz is processed and played blind for 5 volunteer hams. โฅ 4/5 prefer the denoised version AND copy โฅ 1 extra word/sentence on average.
- "FT8 marginal decode" demo โ A 15-minute FT8 cycle with known weak stations, replayed through RFWhisper โ virtual cable โ WSJT-X, recovers at least as many stations as raw, with zero false decodes. Ideal: +1 to +3 marginals/cycle.
- "CW under QRN" demo โ 25 WPM CW with atmospheric crashes. fldigi copy accuracy does not drop; operator reports crashes reduced โฅ 6 dB audibly.
- "POTA in a townhouse" demo โ Field recording from a noisy QTH (solar inverter + neighbor VDSL). Operator reports "I can actually work this band now" in a recorded testimonial.
- Latency probe โ Impulse-train round trip < 100 ms p99 on reference hardware. Logged in CI.
Stretch Goalsโ
- INT8 quantized DFN3 variant for RPi 4 support
- CoreML / DirectML / CUDA execution provider auto-select
- Push-to-toggle keyboard shortcut in GUI
- Waveform-only (no spectrogram) before/after viewer
- One-liner install scripts (
install.sh,install.ps1)
Exit Criteria โ v0.1.0โ
All of A1โA8 pass in CI on the reference hardware matrix, at least 3 of the 5 testable-success demos are recorded and linked from the release notes, and the quickstart doc has been validated end-to-end by at least one non-author contributor on each OS.
v0.2 โ GNU Radio + SoapySDR Pipeline
Theme: Take the audio MVP and wire it into a real SDR flowgraph. Live RF โ denoised audio, on-air.
Scopeโ
In:
- GNU Radio 3.10.x flowgraph: SoapySDR source โ demod (SSB/AM/FM/NBFM) โ resample โ gr-dnn ONNX denoiser block โ audio sink
- Pre-built flowgraphs for RTL-SDR, Airspy HF+, ADALM-Pluto, SDRplay, HackRF
rfwhisper flowgraph run <name>launcher- Working on at least 3 real SDRs with on-air QSOs documented
Out: Mode profiles (v0.3), UI overlays (v0.4), training tools (v0.5)
Deliverablesโ
flowgraphs/rtl_ssb_hf.grc(and generated.py)flowgraphs/airspy_hfplus_ssb.grcflowgraphs/pluto_vhf_fm.grcflowgraphs/sdrplay_ssb.grcflowgraphs/hackrf_wbfm.grcgr-rfwhisper/โ our own gr-dnn wrapper block with model-swap support, or a documented recipe for using stock gr-dnndocs/gnuradio-install.md(per-OS)docs/soapy-hardware-matrix.mdwith tested SDR list- On-air demo videos / recordings in release notes
Acceptance Criteriaโ
| # | Criterion | Threshold |
|---|---|---|
| B1 | Live flowgraph runs end-to-end on โฅ 3 SDRs | RTL-SDR v4, Airspy HF+, 1 of {Pluto, SDRplay, HackRF} |
| B2 | End-to-end latency (antenna โ speaker) | < 250 ms p99 on reference laptop (includes radio DSP) |
| B3 | CPU at 48 kHz audio + 384 ksps IQ | < 60 % of one core on i5-8xxx |
| B4 | Flowgraph restart stability | 1 hr soak without dropouts; 100 stop/start cycles without leaks |
| B5 | Model hot-swap | Switching DFN3 โ RNNoise at runtime works without restart |
| B6 | Retains all v0.1 acceptance | Re-run A1โA8 on equivalent audio through the flowgraph |
Testable Success Examplesโ
- On-air QSO recording demonstrating a real contact worked through RFWhisper on at least 3 different SDRs, posted in release notes.
- Contest replay โ 30-minute HF contest recording through RFWhisper shows improved busy-band copy without destroying CQ decodes.
- VHF FM weak-signal โ a scratchy 2m simplex signal becomes readable.
Stretch Goalsโ
gr-rfwhisperOOT module published to PyBOMBS / distro repos- Windows installer bundle (GR 3.10 + RFWhisper)
- GNU Radio Companion block palette entry with icon + help
- Live waterfall preview in GRC (not full UI yet)
Exit Criteria โ v0.2.0โ
B1โB6 pass. At least 3 on-air recordings from community contributors posted. Hardware matrix doc lists โฅ 5 SDRs with known status (even if "unsupported / needs help").
v0.3 โ Mode Profiles + Adaptive Notch
Theme: One denoiser is good; a tuned denoiser per mode is dramatically better. Add mode awareness and a classical notch that cooperates with the NN.
Scopeโ
In:
- Mode profiles:
ssb,cw,ft8,ft4,rtty,am,fm-narrow,fm-wide,vhf-ssb - Per-mode parameters: attack/release, NN aggressiveness, notch enable, bandwidth, de-emphasis
- Adaptive narrowband notch (classical DSP) before the NN โ removes carriers / birdies that would otherwise confuse it
- Profile auto-detect (optional, conservative)
- Latency budget < 50 ms on reference hardware for SSB/CW
Deliverablesโ
rfwhisper/profiles/*.yamlโ one per moderfwhisper denoise --profile cwCLI flag- Adaptive notch implementation (liquid-dsp
iirfiltor VOLK-accelerated LMS) - Profile docs with band/scenario suggestions
- Regression tests per profile
Acceptance Criteriaโ
| # | Criterion | Threshold |
|---|---|---|
| C1 | CW profile preserves keying transients | RMS window within ยฑ0.5 dB of raw |
| C2 | FT8 profile: decode count | โฅ raw decodes on test cycle; ideal +1 to +3 |
| C3 | SSB profile intelligibility (PESQ) | โฅ raw PESQ on matched pairs |
| C4 | Adaptive notch removes โฅ 30 dB at target birdie | Measured on synthetic carrier |
| C5 | Latency p99 on SSB/CW profiles | < 50 ms on i5-8xxx / M1 |
| C6 | Auto-detect accuracy (if enabled) | โฅ 90 % on labeled eval set; off by default |
Testable Success Examplesโ
- "2m weak-signal SSB" โ EME-style weak SSB goes from unreadable to copyable.
- "630m CW" โ slow CW under atmospheric QRN preserves all keying, crashes reduced.
- "FT8 profile never regresses" โ 10 hours of replayed FT8 across bands shows zero decode loss.
Stretch Goalsโ
- DIGI profile that preserves generic MFSK/PSK shape
- Per-profile model variants (tiny model for CW, full model for SSB)
- Rig-control (Hamlib) hook to auto-select profile from mode
Exit Criteria โ v0.3.0โ
C1โC5 pass across all profiles. At least one community contributor has validated each profile on real on-air signals.
v0.4 โ UI: Before/After Spectrogram + Metrics
Theme: Make the improvement visible. Hams trust their eyes and ears; give them both.
Scopeโ
In:
- Qt/PySide6 main window with:
- Dual waterfall (raw vs denoised) with synchronized scroll
- A/B audio toggle (big, obvious)
- Live telemetry: effective SNR gain, SINAD, RTF, CPU %, end-to-end latency
- Model selector + profile selector
- Before/after record button
- Optional docked view inside GRC-generated flowgraph
- Dark mode, high-contrast mode (for field ops in sunlight)
Deliverablesโ
rfwhisper-guibinary (PySide6)- Waterfall renderer (OpenGL or pyqtgraph)
- Metrics panel
- Screenshots in docs
Acceptance Criteriaโ
| # | Criterion | Threshold |
|---|---|---|
| D1 | GUI frame rate | โฅ 30 fps on reference laptop; โฅ 20 fps on RPi 5 |
| D2 | GUI CPU overhead | โค +10 % CPU vs headless |
| D3 | Telemetry accuracy | SNR gain estimate within ยฑ1 dB of reference |
| D4 | Latency display | Agrees with A4 probe within 5 ms |
| D5 | Accessibility | All controls keyboard-navigable; WCAG AA contrast in light/dark |
Testable Success Examplesโ
- Screenshot thread on QRZ / r/amateurradio where hams post "look at this waterfall difference".
- Field-ops screenshot from a POTA activation showing the UI working on a laptop in bright sun (high-contrast mode).
Stretch Goalsโ
- Web-based UI option (for headless server / remote ops)
- Recording library browser with ABX test mode
- Shareable "clip" export (6-second before/after MP4 with waveform + waterfall)
Exit Criteria โ v0.4.0โ
D1โD5 pass. 3+ screenshots + 1 short demo video in release notes.
v0.5 โ Fine-tuning Tools + Dataset Generator
Theme: Give operators the power to tune the model to their noise environment.
Scopeโ
In:
- Dataset builder: record clean ham speech + isolated noise, synthesize mixed training data with realistic SNRs
- Fine-tuning CLI (
rfwhisper train fine-tune) wrapping PyTorch + DFN3 training code - Export to ONNX with validated parity
- Evaluation harness (reuse v0.1 acceptance tests)
- Docs: "how to record your own noise, train, and deploy in 30 minutes"
Deliverablesโ
rfwhisper train record-noiseโ captures isolated noise from rigrfwhisper train build-datasetโ synthesizes mixes with SNR controlrfwhisper train fine-tuneโ LoRA-style or full fine-tunerfwhisper train exportโ PyTorch โ ONNX with parity checkrfwhisper train evaluateโ runs v0.1 acceptance suite on new model- Tutorial notebook in
notebooks/ - Optional: Hugging Face / self-hosted model hub structure
Acceptance Criteriaโ
| # | Criterion | Threshold |
|---|---|---|
| E1 | Fine-tune wall time (30 min noise sample, RTX 3060) | โค 2 hours |
| E2 | Fine-tune on RPi 5 CPU (long-running) | Completes in < 24 hours for tiny model |
| E3 | ONNX export parity vs PyTorch | Output diff โค 1e-3 RMS on eval set |
| E4 | Post-fine-tune eval | Beats baseline on user's noise by โฅ +2 dB SNR gain; no regression on held-out clean speech |
| E5 | Dataset generator realism | Blind listeners cannot reliably distinguish real vs synthesized mixes |
Testable Success Examplesโ
- Tutorial: operator records 10 minutes of their solar-inverter noise, fine-tunes for an hour, and demonstrates an additional +2 dB gain over the stock model on their own shack.
- Community-submitted model (e.g., "HF-Contester-v1") beats baseline on contest-week recordings.
Stretch Goalsโ
- Federated / community averaging of fine-tunes (privacy-preserving; opt-in)
- Quantization-aware fine-tuning
- LoRA adapters that can be hot-swapped per band
Exit Criteria โ v0.5.0โ
E1โE5 pass. At least 2 community-submitted fine-tunes accepted into the model hub.
v1.0 โ Polished Release
Theme: Boring-in-a-good-way. This is the version we tell non-hacker hams to install.
Scopeโ
In:
- Signed installers (Windows
.msi, macOS.dmgnotarized),.deb,.rpm, AUR - Raspberry Pi OS image (bootable SD card) with RFWhisper pre-installed
- At least 8 SDRs tested and officially supported
- Model hub: minimum 4 community-validated models (HF contest, VHF mobile, POTA portable, 630m / LF)
- Extensive docs site (mkdocs or similar)
- Performance benchmarks published for laptop + RPi 5 + mid-range desktop
- Localization scaffolding (en at minimum; community translations welcomed)
Deliverablesโ
- Signed Windows installer
- Notarized macOS .dmg (universal binary)
.deb,.rpm, AURPKGBUILD- RPi OS image + install doc
- Model hub (static site + CI validator)
- Docs site with tutorials, API reference, architecture
- Published benchmark report (reproducible, with hardware + methodology)
Acceptance Criteriaโ
| # | Criterion | Threshold |
|---|---|---|
| F1 | 8 supported SDRs tested on-air | Documented in hardware matrix with logs |
| F2 | Installer UX | Non-technical ham installs and gets audio routed in โค 15 minutes |
| F3 | Benchmark repro | Any contributor can replicate published numbers ยฑ10 % |
| F4 | All previous acceptance tests pass | A1โA8, B1โB6, C1โC6, D1โD5, E1โE5 green |
| F5 | Zero critical bugs open > 30 days | Tracked in GitHub Projects |
| F6 | Docs completeness | Every CLI flag, every GUI control, every profile documented |
Testable Success Examplesโ
- A new ham with zero DSP / ML background installs v1.0 on Windows, routes it to WSJT-X, and logs their first FT8 DX through RFWhisper within 1 hour of download.
- Contest club publishes testimonial: "RFWhisper made the difference on 80m Saturday night."
- At least one magazine / podcast review (QST, SDR-Academy, Ham Radio Crash Course, etc.).
Stretch Goalsโ
- Pre-installed on a popular SDR distro (DragonOS, etc.)
- Chrome/Firefox extension for browser-based SDR (KiwiSDR, WebSDR)
Exit Criteria โ v1.0.0โ
F1โF6 pass. Release notes include 8 SDR on-air logs, 4 community models, a benchmark report, and at least one external review.
v1.1+ โ Plugins, GR4 Native, Propagation Extras
Theme: Expand the platform. Keep v1.0 stable on a long-term support branch; iterate on main.
Candidate Work (prioritized at v1.0 retro)โ
- Plugin architecture: drop-in user models, custom DSP blocks, alternative notchers
- GNU Radio 4.0 native block (
gr4-rfwhisper) with DAG-native perf wins; keep 3.10 LTS branch - Propagation extras: VOACAP / ionosonde hints to bias the denoiser on expected signal shape
- RX-specific modes: digital voice (DMR/D-STAR/YSF audio denoise), EMCOMM voice modes
- TX assist: compander / de-noise of your own mic (with heavy ethical guardrails and clear labeling)
- Remote shack integration: WFView, FLrig, OpenWebRX pass-through
- Federated model improvements with cryptographic verification
- Rust rewrite of hot paths where profiling justifies it
Ground Rules for Post-1.0โ
- Main stays green. v1.0 users on an LTS branch never get surprised.
- Every new feature needs a testable success metric, same bar as v0.1โv1.0.
- Telemetry remains opt-in. Always. No exceptions.
- If it doesn't help an actual ham on the air, it waits.
How to Move a Version Forwardโ
- Pick an unchecked deliverable above.
- Open an issue linking to the relevant acceptance criterion (e.g., "A2: FT8 regression harness").
- Propose a design in GitHub Discussions if it's non-trivial.
- Submit a PR referencing the issue. CI enforces the applicable acceptance tests.
- Request review from the relevant area owner (see AGENTS.md role mapping).
- When the last box for a version is checked and all its acceptance tests pass, we cut the tag.
The roadmap is a living document. If you think a milestone is wrong, open an RFC issue. We'd rather change the plan than ship the wrong thing.
73 and keep the signal clean.