Skip to content

Commit 7d6ef52

Browse files
authored
Merge pull request drowe67#274 from drowe67/dr-2020A
Experimental 2020A and 2020B Modes
2 parents 665f15e + 23057d7 commit 7d6ef52

30 files changed

+1004
-415
lines changed

.travis.yml

Lines changed: 0 additions & 90 deletions
This file was deleted.

CMakeLists.txt

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ if(UNITTEST)
357357
add_test(NAME test_freedv_get_hash
358358
COMMAND sh -c "${CMAKE_CURRENT_BINARY_DIR}/unittest/thash")
359359

360+
if(UNIX) # Uses pthreads
361+
add_test(NAME test_fifo
362+
COMMAND $<TARGET_FILE:tfifo>
363+
)
364+
endif()
365+
360366
# 16<->8 kHz float resamplers
361367
add_test(NAME test_fdmdv_16to8
362368
COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave;
@@ -514,16 +520,20 @@ if(UNITTEST)
514520
./ofdm_mod --ldpc |
515521
./ofdm_demod --ldpc --testframes > /dev/null")
516522

517-
# noise free 2020 test, including reading and writing payload bits. fsk_*_test_bits used as it does it's own frame sync
523+
# noise free 2020 test, including reading and writing payload bits. fsk_*_test_bits
524+
# used as it does it's own frame sync
518525
add_test(NAME test_OFDM_modem_2020_ldpc
519526
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
520527
./fsk_get_test_bits - 5000 |
521-
./ofdm_mod --ldpc --mode 2020 -p 312 |
522-
./ofdm_demod --ldpc --mode 2020 -p 312 |
528+
./ofdm_mod --ldpc --mode 2020 |
529+
./ofdm_demod --ldpc --mode 2020 |
523530
./fsk_put_test_bits - -q")
524531

525532
add_test(NAME test_OFDM_modem_AWGN_BER
526-
COMMAND sh -c "$<TARGET_FILE:ofdm_mod> --in /dev/zero --ldpc --testframes 60 --txbpf | $<TARGET_FILE:ch> - - --No -20 -f -50 | $<TARGET_FILE:ofdm_demod> --out /dev/null --testframes --ldpc --verbose 1"
533+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
534+
./ofdm_mod --in /dev/zero --ldpc --testframes 60 --txbpf |
535+
./ch - - --No -20 -f -50 |
536+
./ofdm_demod --out /dev/null --testframes --ldpc --verbose 1"
527537
)
528538

529539
add_test(NAME test_OFDM_modem_fading_BER
@@ -555,6 +565,13 @@ endif()
555565
./ch - - --No -22 |
556566
./ofdm_demod --mode 700E --ldpc --testframes -v 2 > /dev/null")
557567

568+
# 2020B AWGN test
569+
add_test(NAME test_OFDM_modem_2020B_AWGN
570+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
571+
./ofdm_mod --in /dev/zero --testframes 10 --mode 2020B --ldpc --clip --txbpf |
572+
./ch - - --No -19 |
573+
./ofdm_demod --mode 2020B --testframes --ldpc -v 2 > /dev/null")
574+
558575
# -------------------------------------------------------------------------
559576
# OFDM Data modes
560577
# -------------------------------------------------------------------------
@@ -737,22 +754,30 @@ if(LPCNET)
737754
add_test(NAME test_freedv_api_2020_to_ofdm_demod
738755
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
739756
./freedv_tx 2020 ../../wav/wia_16kHz.wav - --testframes |
740-
./ofdm_demod --mode 2020 --verbose 1 --ldpc -p 312 --testframes > /dev/null"
757+
./ofdm_demod --mode 2020 --verbose 1 --ldpc --testframes > /dev/null"
741758
)
742759

743760
add_test(NAME test_freedv_api_2020_from_ofdm_mod
744761
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
745-
./ofdm_mod --in /dev/zero --mode 2020 --verbose 1 --ldpc -p 312 --testframes 10 |
762+
./ofdm_mod --in /dev/zero --mode 2020 --verbose 1 --ldpc --testframes 10 |
746763
./freedv_rx 2020 - /dev/null --testframes"
747764
)
748765

749-
add_test(NAME test_freedv_api_2020_awgn
750-
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
766+
add_test(NAME test_freedv_api_2020_awgn
767+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
751768
dd bs=32000 count=10 if=/dev/zero |
752769
./freedv_tx 2020 - - --testframes |
753770
./ch - - --No -24 |
754771
./freedv_rx 2020 - /dev/null --testframes"
755772
)
773+
774+
add_test(NAME test_freedv_api_2020B_mpp
775+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
776+
dd bs=32000 count=60 if=/dev/zero |
777+
./freedv_tx 2020B - - --testframes --clip 1 |
778+
./ch - - --No -25 --mpp --fading_dir ../unittest |
779+
./freedv_rx 2020B - /dev/null --testframes"
780+
)
756781
endif()
757782

758783
add_test(NAME test_freedv_api_2400A
@@ -783,12 +808,6 @@ endif()
783808
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/unittest
784809
)
785810

786-
if(UNIX) # Uses pthreads
787-
add_test(NAME test_fifo
788-
COMMAND $<TARGET_FILE:tfifo>
789-
)
790-
endif()
791-
792811
# -------------------------------------------------------------------------
793812
# Reliable Text
794813
# -------------------------------------------------------------------------
@@ -870,7 +889,7 @@ if(LPCNET)
870889
endif(LPCNET)
871890

872891
# -------------------------------------------------------------------------
873-
# FreeDv API memory leaks
892+
# FreeDV API memory leaks
874893
# -------------------------------------------------------------------------
875894

876895
if (NOT APPLE)
@@ -940,16 +959,33 @@ if (NOT APPLE)
940959
if(LPCNET)
941960
add_test(NAME test_memory_leak_FreeDV_2020_tx
942961
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
943-
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./freedv_tx 2020 ../../wav/wia_16kHz.wav /dev/null"
962+
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
963+
./freedv_tx 2020 ../../wav/wia_16kHz.wav /dev/null"
944964
)
945965
set_tests_properties(test_memory_leak_FreeDV_2020_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors")
946966

947967
add_test(NAME test_memory_leak_FreeDV_2020_rx
948968
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
949969
./freedv_tx 2020 ../../wav/wia_16kHz.wav t.raw; \
950-
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./freedv_rx 2020 t.raw /dev/null"
970+
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
971+
./freedv_rx 2020 t.raw /dev/null"
951972
)
952973
set_tests_properties(test_memory_leak_FreeDV_2020_rx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors")
974+
975+
add_test(NAME test_memory_leak_FreeDV_2020B_tx
976+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
977+
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
978+
./freedv_tx 2020B ../../wav/wia_16kHz.wav /dev/null"
979+
)
980+
set_tests_properties(test_memory_leak_FreeDV_2020B_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors")
981+
982+
add_test(NAME test_memory_leak_FreeDV_2020B_rx
983+
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
984+
./freedv_tx 2020B ../../wav/wia_16kHz.wav t.raw; \
985+
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
986+
./freedv_rx 2020B t.raw /dev/null"
987+
)
988+
set_tests_properties(test_memory_leak_FreeDV_2020B_rx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors")
953989
endif(LPCNET)
954990
endif(NOT APPLE)
955991

README_freedv.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ These are designed for use with a HF SSB radio.
5454

5555
| Mode | Date | Codec | Modem | RF BW | Raw bits/s | FEC | Text bits/s | SNR min | Multipath |
5656
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
57-
| 1600 | 2012 | Codec2 1300 | 14 DQPSK + 1 DBPSK pilot carrier | 1125 | 1600 | Golay (23,12) | 25 | 4 | poor |
58-
| 700C | 2017 | Codec2 700C | 14 carrier coherent QPSK + diversity | 1500 | 1400 | - | - | 2 | good |
59-
| 700D | 2018 | Codec2 700C | 17 carrier coherent OFDM/QPSK | 1000 | 1900 | LDPC (224,112) | 25 | -2 | fair |
60-
| 700E | 2020 | Codec2 700C | 21 carrier coherent OFDM/QPSK | 1500 | 3000 | LDPC (112,56) | 25 | 1 | good |
61-
| 2020 | 2019 | LPCNet 1733 | 31 carrier coherent OFDM/QPSK | 1600 | 3000 | LDPC (504,396) | 22.2 | 2 | poor |
57+
| 1600 | 2012 | Codec2 1300 | 14 DQPSK + 1 DBPSK pilot carrier | 1125 | 1600 | Golay (23,12) | 25 | 4 | poor |
58+
| 700C | 2017 | Codec2 700C | 14 carrier coherent QPSK + diversity | 1500 | 1400 | - | - | 2 | good |
59+
| 700D | 2018 | Codec2 700C | 17 carrier coherent OFDM/QPSK | 1000 | 1900 | LDPC (224,112) | 25 | -2 | fair |
60+
| 700E | 2020 | Codec2 700C | 21 carrier coherent OFDM/QPSK | 1500 | 3000 | LDPC (112,56) | 25 | 1 | good |
61+
| 2020 | 2019 | LPCNet 1733 | 31 carrier coherent OFDM/QPSK | 1600 | 3000 | LDPC (504,396) | 22.2 | 2 | poor |
62+
| 2020A | 2022 | LPCNet 1733 | 31 carrier coherent OFDM/QPSK | 1600 | 3000 | LDPC (504,396) unequal | 22.2 | 2 | fair |
63+
| 2020B | 2022 | LPCNet 1733 | 29 carrier coherent OFDM/QPSK | 2100 | 4100 | LDPC (112,56) unequal | 22.2 | 3 | good |
6264

6365
Notes:
6466

@@ -86,6 +88,8 @@ Notes:
8688

8789
1. FEC was added fairly recently to FreeDV modes. The voice codecs we use work OK at bit error rates of a few %, and packet error rates of 10%. Raw bit error rates on multipath channels often exceed 10%. For reasonable latency (say 40ms) we need small codewords. Thus to be useful we require a FEC code that works at over 10% raw BER, has 1% output (coded) bit error rate, and a codeword of around 100 bits. Digital voice has unusual requirements, most FEC codes are designed for data which is intolerant of any bit errors, and few operate over 10% raw BER. Powerful FEC codes have long block lengths (1000's of bits) which leads to long latency. However LDPC codes come close, and can also "clean up" other channel errors caused by static and interference. The use of OFDM means we now have "room" for the extra bits required for FEC, so there is little cost in adding it, apart from latency.
8890

91+
1. 2020A and 2020B use unequal error protection, only 11 bits from each 52 bit vocoder frame are protected by FEC. This provides strong protection of the most important bits. The effect is a gentle "slope" in the speech quality versus SNR curve. These modes will work at lower SNRs that 2020, but will still have some audible errors even at high SNRs. 2020B has a modem waveform similar to 700E - a high pilot symbol rate so it operates on fast fading channels. Compared to 2020 it has a shorter frame duration (90ms), lower latency and faster sync, but requires a few more dB SNR.
92+
8993
## FreeDV VHF Modes
9094

9195
These modes use constant amplitude modulation like FSK or FM, and are designed for VHF and above. However 800XA can be run over HF or VHF on a SSB radio.
@@ -149,11 +153,11 @@ $ ./freedv_tx 2400B ../../raw/ve9qrp_10s.raw - | sox -t .s16 -r 48000 - -t .s16
149153
## FreeDV 2020 tests with FreeDV API
150154

151155
```
152-
$ cat ~/LPCNet/wav/wia.wav | ~/LPCNet/build_linux/src/lpcnet_enc -s | ./ofdm_mod --mode 2020 --ldpc --verbose 1 -p 312 | ./ofdm_demod --mode 2020 --verbose 1 --ldpc -p 312 | ~/LPCNet/build_linux/src/lpcnet_dec -s | aplay -f S16_LE -r 16000
156+
$ cat ~/LPCNet/wav/wia.wav | ~/LPCNet/build_linux/src/lpcnet_enc -s | ./ofdm_mod --mode 2020 --ldpc --verbose 1 | ./ofdm_demod --mode 2020 --verbose 1 --ldpc | ~/LPCNet/build_linux/src/lpcnet_dec -s | aplay -f S16_LE -r 16000
153157
```
154158
Listen the reference tx:
155159
```
156-
$ cat ~/LPCNet/wav/wia.wav | ~/LPCNet/build_linux/src/lpcnet_enc -s | ./ofdm_mod --mode 2020 --ldpc --verbose 1 -p 312 | aplay -f S16_LE
160+
$ cat ~/LPCNet/wav/wia.wav | ~/LPCNet/build_linux/src/lpcnet_enc -s | ./ofdm_mod --mode 2020 --ldpc --verbose 1 | aplay -f S16_LE
157161
```
158162

159163
Listen the freedv_tx:
@@ -163,7 +167,7 @@ $ ./freedv_tx 2020 ~/LPCNet/wav/wia.wav - | aplay -f S16_LE
163167

164168
FreeDV API tx, with reference rx from above:
165169
```
166-
$ ./freedv_tx 2020 ~/LPCNet/wav/wia.wav - | ./ofdm_demod --mode 2020 --verbose 1 --ldpc -p 312 | ~/LPCNet/build_linux/src/lpcnet_dec -s | aplay -f S16_LE -r 16000
170+
$ ./freedv_tx 2020 ~/LPCNet/wav/wia.wav - | ./ofdm_demod --mode 2020 --verbose 1 --ldpc | ~/LPCNet/build_linux/src/lpcnet_dec -s | aplay -f S16_LE -r 16000
167171
```
168172

169173
FreeDV API tx and rx:
@@ -196,6 +200,11 @@ $ ./src/freedv_tx 700D ../raw/ve9qrp.raw - --clip 0 --testframes | ./src/ch - -
196200

197201
Adjust `--clip [0|1]` and `No` argument of `ch` to obtain a PER of just less than 0.1, and note the SNR and PAPR reported by `ch`. The use of the `ve9qrp` samples makes the test run for a few minutes, in order to get reasonable multipath channel results.
198202

203+
Low SNR MPP channel 2020B command line:
204+
```
205+
cat ~/LPCNet/wav/all.wav | ~/LPCNet/build_linux/src/lpcnet_enc -x | ./src/ofdm_mod --mode 2020B --ldpc --clip --txbpf | ./src/ch - - --No -22 --mpd | ./src/ofdm_demod --mode 2020B --verbose 1 --ldpc | ~/LPCNet/build_linux/src/lpcnet_dec -x | aplay -f S16_LE -r 16000
206+
```
207+
199208
## Reading Further
200209

201210
1. [FreeDV web site](http://freedv.org)

README_ofdm.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Built as part of codec2-dev, see [README](README.md) for build instructions.
108108

109109
1. 20.5ms symbol period, 31 carrier waveform, (504,396) code, but only 312 data bits used, so we don't send unused data bits. This means we need less carriers (so more power per carrier), and code rate is increased slightly:
110110
```
111-
build_linux/src$ ./ofdm_mod --in /dev/zero --testframes 300 --mode 2020 --ldpc 1 --verbose 1 -p 312 | ./ch - - --No -22 -f 10 --ssbfilt 1 | ./ofdm_demod --out /dev/null --testframes --mode 2020 --verbose 1 --ldpc -p 312
111+
build_linux/src$ ./ofdm_mod --in /dev/zero --testframes 300 --mode 2020 --ldpc 1 --verbose 1 | ./ch - - --No -22 -f 10 --ssbfilt 1 | ./ofdm_demod --out /dev/null --testframes --mode 2020 --verbose 1 --ldpc
112112
113113
SNR3k(dB): 2.21 C/No: 37.0 PAPR: 9.6
114114
BER......: 0.0505 Tbits: 874020 Terrs: 44148

doc/modem_codec_frame_design.ods

-399 Bytes
Binary file not shown.

octave/ofdm_lib.m

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@
293293
Ts = 0.018;
294294
Nc = 17;
295295
config.bps = 2;
296-
config.txbpf_width_Hz = 1500;
297296
config.Np = 1;
298297
config.Ntxtbits = 4;
299298
config.Nuwbits = 5*config.bps;
@@ -322,7 +321,15 @@
322321
config.amp_scale = 155E3; config.clip_gain1 = 3; config.clip_gain2 = 0.8;
323322
config.foff_limiter = 1;
324323
elseif strcmp(mode,"2020")
325-
Ts = 0.0205; Nc = 31; config.amp_scale = 167E3;
324+
Ts = 0.0205; Nc = 31;
325+
config.amp_scale = 167E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8;
326+
elseif strcmp(mode,"2020B")
327+
Ts = 0.014; Tcp = 0.004; Nc = 29; Ns=5;
328+
config.Ntxtbits = 4; config.Nuwbits = 8*2; config.bad_uw_errors = 5;
329+
config.amp_scale = 130E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8;
330+
config.edge_pilots = 0; config.state_machine = "voice2";
331+
config.foff_limiter = 1; config.ftwindow_width = 64;
332+
config.txbpf_width_Hz = 2200;
326333
elseif strcmp(mode,"qam16c1")
327334
Ns=5; config.Np=5; Tcp = 0.004; Ts = 0.016; Nc = 33; config.data_mode = "streaming";
328335
config.bps=4; config.Ntxtbits = 0; config.Nuwbits = 15*4; config.bad_uw_errors = 5;
@@ -1890,8 +1897,8 @@ function test_assemble_disassemble(states)
18901897
function [rx_real rx] = ofdm_channel(states, tx, SNR3kdB, channel, freq_offset_Hz)
18911898
[rx_real rx sigma] = channel_simulate(states.Fs, SNR3kdB, freq_offset_Hz, channel, tx, states.verbose);
18921899

1893-
% add a few seconds of no signal either side
1894-
rx_real = [sigma*randn(1,states.Fs) rx_real sigma*randn(1,states.Fs/2)];
1900+
% add a few seconds of no-signal at the start
1901+
rx_real = [sigma*randn(1,states.Fs) rx_real];
18951902

18961903
% multipath models can lead to clipping of int16 samples
18971904
num_clipped = length(find(abs(rx_real>32767)));

0 commit comments

Comments
 (0)