RADE (Radio AutoEncoder) is a neural codec for transmitting speech over HF radio channels. A neural encoder compresses speech into a latent vector which is modulated onto an OFDM waveform and transmitted. At the receiver a neural decoder reconstructs the speech features, which are synthesised into audio by the FARGAN vocoder. The system is trained end-to-end, jointly optimising the encoder, channel layer, and decoder for minimum speech distortion across a range of channel conditions.
RADE V2 builds on V1 with several algorithmic improvements:
| V1 | V2 | |
|---|---|---|
| Carriers | 30, includes pilot symbols | 14, data only (no pilots) |
| Equalisation | Classical DSP, pilot-aided | ML-based, no pilots required |
| 99% Occupied Bandwidth | ~2100 Hz (SSB filter limited) | ~860 Hz |
| Frame duration | ~120 ms | ~40 ms |
| PAPR (100% CCDF) | 4.2 dB | 3.5 dB |
| Frame sync | DSP | Neural network |
| End-of-over detection | Pilot pend sequence | Channel sparsity metric |
| Threshold SNR (AWGN) | -2 dB | ~-4.5 dB |
| Threshold SNR (MPP) | 0 dB | ~-3 dB |
The elimination of pilot symbols in V2 recovers the bandwidth and power they consumed, enabling a narrower, cleaner waveform and improved high and low SNR performance. Combined with the PAPR improvement, RADE V2 is approximately 3 dB more sensitive than V1 at low SNRs.
Threshold SNR values are approximate, based on informal listening tests and objective loss metric.
This repo is the reference Python implementation for RADE V1 and V2. The current focus is on RADE V2 development, however this repo also contains RADE V1 (including many ctests).
This repo is intended to support experimental work, with just enough information for the advanced experimenter to reproduce aspects of the work. The focus is on waveform development, not software configuration. It is not intended to be packaged for general use or to work across multiple Linux distros and operating systems. Unless otherwise stated, the code in this repo is intended to run only on Ubuntu Linux 22-24 on a non-virtual machine.
For deployment and distribution of RADE please use the C port.
RADE V2 is under active development. The waveform, model weights, and API are subject to change without notice, and future versions will not be backwards compatible with the current implementation.
Known issues are under investigation. On-air use is not recommended at this stage, and the FreeDV team is not able to provide support for pre-release V2 deployments. Any on-air V2 signals should be considered premature use of the development waveform and are not part of official FreeDV development activity.
The official V2 status will be announced on the FreeDV blog.
./inference.sh 250725/checkpoints/checkpoint_epoch_200.pth wav/brian_g8sez.wav /dev/null --rate_Fs --latent-dim 56 \
--peak --cp 0.004 --time_offset -16 --correct_time_offset -8 --auxdata --w1_dec 128 --write_rx 250725_rx.f32
./rx2.sh 250725/checkpoints/checkpoint_epoch_200.pth 250725a_ml_sync 250725_rx.f32 test.wav
play test.wav
./inference.sh model19_check3/checkpoints/checkpoint_epoch_100.pth wav/brian_g8sez.wav /dev/null \
--rate_Fs --pilots --pilot_eq --eq_ls --cp 0.004 --bottleneck 3 --auxdata --write_rx v1_rx.f32
cat v1_rx.f32 | python3 radae_rxe.py --model model19_check3/checkpoints/checkpoint_epoch_100.pth > features_out.f32
./build/src/lpcnet_demo -fargan-synthesis features_out.f32 - | aplay -f S16_LE -r 16000
test/v2_spot.sh is a good starting point for RADE V2 experimentation.D. Rowe, J.-M. Valin, RADE: A Neural Codec for Transmitting Speech over HF Radio Channels, arXiv:2505.06671, 2025. This paper describes RADE V1; a V2 paper is planned as future work. The companion branch of this repo (with a RADE V1 focus) is waspaa_2025.
The RADE source code is released under the two-clause BSD license.
| File | Description |
|---|---|
inference.py / inference.sh | RADE V2 transmitter: encodes speech and modulates to a complex IQ sample file |
rx2.py / rx2.sh | RADE V2 receiver: stateful, streaming decoder |
radae_txe.py / radae_rxe.py | RADE V1 transmitter and receiver |
radae/radae.py | Core RADE model definition (encoder, channel layer, decoder) |
train.py | Training script for the RADE encoder/decoder |
ml_sync.py / models_sync.py | ML frame sync: trains and runs the neural frame synchroniser |
train_ft_sync.sh | Automation script for training the ML sync model |
loss.py | Measures ML loss (speech distortion) between encoder and decoder feature vectors |
compare_models_inf.sh | Generates loss versus SNR curves across models and channel types |
ota_test.sh | Over-the-air/over-the-cable test: generates tx signal, decodes rx, measures loss |
radev2_rx_wav.sh | Decode an off-air RADE V2 WAV recording; outputs decoded speech and diagnostic plots |
est_CNo.py | C/No estimation from a received chirp signal |
chirp.py | Generates a chirp reference signal used for timing and level calibration in OTA tests |
int16tof32.py / f32toint16.py | Sample format converters between int16 and float32 |
test/v2_spot.sh | RADE V2 spot test: encodes, applies channel impairments, decodes, checks loss |
test/v2_acq.sh | Acquisition tests: false acquisition rate on noise or noise plus sine wave |
test/ota_test_cal.sh | Calibrated OTA test using the ch channel simulator, checks V1 and V2 loss |
test/snr_est_test.sh | Steps through SNR range comparing measured vs estimated SNR3k |
test/eoo_detect_prob.sh | Measures probability of correct EOO detection over a range of channel conditions |
test/eoo_false_prob.sh | Measures EOO false detection rate on noise |
sox, python3, python3-matplotlib and python3-tqdm, octave, octave-signal, cmake. Pytorch should be installed using the instructions from the pytorch web site.
Builds the FARGAN vocoder and ctest framework, most of RADAE is in Python.
cd ~
git clone https://github.com/drowe67/radae.git
cd radae
mkdir build
cd build
cmake ..
make
The cmake/ctest framework is being used as a build and test framework. The command lines in CmakeLists.txt are a good source of examples, if you are interested in running the code in this repo. The ctests are a work in progress and may not pass on all systems (see Scope above).
To run the tests:
cd radae/build
ctest
To list tests ctest -N, to run just one test ctest -R inference_model5, to run in verbose mode ctest -V -R inference_model5.
A lot of the tests generate a float IQ sample file. You can listen to this file with:
cat rx.f32 | python3 f32toint16.py --real --scale 8192 | play -t .s16 -r 8000 -c 1 - bandpass 300 2000
The scaling --scale is required as the low SNRs mean the noise peak amplitude can clip 16 bit samples if not carefully scaled.
To decode a WAV file received off air (e.g. from a KiwiSDR or similar SDR receiver):
./radev2_rx_wav.sh ~/Downloads/kiwi_sdr_rx.wav
All output artefacts are stored in a subdirectory named after the input file:
~/Downloads/kiwi_sdr_rx/kiwi_sdr_rx_rade2.wav # decoded speech
~/Downloads/kiwi_sdr_rx/kiwi_sdr_rx_plots.png # sync state, SNR, freq offset, gain plots
~/Downloads/kiwi_sdr_rx/report.txt # terse per-frame decoder log
The input WAV can be any sample rate (resampled to 8kHz internally). Pass --verbose for the full decoder log including bash trace.
The rade_c repo contains the C port of RADE V1 and V2. Its ctests are optional and only enabled when RADE_C_BUILD_DIR is passed to cmake:
cd ~
git clone https://github.com/freedv/rade_c.git
cd rade_c && mkdir build && cd build && cmake .. && make
cd ~/radae/build
cmake -DRADE_C_BUILD_DIR=~/rade_c/build ..
ctest -R rade_c
This section is optional - pre-trained models that run on a standard laptop CPU are available for experimenting with RADAE. If you wish to perform training, a serious NVIDIA GPU is required - the author used a RTX4090.
Generate a training features file using your speech training database training_input.pcm, we used 200 hours of speech from open source databases:
./lpcnet_demo -features training_input.pcm training_features_file.f32
Generate the MPP channel simulation file:
echo "Rs=50; Nc=14; multipath_samples('mpp', Rs, Rs, Nc, 250*60*60, 'h_nc14_mpp_train_test.c64','',1); quit" | octave-cli -qf
Train the RADE V2 encoder/decoder (the 250725 model was trained with these settings):
python3 train.py --cuda-visible-devices 0 --sequence-length 400 --batch-size 512 \
--epochs 200 --lr 0.003 --lr-decay-factor 0.0001 \
training_features_file.f32 250725 \
--latent-dim 56 --cp 0.004 --auxdata --w1_dec 128 --peak \
--h_file h_nc14_mpp_train.c64 --h_complex --range_EbNo --range_EbNo_start 3 \
--timing_rand --freq_rand --ssb_bpf --plot_loss
Generate latent vectors from the trained model for ML sync training. This runs one pass through the training data without updating weights. Note the addition of +/- 2 ms of timing jitter, to maintain frame sync across the delay spread of multipath channels:
python3 train.py --cuda-visible-devices 0 --sequence-length 400 --batch-size 512 \
--epochs 200 --lr 0.003 --lr-decay-factor 0.0001 \
training_features_file.f32 tmp \
--latent-dim 56 --cp 0.004 --auxdata --w1_dec 128 --peak \
--h_file h_nc14_mpp_train.c64 --h_complex --range_EbNo --range_EbNo_start 3 \
--timing_rand --timing_jitter 0.002 --freq_rand --ssb_bpf \
--plot_EqNo 250725 --initial-checkpoint 250725/checkpoints/checkpoint_epoch_200.pth \
--write_latent 250725a_z_train.f32
Train the ML frame sync model:
python3 ml_sync.py 250725a_z_train.f32 --count 100000 --save_model 250725a_ml_sync --latent_dim 56
Automatic Speech Recognition (ASR) is used as an objective speech quality metric to compare RADE V1 against SSB and FreeDV 700D. The Whisper ASR model scores Word Error Rate (WER) on LibriSpeech samples passed through the modems under test.
Install dependencies:
pip3 install jiwer openai-whisper soundfile
The LibriSpeech test-clean dataset (~400 MB) is downloaded automatically to ~/.cache/LibriSpeech/ on first run via torchaudio.
Run controls (clean speech, FARGAN vocoder only, 4 kHz bandwidth):
./asr_test.sh clean && ./asr_test.sh fargan && ./asr_test.sh 4kHz
Run a sweep across AWGN channel conditions for each mode (100 samples):
./asr_test_top.sh ssb -n 100
./asr_test_top.sh rade -n 100
./asr_test_top.sh radev2 -n 100
./asr_test_top.sh 700D -n 100
For MPP channel, first generate the 4000s fading file (if not already present), then run MPP sweeps:
if [ ! -f g_mpp_4000s.f32 ]; then
DISPLAY="" echo "Fs=8000; Rs=50; Nc=20; multipath_samples('mpp', Fs, Rs, Nc, 4000, '','g_mpp_4000s.f32'); quit" | octave-cli -qf
fi
./asr_test_top.sh ssb -n 100
./asr_test_top.sh rade -n 100
./asr_test_top.sh radev2 -n 100
Plot WER curves in Octave:
octave:1> radae_plots; plot_wer("260702","260702_asr_test.png")
octave:1> radae_plots; plot_wer_v2("260702","260702_wer_v2.png")
The rade_c repo contains the full standalone C port of RADE. When a new model is trained, the weights need to be exported from Python and compiled into rade_c:
cd radae
python3 export_rade_weights.py model19_check3/checkpoints/checkpoint_epoch_100.pth src
rade_enc_data.c, rade_enc_data.h, rade_dec_data.c, rade_dec_data.h into rade_c/src/ and rebuild.You are welcome to join the RADE development effort by testing RADE, submitting bug reports or interesting test results. There are several kinds of tests:
ota_test.sh script. These are carefully calibrated to measure the channel SNR, and test SSB, RADE V1, RADE V2 at the same peak power. This is a high quality test that is very useful to the RADE developers. It requires Linux command line skills, and effort to run the script. You need to send us the Tx input source audio and off air Rx audio files, so we can repeat the results (instructions below).We need repeatable, controlled test results for RADE development.
Any test results must be reproducible using the RADE command line tools (our verified C port or Python OK). The RADE team are unable to reproduce or investigate bug reports that require running an end user application or radio to reproduce (e.g. freedv-gui or other GUI application, web based SDR, hardware radio etc). This is because applications often have their own bugs, which are out of scope of RADE development. This generally means you need to submit an off air receive audio file that reproduces the issue you are reporting with the RADE command line tools. Application maintainers are encouraged to modify their programs to dump such a file to a disk file so the issue can be reproduced with the RADE command line tools.
Before contributing OTA test results or deploying RADE in an application, integration must be verified using a loss-based test procedure. This confirms the signal path is clean — no dropped buffers, no unintended DSP, no scaling errors — so that any on-air results reflect RADE performance, not integration issues.
The full procedure, including a checklist template for submitting results, is in doc/verification/verification_procedure.md.
The ota_test.sh script supports stored-file over-the-air and over-the-cable testing. It assembles a transmit file containing a chirp reference, compressed SSB, RADE V1, and RADE V2 signals in sequence, which can be sent over a real HF channel or processed through a channel simulator. The script performs a controlled test of SSB, RADE V1, and RADE V2 over real-world channels.
Generate a transmit file from an input speech wav (16 kHz mono):
./ota_test.sh wav/brian_g8sez.wav -x
This produces tx.wav, which is suitable for transmission OTA using your SSB transmitter. For OTA testing, transmit tx.wav and record the received signal to a wave file, e.g. rx.wav, using a remote HF receiver.
Alternatively, simulate a real HF channel by passing tx.wav through the ch channel simulator to add noise and fading:
./build/src/ch tx.wav - --No -20 | sox -t .s16 -r 8000 -c 1 - rx.wav
Decode rx.wav and measure ML loss against the original speech:
./ota_test.sh -r rx.wav -l wav/brian_g8sez.wav
The decoded audio files rx_ssb.wav, rx_rade1.wav, and rx_rade2.wav are written to the same directory as rx.wav. A report file and spectrogram are also produced, including objective loss measurements (if -l option used).
See ota_test.sh for more information.
If submitting a test result to the RADE team, please email the input audio file (e.g. brian_g8sez.wav) and off air received audio file (e.g. rx.wav). We can then use your files to reproduce your results.
This section contains some notes on setting up a web server to run ota_test.sh. The idea is to make it easier for non-Linux users to contribute to the stored file test program. The general idea is a CGI script interfaces to ota_test.sh to perform the Tx and Rx processing. We configure the web server so that the HTML forms and CGI scripts run in ~/public_html. The notes below are for Apache on Ubuntu 22.
The Python packages need to be available system wide , so www-data can use them:
sudo pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
sudo -u www-data python3 -c "import torch"
sudo pip3 install matplotlib
sudo -u www-data python3 -c "import matplotlib"
The presence of the packages can be checked by mimicing the www-data user (the last line in each step above should not fail if all is well).
Configure Apache for CGI and serving pages from our ~/public_html dir.
sudo a2enmod cgid
sudo a2enmod userdir
sudo systemctl restart apache2
We want html and cgi to run out of ~/public_html, so permissions have to be 755 and www-data has to be added to the users group.
mkdir ~/public_html
chmod 755 public_html
sudo usermod -a -G <username> www-data
To let CGI scripts run from ~/public_html I placed this in my /etc/apache2/apache2.conf:
<Directory "/home/<username>/public_html">
Options +ExecCGI
AddHandler cgi-script .cgi
</Directory>
Then restart apache as above.
Create sym links to HTML/CGI scripts in radae repo, this allows the script to be part of the RADAE repo:
cd ~/public_html
ln -s ~/radae/public_html/tx_form.html tx_form.html
ln -s ~/radae/public_html/tx_process.cgi tx_process.cgi
Note that files created when the CGI process run (e.g. /tmp/input.wav) get put in a sandbox rather than directly in /tmp. This is a systemd security feature. You can find the files with:
sudo find /tmp -name input.wav | xargs sudo ls -ld
-rw-r--r-- 1 www-data www-data 3918458 Aug 15 15:28 /tmp/systemd-private-2fcf85ad243b4da08d79d2e27e0375af-apache2.service-vDE2Dg/tmp/input.wav
Apache error log, good for viewing ota_test.sh progress and spotting any issues:
tail -f /var/log/apache2/error.log
549 followers · starred May 2026
166 followers · starred Feb 2026
482 followers · starred Jul 2026
Python
54.4%
Shell
19.5%
CMake
13.6%
MATLAB
6.4%
C
6.0%
RADE (Radio AutoEncoder) is a neural codec for transmitting speech over HF radio channels. A neural encoder compresses speech into a latent vector which is modulated onto an OFDM waveform and transmitted. At the receiver a neural decoder reconstructs the speech features, which are synthesised into audio by the FARGAN vocoder. The system is trained end-to-end, jointly optimising the encoder, channel layer, and decoder for minimum speech distortion across a range of channel conditions.
RADE V2 builds on V1 with several algorithmic improvements:
| V1 | V2 | |
|---|---|---|
| Carriers | 30, includes pilot symbols | 14, data only (no pilots) |
| Equalisation | Classical DSP, pilot-aided | ML-based, no pilots required |
| 99% Occupied Bandwidth | ~2100 Hz (SSB filter limited) | ~860 Hz |
| Frame duration | ~120 ms | ~40 ms |
| PAPR (100% CCDF) | 4.2 dB | 3.5 dB |
| Frame sync | DSP | Neural network |
| End-of-over detection | Pilot pend sequence | Channel sparsity metric |
| Threshold SNR (AWGN) | -2 dB | ~-4.5 dB |
| Threshold SNR (MPP) | 0 dB | ~-3 dB |
The elimination of pilot symbols in V2 recovers the bandwidth and power they consumed, enabling a narrower, cleaner waveform and improved high and low SNR performance. Combined with the PAPR improvement, RADE V2 is approximately 3 dB more sensitive than V1 at low SNRs.
Threshold SNR values are approximate, based on informal listening tests and objective loss metric.
This repo is the reference Python implementation for RADE V1 and V2. The current focus is on RADE V2 development, however this repo also contains RADE V1 (including many ctests).
This repo is intended to support experimental work, with just enough information for the advanced experimenter to reproduce aspects of the work. The focus is on waveform development, not software configuration. It is not intended to be packaged for general use or to work across multiple Linux distros and operating systems. Unless otherwise stated, the code in this repo is intended to run only on Ubuntu Linux 22-24 on a non-virtual machine.
For deployment and distribution of RADE please use the C port.
RADE V2 is under active development. The waveform, model weights, and API are subject to change without notice, and future versions will not be backwards compatible with the current implementation.
Known issues are under investigation. On-air use is not recommended at this stage, and the FreeDV team is not able to provide support for pre-release V2 deployments. Any on-air V2 signals should be considered premature use of the development waveform and are not part of official FreeDV development activity.
The official V2 status will be announced on the FreeDV blog.
./inference.sh 250725/checkpoints/checkpoint_epoch_200.pth wav/brian_g8sez.wav /dev/null --rate_Fs --latent-dim 56 \
--peak --cp 0.004 --time_offset -16 --correct_time_offset -8 --auxdata --w1_dec 128 --write_rx 250725_rx.f32
./rx2.sh 250725/checkpoints/checkpoint_epoch_200.pth 250725a_ml_sync 250725_rx.f32 test.wav
play test.wav
./inference.sh model19_check3/checkpoints/checkpoint_epoch_100.pth wav/brian_g8sez.wav /dev/null \
--rate_Fs --pilots --pilot_eq --eq_ls --cp 0.004 --bottleneck 3 --auxdata --write_rx v1_rx.f32
cat v1_rx.f32 | python3 radae_rxe.py --model model19_check3/checkpoints/checkpoint_epoch_100.pth > features_out.f32
./build/src/lpcnet_demo -fargan-synthesis features_out.f32 - | aplay -f S16_LE -r 16000
test/v2_spot.sh is a good starting point for RADE V2 experimentation.D. Rowe, J.-M. Valin, RADE: A Neural Codec for Transmitting Speech over HF Radio Channels, arXiv:2505.06671, 2025. This paper describes RADE V1; a V2 paper is planned as future work. The companion branch of this repo (with a RADE V1 focus) is waspaa_2025.
The RADE source code is released under the two-clause BSD license.
| File | Description |
|---|---|
inference.py / inference.sh | RADE V2 transmitter: encodes speech and modulates to a complex IQ sample file |
rx2.py / rx2.sh | RADE V2 receiver: stateful, streaming decoder |
radae_txe.py / radae_rxe.py | RADE V1 transmitter and receiver |
radae/radae.py | Core RADE model definition (encoder, channel layer, decoder) |
train.py | Training script for the RADE encoder/decoder |
ml_sync.py / models_sync.py | ML frame sync: trains and runs the neural frame synchroniser |
train_ft_sync.sh | Automation script for training the ML sync model |
loss.py | Measures ML loss (speech distortion) between encoder and decoder feature vectors |
compare_models_inf.sh | Generates loss versus SNR curves across models and channel types |
ota_test.sh | Over-the-air/over-the-cable test: generates tx signal, decodes rx, measures loss |
radev2_rx_wav.sh | Decode an off-air RADE V2 WAV recording; outputs decoded speech and diagnostic plots |
est_CNo.py | C/No estimation from a received chirp signal |
chirp.py | Generates a chirp reference signal used for timing and level calibration in OTA tests |
int16tof32.py / f32toint16.py | Sample format converters between int16 and float32 |
test/v2_spot.sh | RADE V2 spot test: encodes, applies channel impairments, decodes, checks loss |
test/v2_acq.sh | Acquisition tests: false acquisition rate on noise or noise plus sine wave |
test/ota_test_cal.sh | Calibrated OTA test using the ch channel simulator, checks V1 and V2 loss |
test/snr_est_test.sh | Steps through SNR range comparing measured vs estimated SNR3k |
test/eoo_detect_prob.sh | Measures probability of correct EOO detection over a range of channel conditions |
test/eoo_false_prob.sh | Measures EOO false detection rate on noise |
sox, python3, python3-matplotlib and python3-tqdm, octave, octave-signal, cmake. Pytorch should be installed using the instructions from the pytorch web site.
Builds the FARGAN vocoder and ctest framework, most of RADAE is in Python.
cd ~
git clone https://github.com/drowe67/radae.git
cd radae
mkdir build
cd build
cmake ..
make
The cmake/ctest framework is being used as a build and test framework. The command lines in CmakeLists.txt are a good source of examples, if you are interested in running the code in this repo. The ctests are a work in progress and may not pass on all systems (see Scope above).
To run the tests:
cd radae/build
ctest
To list tests ctest -N, to run just one test ctest -R inference_model5, to run in verbose mode ctest -V -R inference_model5.
A lot of the tests generate a float IQ sample file. You can listen to this file with:
cat rx.f32 | python3 f32toint16.py --real --scale 8192 | play -t .s16 -r 8000 -c 1 - bandpass 300 2000
The scaling --scale is required as the low SNRs mean the noise peak amplitude can clip 16 bit samples if not carefully scaled.
To decode a WAV file received off air (e.g. from a KiwiSDR or similar SDR receiver):
./radev2_rx_wav.sh ~/Downloads/kiwi_sdr_rx.wav
All output artefacts are stored in a subdirectory named after the input file:
~/Downloads/kiwi_sdr_rx/kiwi_sdr_rx_rade2.wav # decoded speech
~/Downloads/kiwi_sdr_rx/kiwi_sdr_rx_plots.png # sync state, SNR, freq offset, gain plots
~/Downloads/kiwi_sdr_rx/report.txt # terse per-frame decoder log
The input WAV can be any sample rate (resampled to 8kHz internally). Pass --verbose for the full decoder log including bash trace.
The rade_c repo contains the C port of RADE V1 and V2. Its ctests are optional and only enabled when RADE_C_BUILD_DIR is passed to cmake:
cd ~
git clone https://github.com/freedv/rade_c.git
cd rade_c && mkdir build && cd build && cmake .. && make
cd ~/radae/build
cmake -DRADE_C_BUILD_DIR=~/rade_c/build ..
ctest -R rade_c
This section is optional - pre-trained models that run on a standard laptop CPU are available for experimenting with RADAE. If you wish to perform training, a serious NVIDIA GPU is required - the author used a RTX4090.
Generate a training features file using your speech training database training_input.pcm, we used 200 hours of speech from open source databases:
./lpcnet_demo -features training_input.pcm training_features_file.f32
Generate the MPP channel simulation file:
echo "Rs=50; Nc=14; multipath_samples('mpp', Rs, Rs, Nc, 250*60*60, 'h_nc14_mpp_train_test.c64','',1); quit" | octave-cli -qf
Train the RADE V2 encoder/decoder (the 250725 model was trained with these settings):
python3 train.py --cuda-visible-devices 0 --sequence-length 400 --batch-size 512 \
--epochs 200 --lr 0.003 --lr-decay-factor 0.0001 \
training_features_file.f32 250725 \
--latent-dim 56 --cp 0.004 --auxdata --w1_dec 128 --peak \
--h_file h_nc14_mpp_train.c64 --h_complex --range_EbNo --range_EbNo_start 3 \
--timing_rand --freq_rand --ssb_bpf --plot_loss
Generate latent vectors from the trained model for ML sync training. This runs one pass through the training data without updating weights. Note the addition of +/- 2 ms of timing jitter, to maintain frame sync across the delay spread of multipath channels:
python3 train.py --cuda-visible-devices 0 --sequence-length 400 --batch-size 512 \
--epochs 200 --lr 0.003 --lr-decay-factor 0.0001 \
training_features_file.f32 tmp \
--latent-dim 56 --cp 0.004 --auxdata --w1_dec 128 --peak \
--h_file h_nc14_mpp_train.c64 --h_complex --range_EbNo --range_EbNo_start 3 \
--timing_rand --timing_jitter 0.002 --freq_rand --ssb_bpf \
--plot_EqNo 250725 --initial-checkpoint 250725/checkpoints/checkpoint_epoch_200.pth \
--write_latent 250725a_z_train.f32
Train the ML frame sync model:
python3 ml_sync.py 250725a_z_train.f32 --count 100000 --save_model 250725a_ml_sync --latent_dim 56
Automatic Speech Recognition (ASR) is used as an objective speech quality metric to compare RADE V1 against SSB and FreeDV 700D. The Whisper ASR model scores Word Error Rate (WER) on LibriSpeech samples passed through the modems under test.
Install dependencies:
pip3 install jiwer openai-whisper soundfile
The LibriSpeech test-clean dataset (~400 MB) is downloaded automatically to ~/.cache/LibriSpeech/ on first run via torchaudio.
Run controls (clean speech, FARGAN vocoder only, 4 kHz bandwidth):
./asr_test.sh clean && ./asr_test.sh fargan && ./asr_test.sh 4kHz
Run a sweep across AWGN channel conditions for each mode (100 samples):
./asr_test_top.sh ssb -n 100
./asr_test_top.sh rade -n 100
./asr_test_top.sh radev2 -n 100
./asr_test_top.sh 700D -n 100
For MPP channel, first generate the 4000s fading file (if not already present), then run MPP sweeps:
if [ ! -f g_mpp_4000s.f32 ]; then
DISPLAY="" echo "Fs=8000; Rs=50; Nc=20; multipath_samples('mpp', Fs, Rs, Nc, 4000, '','g_mpp_4000s.f32'); quit" | octave-cli -qf
fi
./asr_test_top.sh ssb -n 100
./asr_test_top.sh rade -n 100
./asr_test_top.sh radev2 -n 100
Plot WER curves in Octave:
octave:1> radae_plots; plot_wer("260702","260702_asr_test.png")
octave:1> radae_plots; plot_wer_v2("260702","260702_wer_v2.png")
The rade_c repo contains the full standalone C port of RADE. When a new model is trained, the weights need to be exported from Python and compiled into rade_c:
cd radae
python3 export_rade_weights.py model19_check3/checkpoints/checkpoint_epoch_100.pth src
rade_enc_data.c, rade_enc_data.h, rade_dec_data.c, rade_dec_data.h into rade_c/src/ and rebuild.You are welcome to join the RADE development effort by testing RADE, submitting bug reports or interesting test results. There are several kinds of tests:
ota_test.sh script. These are carefully calibrated to measure the channel SNR, and test SSB, RADE V1, RADE V2 at the same peak power. This is a high quality test that is very useful to the RADE developers. It requires Linux command line skills, and effort to run the script. You need to send us the Tx input source audio and off air Rx audio files, so we can repeat the results (instructions below).We need repeatable, controlled test results for RADE development.
Any test results must be reproducible using the RADE command line tools (our verified C port or Python OK). The RADE team are unable to reproduce or investigate bug reports that require running an end user application or radio to reproduce (e.g. freedv-gui or other GUI application, web based SDR, hardware radio etc). This is because applications often have their own bugs, which are out of scope of RADE development. This generally means you need to submit an off air receive audio file that reproduces the issue you are reporting with the RADE command line tools. Application maintainers are encouraged to modify their programs to dump such a file to a disk file so the issue can be reproduced with the RADE command line tools.
Before contributing OTA test results or deploying RADE in an application, integration must be verified using a loss-based test procedure. This confirms the signal path is clean — no dropped buffers, no unintended DSP, no scaling errors — so that any on-air results reflect RADE performance, not integration issues.
The full procedure, including a checklist template for submitting results, is in doc/verification/verification_procedure.md.
The ota_test.sh script supports stored-file over-the-air and over-the-cable testing. It assembles a transmit file containing a chirp reference, compressed SSB, RADE V1, and RADE V2 signals in sequence, which can be sent over a real HF channel or processed through a channel simulator. The script performs a controlled test of SSB, RADE V1, and RADE V2 over real-world channels.
Generate a transmit file from an input speech wav (16 kHz mono):
./ota_test.sh wav/brian_g8sez.wav -x
This produces tx.wav, which is suitable for transmission OTA using your SSB transmitter. For OTA testing, transmit tx.wav and record the received signal to a wave file, e.g. rx.wav, using a remote HF receiver.
Alternatively, simulate a real HF channel by passing tx.wav through the ch channel simulator to add noise and fading:
./build/src/ch tx.wav - --No -20 | sox -t .s16 -r 8000 -c 1 - rx.wav
Decode rx.wav and measure ML loss against the original speech:
./ota_test.sh -r rx.wav -l wav/brian_g8sez.wav
The decoded audio files rx_ssb.wav, rx_rade1.wav, and rx_rade2.wav are written to the same directory as rx.wav. A report file and spectrogram are also produced, including objective loss measurements (if -l option used).
See ota_test.sh for more information.
If submitting a test result to the RADE team, please email the input audio file (e.g. brian_g8sez.wav) and off air received audio file (e.g. rx.wav). We can then use your files to reproduce your results.
This section contains some notes on setting up a web server to run ota_test.sh. The idea is to make it easier for non-Linux users to contribute to the stored file test program. The general idea is a CGI script interfaces to ota_test.sh to perform the Tx and Rx processing. We configure the web server so that the HTML forms and CGI scripts run in ~/public_html. The notes below are for Apache on Ubuntu 22.
The Python packages need to be available system wide , so www-data can use them:
sudo pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
sudo -u www-data python3 -c "import torch"
sudo pip3 install matplotlib
sudo -u www-data python3 -c "import matplotlib"
The presence of the packages can be checked by mimicing the www-data user (the last line in each step above should not fail if all is well).
Configure Apache for CGI and serving pages from our ~/public_html dir.
sudo a2enmod cgid
sudo a2enmod userdir
sudo systemctl restart apache2
We want html and cgi to run out of ~/public_html, so permissions have to be 755 and www-data has to be added to the users group.
mkdir ~/public_html
chmod 755 public_html
sudo usermod -a -G <username> www-data
To let CGI scripts run from ~/public_html I placed this in my /etc/apache2/apache2.conf:
<Directory "/home/<username>/public_html">
Options +ExecCGI
AddHandler cgi-script .cgi
</Directory>
Then restart apache as above.
Create sym links to HTML/CGI scripts in radae repo, this allows the script to be part of the RADAE repo:
cd ~/public_html
ln -s ~/radae/public_html/tx_form.html tx_form.html
ln -s ~/radae/public_html/tx_process.cgi tx_process.cgi
Note that files created when the CGI process run (e.g. /tmp/input.wav) get put in a sandbox rather than directly in /tmp. This is a systemd security feature. You can find the files with:
sudo find /tmp -name input.wav | xargs sudo ls -ld
-rw-r--r-- 1 www-data www-data 3918458 Aug 15 15:28 /tmp/systemd-private-2fcf85ad243b4da08d79d2e27e0375af-apache2.service-vDE2Dg/tmp/input.wav
Apache error log, good for viewing ota_test.sh progress and spotting any issues:
tail -f /var/log/apache2/error.log
549 followers · starred May 2026
166 followers · starred Feb 2026
482 followers · starred Jul 2026
Python
54.4%
Shell
19.5%
CMake
13.6%
MATLAB
6.4%
C
6.0%