aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrowe67 <[email protected]>2023-07-07 14:22:31 +0930
committerDavid Rowe <[email protected]>2023-07-07 14:22:31 +0930
commita291cfaf4ca3bb359852336f796aa5cc64568826 (patch)
tree5d765b89334fb422e1b6b83a0ce5d1e75098c15e
parent87025ac7d2a23192bf124ce8684626f821b099ea (diff)
some more Octave files rm-ed
-rw-r--r--octave/hackrf_dc.m26
-rw-r--r--octave/hackrf_twotone.m24
-rw-r--r--octave/hackrf_uc.m47
-rw-r--r--octave/horus_msg.txt1
-rw-r--r--octave/impulse_noise.m122
-rw-r--r--octave/load_comp.m9
-rw-r--r--octave/load_hackrf.m11
-rw-r--r--octave/load_rtlsdr.m11
-rw-r--r--octave/mancyfsk.m500
-rw-r--r--octave/mfsk.m199
-rw-r--r--octave/newamp1_fbf.m144
-rw-r--r--octave/nf_from_gr.m129
-rw-r--r--octave/nf_from_stdio.m133
-rw-r--r--octave/oqpsk.m521
-rw-r--r--octave/papr_test.m407
-rw-r--r--octave/phase_noise.m72
-rw-r--r--octave/pitch_test.m39
-rw-r--r--octave/pl.m45
-rw-r--r--octave/pl2.m44
-rw-r--r--octave/plamp.m135
-rw-r--r--octave/plinterp.m11
-rw-r--r--octave/pllpcpf.m150
-rw-r--r--octave/pllsp.m46
-rw-r--r--octave/pllspdt.m27
-rw-r--r--octave/plnlp.m134
-rw-r--r--octave/plphase.m198
-rw-r--r--octave/plpitch.m36
-rw-r--r--octave/plvoicing.m89
-rw-r--r--octave/power_from_stdio.m27
-rw-r--r--octave/pulse.m37
-rw-r--r--octave/save_array_c_header.m14
-rw-r--r--octave/save_comp.m12
-rw-r--r--octave/save_f32.m12
-rw-r--r--octave/save_hackrf.m13
-rw-r--r--octave/save_raw.m7
-rw-r--r--octave/snr_curves_plot.m262
-rw-r--r--octave/tdetphase.m84
-rw-r--r--octave/test_dqpsk2.m465
-rw-r--r--octave/trellis.m594
-rw-r--r--octave/vq_700c_eq.m366
-rw-r--r--octave/vq_compare.m349
41 files changed, 0 insertions, 5552 deletions
diff --git a/octave/hackrf_dc.m b/octave/hackrf_dc.m
deleted file mode 100644
index a204e70..0000000
--- a/octave/hackrf_dc.m
+++ /dev/null
@@ -1,26 +0,0 @@
-% hackrf_dc.m
-%
-% David Rowe Nov 2015
-%
-% Downconverts a HackRF IQ sample file to a lower sample rate
-%
-% To sample a -60dB signal:
-% $ hackrf_transfer -r df1.iq -f 439200000 -n 10000000 -l 20 -g 40play file at 10.7MHz used:
-% octave:25> d = hackrf_dc("df1.iq")
-
-function d = hackrf_dc(infilename)
- Fs1 = 10E6; % input sample rate to HackRF
- Fs2 = 96E3; % output sample rate
- fc = 700E3; % offset to shift input by, HackRF doesn't like signals in the centre
-
- s1 = load_hackrf(infilename);
- ls1 = length(s1);
- ls1 = 20*Fs1;
- t = 0:ls1-1;
-
- % shift down to baseband from Fc, not sure of rot90 rather than trasnpose operator '
- % to avoid unwanted complex conj
-
- s2 = rot90(s1(1:ls1)) .* exp(-j*2*pi*t*fc/Fs1);
- d = resample(s2, Fs2, Fs1);
-end
diff --git a/octave/hackrf_twotone.m b/octave/hackrf_twotone.m
deleted file mode 100644
index 1d5aa02..0000000
--- a/octave/hackrf_twotone.m
+++ /dev/null
@@ -1,24 +0,0 @@
-% hackrf_twotone.m
-%
-% David Rowe Nov 2015
-%
-% Generates a two tone test signal that can be played out of HackRF
-%
-% To play file at 10.7MHz used:
-% $ hackrf_transfer -t ../octave/twotone.iq -f 10000000 -a 0 -x 47
-%
-% However 2nd harmonic at 21.4 was only -32dBC so not really useful for my application
-% in testing an ADC
-
-Fs = 8E6;
-fc = 2E6;
-f1 = fc;
-f2 = fc+1E3;
-A = 127;
-T = 2;
-
-N = T*Fs;
-t = 0:N-1;
-%s = A*exp(j*2*pi*t*f1/Fs) + A*exp(j*2*pi*t*f2/Fs);
-s = A*exp(j*2*pi*t*f2/Fs);
-save_hackrf("twotone.iq",s);
diff --git a/octave/hackrf_uc.m b/octave/hackrf_uc.m
deleted file mode 100644
index 0f55bd1..0000000
--- a/octave/hackrf_uc.m
+++ /dev/null
@@ -1,47 +0,0 @@
-% hackrf_uc.m
-%
-% David Rowe Nov 2015
-%
-% Upconverts a real baseband sample file to a file suitable for input into a HackRF
-%
-% To play file at 10.7MHz used:
-% octave:25> hackrf_uc("fsk_10M.iq","fsk_horus_rx_1200_96k.raw")
-% $ hackrf_transfer -t ../octave/fsk_10M.iq -f 10000000 -a 1 -x 40
-
-function hackrf_uc(outfilename, infilename)
- pkg load signal;
- Fs1 = 48E3; % input sample rate
- Fs2 = 10E6; % output sample rate to HackRF
- fc = 700E3-24E3; % offset to shift to, HackRF doesn't like signals in the centre
- A = 100; % amplitude of signal after upc-nversion (max 127)
- N = Fs1*20;
-
- fin = fopen(infilename,"rb");
- printf("1\n");
- s1 = fread(fin,"short");
- printf("1\n");
- fclose(fin);
- printf("1\n");
- ls1 = length(s1);
- printf("1\n");
- N = ls1;
- % single sided freq shifts, we don't want DSB
- printf("1\n");
- s1 = hilbert(s1(1:N));
-
- % upsample to Fs2
-
- M = Fs2/Fs1;
- s2 = resample(s1(1:N),Fs2,Fs1);
- ls2 = length(s2);
- mx = max(abs(s2));
- t = 0:ls2-1;
- printf("2\n");
- % shift up to Fc, note use of rot90 rather than trasnpose operator '
- % as we don't want complex conj, that would shift down in freq
-
- sout = rot90((A/mx)*s2) .* exp(j*2*pi*t*fc/Fs2);
-
- save_hackrf(outfilename,sout);
-
-end
diff --git a/octave/horus_msg.txt b/octave/horus_msg.txt
deleted file mode 100644
index 882a9b3..0000000
--- a/octave/horus_msg.txt
+++ /dev/null
@@ -1 +0,0 @@
- 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 0.00000000e+00
diff --git a/octave/impulse_noise.m b/octave/impulse_noise.m
deleted file mode 100644
index dee5c5d..0000000
--- a/octave/impulse_noise.m
+++ /dev/null
@@ -1,122 +0,0 @@
-% impulse_noise
-% David Rowe May 2017
-%
-% Experiments with impulsive noise and HF radio
-
-format;
-more off;
-rand('seed',1)
-
-% DFT function ------------------------------------------------
-% note k is on 0..K-1 format, unlike Octave fft() which is 1..K
-
-function H = calc_H(k, K, a, d)
- L = length(d);
- H = 0;
- for i=1:L
- H += a(i)*exp(-j*2*pi*k*d(i)/K);
- end
-endfunction
-
-% -----------------------------------------
-% PWM noise simulation
-% -----------------------------------------
-
-function pwm_noise
-
- Fs = 10E6; % sample rate of simulation
- Fsig = 1E6; % frequency of our wanted signal
- Fpwm = 255E3; % switcher PWM frequency
- T = 1; % length of simulations in seconds
- Nsam = T*Fs;
- Nsamplot = 200;
- Apwm = 0.1;
- Asig = -40; % attenuation of wanted signal in dB
-
- % generate an impulse train with jitter to simulate switcher noise
-
- pwm = zeros(1,Fs);
- Tpwm = floor(Fs/Fpwm);
- pulse_positions_pwm = Tpwm*(1:T*Fpwm) + round(rand(1,T*Fpwm));
-
- h_pwm = zeros(1,Nsam);
- h_pwm(pulse_positions_pwm) = Apwm;
- h_pwm = h_pwm(1:Nsam);
-
- % add in wanted signal and computer amplitude spectrum
-
- s = 10^(Asig/20)*cos(2*pi*Fsig*(1:Nsam)/Fs);
-
- h = h_pwm+s;
- H = fft(h);
- Hdb = 20*log10(abs(H)) - 20*log10(Nsam/2);
-
- figure(1); clf;
- subplot(211)
- plot(h(1:Nsamplot));
- subplot(212)
- plot(Hdb(1:Nsam/2));
- axis([0 T*2E6 -120 0]); xlabel('Frequency Hz'); ylabel('Amplityude dBV'); grid;
-
- printf("pwm rms: %f signal rms: %f noise rms\n", std(h_pwm), std(s));
-endfunction
-
-% -----------------------------------------
-% Single pulse noise simulation
-% -----------------------------------------
-
-function pulse_noise
-
- % set up short pulse in wide window, consisting of two samples next
- % to each other
-
- K = 1024;
- a(1) = a(2) = 1; d(1) = 10; d(2) = d(1)+1;
- h = zeros(1,K);
- h(d(1)) = a(1);
- h(d(2)) = a(2);
-
- % mag and phase spectrum, mag spectrum changes slowly
-
- figure(2); clf;
- Hfft = fft(h);
- subplot(311)
- stem(h(1:100));
- axis([1 100 -0.2 1.2]);
- subplot(312)
- plot(abs(Hfft(1:K/2)),'+');
- title('Magnitude');
- subplot(313)
- plot(angle(Hfft(1:K/2)),'+');
- title('Phase');
-
- % simple test to estimate H(k+1) from H(k) --------------------
-
- % brute force calculation
-
- k = 300;
- H = zeros(1,K);
- H(k-1) = calc_H(k-1, K, a, d);
- H(k) = calc_H(k, K, a, d);
- H(k+1) = calc_H(k+1, K, a, d);
-
- % calculation of k+1 from k using approximation that {d(i)} are
- % close together compared to M, i.e it's a narrow pulse (assumes we
- % can estimate d using other means)
-
- Hk1_ = exp(-j*2*pi*d(1)/K)*H(k);
-
- % plot zoomed in version around k to compare
-
- figure(3); clf;
- plot(H(k-1:k+1),'b+','markersize', 10, 'linewidth', 2);
- hold on; plot(Hk1_,'g+','markersize', 10, 'linewidth', 2); hold off;
- title('H(k-1) .... H(k+1)');
- printf("H(k+1) match: %f dB\n", 20*log10(abs(H(k+1) - Hk1_)));
-endfunction
-
-% Run various simulations here ---------------------------------------------
-
-%pwm_noise
-pulse_noise
-
diff --git a/octave/load_comp.m b/octave/load_comp.m
deleted file mode 100644
index b9fa686..0000000
--- a/octave/load_comp.m
+++ /dev/null
@@ -1,9 +0,0 @@
-% load_comp.m
-% David Rowe Sep 2015
-
-function s = load_comp(fn)
- fs=fopen(fn,"rb");
- s = fread(fs,Inf,"float32");
- ls = length(s);
- s = s(1:2:ls) + j*s(2:2:ls);
-endfunction
diff --git a/octave/load_hackrf.m b/octave/load_hackrf.m
deleted file mode 100644
index 85bfb73..0000000
--- a/octave/load_hackrf.m
+++ /dev/null
@@ -1,11 +0,0 @@
-% load_hackrf.m
-%
-% David Rowe Oct 2015
-
-function s = load_hackrf(fn)
- fs = fopen(fn,"rb");
- iq = fread(fs,Inf,"schar");
- fclose(fs);
- l = length(iq);
- s = iq(1:2:l) + j*iq(2:2:l);
-endfunction
diff --git a/octave/load_rtlsdr.m b/octave/load_rtlsdr.m
deleted file mode 100644
index 946cfb2..0000000
--- a/octave/load_rtlsdr.m
+++ /dev/null
@@ -1,11 +0,0 @@
-% load_rtlsdr.m
-%
-% David Rowe Oct 2015
-
-function s = load_rtlsdr(fn)
- fs = fopen(fn,"rb");
- iq = fread(fs,Inf,"uchar");
- fclose(fs);
- l = length(iq);
- s = iq(1:2:l) + j*iq(2:2:l);
-endfunction
diff --git a/octave/mancyfsk.m b/octave/mancyfsk.m
deleted file mode 100644
index 1ee24ef..0000000
--- a/octave/mancyfsk.m
+++ /dev/null
@@ -1,500 +0,0 @@
-% mancyfsk.m
-% David Rowe October 2015
-%
-% Manchester encoded 2FSK & 4FSK simulation.
-%
-% Attempt to design a FSK waveform that can pass through legacy FM
-% radios but still be optimally demodulated by SDRs. It doesn't have
-% to be optimally demodulated by legacy radios. Trick is getting it
-% to pass through 300-3000Hz audio filters in legacy radios.
-%
-% [X] code up modulator
-% [X] manchester two bit symbols
-% [X] plot spectrum
-% [X] demodulate using analog FM and ideal demods
-% [X] measure BER compared to ideal coherent FSK
-
-1;
-
-fm; % analog FM library
-
-
-function states = legacyfsk_init(M,Rs)
- Fs = states.Fs = 96000;
- states.Rs = Rs; % symbol rate over channel
- Ts = states.Ts = Fs/Rs; % symbol period in samples
- states.M = M; % mFSK, either 2 or 4
- bpsym = state.Rb = log2(M); % bits per symbol over channel
- rate = states.rate = 0.5; % Manchester code rate
- nbits = 100;
- nbits = states.nbits = 100; % number of payload data symbols/frame
- nbits2 = states.nbits2 = nbits/rate; % number of symbols/frame over channel after manchester encoding
- nsym = states.nsym = nbits2/log2(M); % number of symbols per frame
- nsam = states.nsam = nsym*Ts;
-
- %printf(" Rs: %d M: %d bpsym: %d nbits: %d nbits2: %d nsym: %d nsam: %d\n", Rs, M, bpsym, nbits, nbits2, nsym, nsam);
-
- states.fc = states.Fs/4;
- if states.M == 2
- states.f(1) = states.fc - Rs/2;
- states.f(2) = states.fc + Rs/2;
- else
- states.f(1) = states.fc - 3*Rs/2;
- states.f(2) = states.fc - Rs/2;
- states.f(3) = states.fc + Rs/2;
- states.f(4) = states.fc + 3*Rs/2;
- end
-endfunction
-
-
-% test modulator function
-
-function tx = legacyfsk_mod(states, tx_bits)
- Fs = states.Fs;
- Ts = states.Ts;
- Rs = states.Rs;
- f = states.f;
- M = states.M;
- nsym = states.nsym;
-
- tx = zeros(Ts*length(tx_bits)/log2(M),1);
- tx_phase = 0;
-
- step = log2(M);
- k = 1;
- for i=1:step:length(tx_bits)
- if M == 2
- tone = tx_bits(i) + 1;
- else
- tone = (tx_bits(i:i+1) * [2 1]') + 1;
- end
- tx_phase_vec = tx_phase + (1:Ts)*2*pi*f(tone)/Fs;
- tx((k-1)*Ts+1:k*Ts) = 2.0*cos(tx_phase_vec); k++;
- tx_phase = tx_phase_vec(Ts) - floor(tx_phase_vec(Ts)/(2*pi))*2*pi;
- end
-
-endfunction
-
-
-function run_sim(sim_in)
-
- frames = sim_in.frames;
- test_frame_mode = sim_in.test_frame_mode;
- M = sim_in.M;
- Rs = sim_in.Rs;
- demod = sim_in.demod;
- EbNodB = sim_in.EbNodB;
- timing_offset = sim_in.timing_offset;
-
- % rx timing has been adjusted experimentally
-
- if Rs == 4800
- if demod == 1
- rx_timing = 4;
- else
- rx_timing = 0;
- end
- end
- if Rs == 2400
- if demod == 1
- rx_timing = 40;
- else
- rx_timing = 0;
- end
- end
-
- % init fsk modem
-
- more off
- rand('state',1);
- randn('state',1);
- states = legacyfsk_init(M,Rs);
- Fs = states.Fs;
- nbits = states.nbits;
- nbits2 = states.nbits2;
- Ts = states.Ts;
- nsam = states.nsam;
- rate = states.rate;
-
- % init analog FM modem
-
- fm_states.Fs = Fs;
- fm_max = fm_states.fm_max = 3E3;
- fd = fm_states.fd = 5E3;
- fm_states.fc = states.fc;
-
- fm_states.pre_emp = 0;
- fm_states.de_emp = 1;
- fm_states.Ts = 1;
- fm_states.output_filter = 1;
- fm_states = analog_fm_init(fm_states);
- [b, a] = cheby1(4, 1, 300/Fs, 'high'); % 300Hz HPF to simulate FM radios
-
- % init sim states
-
- rx_bits_buf = zeros(1,2*nbits2);
- Terrs = Tbits = 0;
- state = 0;
- nerr_log = [];
-
- % set up the channel noise. We have log(M)*rate payload bits/symbol
- % we have log2(M) bits/symbol, and rate bits per payload symbol
- % TODO: explain this better as Im confused!
-
- EbNo = 10^(EbNodB/10);
- EsNo = EbNo*rate*log2(M);
- variance = states.Fs/((states.Rs)*EsNo);
- %printf("EbNodB: %3.1f EbNo: %3.2f EsNo: %3.2f\n", EbNodB, EbNo, EsNo);
-
- % set up the input bits
-
- if test_frame_mode == 1
- % test frame of bits, which we repeat for convenience when BER testing
- test_frame = round(rand(1, nbits));
- tx_bits = [];
- for i=1:frames+1
- tx_bits = [tx_bits test_frame];
- end
- end
- if test_frame_mode == 2
- % random bits, just to make sure sync algs work on random data
- tx_bits = round(rand(1, nbits*(frames+1)));
- end
- if test_frame_mode == 3
- % ...10101... sequence
- tx_bits = zeros(1, nbits*(frames+1));
- tx_bits(1:2:length(tx_bits)) = 1;
- end
-
- % Manchester Encoding -----------------------------------------------------------
-
- % Manchester encoding, which removes DC term in baseband signal,
- % making the waveform friendly to old-school legacy FM radios with
- % voiceband filtering. The "code rate" is 0.5, which means we have
- % encode one input bit into 2 output bits. The 2FSK encoder takes
- % one input bit, the 4FSK encoder two input bits.
-
- tx_bits_encoded = zeros(1,length(tx_bits)*2);
- fsk2_enc = [[1 0]; [0 1]];
- % -1.5 1.5 1.5 -1.5 -0.5 0.5 0.5 -0.5
- % 0 3 3 0 1 2 2 1
- fsk4_enc = [[0 0 1 1]; [1 1 0 0]; [0 1 1 0]; [1 0 0 1]];
- k=1;
- if M == 2
- for i=1:2:length(tx_bits_encoded)
- input_bit = tx_bits(k); k++;
- tx_bits_encoded(i:i+1) = fsk2_enc(input_bit+1,:);
- end
- else
- for i=1:4:length(tx_bits_encoded)
- input_bits = tx_bits(k:k+1) * [2 1]'; k+=2;
- tx_bits_encoded(i:i+3) = fsk4_enc(input_bits+1,:);
- end
- end
-
- % FSK Modulator --------------------------------------------------------------
-
- % use ideal FSK modulator (note: need to try using analog FM modulator)
-
- tx = legacyfsk_mod(states, tx_bits_encoded);
- noise = sqrt(variance)*randn(length(tx),1);
- rx = tx + noise;
- timing_offset_samples = round(timing_offset*Ts);
- rx = [zeros(timing_offset_samples,1); rx];
-
- % Demodulator ----------------------------------------------------------------------------
-
- if demod == 1
- % use analog FM demodulator, aka a $40 Baofeng
-
- [rx_out rx_bb] = analog_fm_demod(fm_states, rx');
- if sim_in.hpf
- rx_out_hp = filter(b,a,rx_out);
- else
- rx_out_hp = rx_out;
- end
- rx_filt = filter(ones(1,Ts),1,rx_out_hp);
- rx_timing_sig = rx_filt;
-
- % TODO: for 4FSK determine amplitude/decn boundaries, choose closest to demod each symbol
-
- end
-
- if demod == 2
-
- % optimal non-coherent demod at Rs
-
- rx_timing_sig = zeros(1,length(rx));
- for m=1:M
- phi_vec = (1:length(rx))*2*pi*states.f(m)/Fs;
- dc = rx' .* exp(-j*phi_vec);
- rx_filt(m,:) = abs(filter(ones(1,Ts),1,dc));
- rx_timing_sig = rx_timing_sig + rx_filt(m,1:length(rx));
- end
- end
-
- % Fine timing estimation ------------------------------------------------------
-
- % Estimate fine timing using line at Rs/2 that Manchester encoding provides
- % We need this to sync up to Manchester codewords. TODO plot signal and
- % timing "line" we extract
-
- Np = length(rx_timing_sig);
- w = 2*pi*(Rs)/Fs;
- x = (rx_timing_sig .^ 2) * exp(-j*w*(0:Np-1))';
- norm_rx_timing = angle(x)/(2*pi) - 0.42;
- %rx_timing = round(norm_rx_timing*Ts);
- %printf("norm_rx_timing: %4.4f rx_timing: %d\n", norm_rx_timing, rx_timing);
-
- % Max likelihood decoding of Manchester encoded symbols. Search
- % through all ML possibilities to extract bits. Use energy (filter
- % output sq)
-
- % Manchester Decoding --------------------------------------------------------
-
- if M == 2
- if demod == 1
-
- % sample at optimum instant
-
- [tmp l] = size(rx_filt);
- rx_filt_dec = rx_filt(:, Ts+rx_timing:Ts:l);
-
- [tmp l] = size(rx_filt_dec);
- rx_bits = zeros(1,l);
- k = 1;
- for i=1:2:l-1
- ml = [rx_filt_dec(i)-rx_filt_dec(i+1) -rx_filt_dec(i)+rx_filt_dec(i+1)];
- [mx mx_ind] = max(ml);
- rx_bits(k) = mx_ind-1; k++;
- end
- end
-
- if demod == 2
-
- % sample at optimum instant
-
- [tmp l] = size(rx_filt);
- rx_filt_dec = rx_filt(:, Ts+rx_timing:Ts:l);
-
- [tmp l] = size(rx_filt_dec);
- rx_bits = zeros(1,l);
- k = 1;
- for i=1:2:l-1
- %ml = [rx_filt_dec(2,i)*rx_filt_dec(1,i+1) rx_filt_dec(1,i)*rx_filt_dec(2,i+1)];
- ml = [rx_filt_dec(2,i)+rx_filt_dec(1,i+1) rx_filt_dec(1,i)+rx_filt_dec(2,i+1)];
- [mx mx_ind] = max(ml);
- rx_bits(k) = mx_ind-1; k++;
- end
- end
- else % M == 4
- if demod == 1
- % TODO: 4FSK version of demod
- rx_bits=tx_bits;
- end
- if demod == 2
- % sample at optimal instant
-
- [tmp l] = size(rx_filt);
- rx_filt_dec = rx_filt(:, Ts+rx_timing:Ts:l);
- [tmp l] = size(rx_filt_dec);
- rx_bits = zeros(1,l);
-
- k = 1;
- fsk4_dec = [[0 0]; [0 1]; [1 0]; [1 1]];
- for i=1:2:l-1
- %ml = [rx_filt_dec(1,i)*rx_filt_dec(4,i+1) rx_filt_dec(4,i)*rx_filt_dec(1,i+1) rx_filt_dec(2,i)*rx_filt_dec(3,i+1) rx_filt_dec(3,i)*rx_filt_dec(2,i+1)];
- ml = [(rx_filt_dec(1,i)+rx_filt_dec(4,i+1)) (rx_filt_dec(4,i)+rx_filt_dec(1,i+1)) (rx_filt_dec(2,i)+rx_filt_dec(3,i+1)) (rx_filt_dec(3,i)+rx_filt_dec(2,i+1))];
- [mx mx_ind] = max(ml);
- rx_bits(k:k+1) = fsk4_dec(mx_ind,:); k+=2;
- end
- end
- end
-
- % useful for getting decoding right
- %tx_bits(1:20)
- %rx_bits(1:20)
-
- % Frame sync and BER logic -------------------------------------------------------------
-
- st = 1;
- for f=1:frames
-
- % extract nin bits
-
- nin = nbits;
- en = st + nin - 1;
-
- rx_bits_buf(1:nbits) = rx_bits_buf(nbits+1:2*nbits);
- rx_bits_buf(nbits+1:2*nbits) = rx_bits(st:en);
-
- st += nin;
-
- % frame sync based on min BER
-
- if test_frame_mode == 1
- nerrs_min = nbits;
- next_state = state;
- if state == 0
- for i=1:nbits
- error_positions = xor(rx_bits_buf(i:nbits+i-1), test_frame);
- nerrs = sum(error_positions);
- %printf("i: %d nerrs: %d nerrs_min: %d \n", i, nerrs, nerrs_min);
- if nerrs < nerrs_min
- nerrs_min = nerrs;
- coarse_offset = i;
- end
- end
- if nerrs_min < 3
- next_state = 1;
- %printf("%d %d\n", coarse_offset, nerrs_min);
- end
- end
-
- if state == 1
- error_positions = xor(rx_bits_buf(coarse_offset:coarse_offset+nbits-1), test_frame);
- nerrs = sum(error_positions);
- Terrs += nerrs;
- Tbits += nbits;
- nerr_log = [nerr_log nerrs];
- end
-
- state = next_state;
-
- end
- end
-
- if test_frame_mode == 1
- if sim_in.verbose
- printf(" demod: %d frames: %d EbNodB: %3.1f Tbits: %d Terrs: %d BER %4.3f\n", demod, frames, EbNodB, Tbits, Terrs, Terrs/Tbits);
- else
- printf(" EbNodB: %3.1f BER %4.3f\n", EbNodB, Terrs/Tbits);
- end
- end
-
- % Bunch O'plots --------------------------------------------------------------
-
- close all;
-
- st = 1; en=20;
-
- Tx=fft(tx, Fs);
- TxdB = 20*log10(abs(Tx(1:Fs/2)));
- figure(1)
- clf;
- plot(TxdB)
- axis([1 Fs/2 (max(TxdB)-100) max(TxdB)])
- title('Tx Spectrum');
-
- figure(2)
- clf
- if demod == 1
- subplot(211)
- plot(rx_filt(st*Ts:en*Ts));
- title('After integrator');
- subplot(212)
- plot(rx_filt_dec(st:en),'+');
- title('Decimated output');
- end
- if demod == 2
- subplot(211);
- plot(rx_filt(1,st*Ts:en*Ts));
- hold on;
- plot(rx_filt(2,st*Ts:en*Ts),'g');
- if M == 4
- plot(rx_filt(3,st*Ts:en*Ts),'c');
- plot(rx_filt(4,st*Ts:en*Ts),'r');
- end
- hold off;
- title('Output of each filter');
- subplot(212);
- plot(rx_filt_dec(1,st:en),'+');
- hold on;
- plot(rx_filt_dec(2,st:en),'g+');
- if M == 4
- plot(rx_filt_dec(3,st:en),'c+');
- plot(rx_filt_dec(4,st:en),'r+');
- end
- hold off;
- title('Decimated output of each filter');
- end
-
- figure(3)
- clf;
- subplot(211)
- plot(rx_timing_sig(st*Ts:en*Ts).^2)
- title('rx-timing-sig')
- subplot(212)
- F = abs(fft(rx_timing_sig(1:Fs)));
- plot(F(100:8000))
- title('FFT of rx-timing-sig')
-
- if demod == 1
- figure(4);
- clf;
- h = fft(rx_out, Fs);
- hdB = 20*log10(abs(h));
- plot(hdB(1:4000))
- title('Spectrum of baseband modem signal after analog FM demod');
- axis([1 4000 (max(hdB)-40) max(hdB)])
- end
-
- if demod == 1
- figure(5)
- clf;
- subplot(211)
- plot(rx_out(st*Ts:en*Ts));
- title('baseband modem signal after analog FM demod');
- subplot(212)
- plot(rx_out_hp(st*Ts:en*Ts));
- title('baseband modem signal after 300Hz filter');
- end
-end
-
-
-% Run various permutations of simulation here ---------------------------------------
-
-function run_single
-
- sim_in.frames = 100;
- sim_in.test_frame_mode = 1;
- sim_in.M = 2;
- sim_in.Rs = 2400;
- sim_in.demod = 1;
- sim_in.EbNodB = 15;
- sim_in.timing_offset = 0.0;
- sim_in.hpf = 1;
- sim_in.verbose = 1;
-
- run_sim(sim_in);
-endfunction
-
-
-function run_lots
-
- % adjusted a few scenarios for about 2% BER so we can compare
-
- sim_in.frames = 100;
- sim_in.test_frame_mode = 1;
- sim_in.M = 2;
- sim_in.Rs = 4800;
- sim_in.demod = 1;
- sim_in.EbNodB = 12;
- sim_in.timing_offset = 0.0;
- sim_in.hpf = 1;
- sim_in.verbose = 0;
-
- printf("Rs=4800 2FSK ideal demod\n");
- sim_in.EbNodB = 8.5; sim_in.demod = 2; run_sim(sim_in);
- printf("Rs=4800 2FSK analog FM demod, not too shabby and pushes 2400bit/s thru a $40 HT!\n");
- sim_in.EbNodB = 12; sim_in.demod = 1; run_sim(sim_in);
- printf("Rs=2400 2FSK analog FM demod, needs more power for same BER! Che?\n");
- sim_in.Rs = 2400; sim_in.EbNodB = 15; run_sim(sim_in);
- printf("Hmm, doesn't improve with no 300Hz HPF, maybe due to less deviation?\n");
- sim_in.hpf = 0; run_sim(sim_in);
- printf("Rs=2400 4FSK ideal demod, nice low Eb/No!\n");
- sim_in.demod = 2; sim_in.M = 4; sim_in.Rs = 2400; sim_in.EbNodB = 6; run_sim(sim_in);
-endfunction
-
-%run_single;
-run_lots;
diff --git a/octave/mfsk.m b/octave/mfsk.m
deleted file mode 100644
index 0414b5e..0000000
--- a/octave/mfsk.m
+++ /dev/null
@@ -1,199 +0,0 @@
-% mfsk.m
-% David Rowe Nov 2015
-
-% Simulation to test m=2 and m=4 FSK demod
-
-
-1;
-
-function sim_out = fsk_ber_test(sim_in)
- Fs = 96000;
- M = sim_in.M;
- Rs = sim_in.Rs;
- Ts = Fs/Rs;
- verbose = sim_in.verbose;
-
- nbits = sim_in.nbits;
- nsym = sim_in.nbits*2/M;
- nsam = nsym*Ts;
- EsNodB = sim_in.EbNodB + 10*log10(M/2);
-
- % printf("M: %d nbits: %d nsym: %d\n", M, nbits, nsym);
-
- if M == 2
- f(1) = -Rs/2;
- f(2) = Rs/2;
- end
- if M == 4
- f(1) = -3*Rs/2;
- f(2) = -Rs/2;
- f(3) = Rs/2;
- f(4) = 3*Rs/2;
- end
-
- % simulate over a range of Eb/No values
-
- for ne = 1:length(EsNodB)
- Nerrs = Terrs = Tbits = 0;
-
- aEsNodB = EsNodB(ne);
- EsNo = 10^(aEsNodB/10);
- variance = Fs/(Rs*EsNo);
-
- % Modulator -------------------------------
-
- tx_bits = round(rand(1, nbits));
- tx = zeros(1,nsam);
- tx_phase = 0;
-
- for i=1:nsym
- if M == 2
- tone = tx_bits(i) + 1;
- else
- tone = (tx_bits(2*(i-1)+1:2*i) * [2 1]') + 1;
- end
-
- tx_phase_vec = tx_phase + (1:Ts)*2*pi*f(tone)/Fs;
- tx((i-1)*Ts+1:i*Ts) = exp(j*tx_phase_vec);
- tx_phase = tx_phase_vec(Ts) - floor(tx_phase_vec(Ts)/(2*pi))*2*pi;
- end
-
- % Channel ---------------------------------
-
- % We use complex (single sided) channel simulation, as it's convenient
- % for the FM simulation.
-
- noise = sqrt(variance/2)*(randn(1,nsam) + j*randn(1,nsam));
- rx = tx + noise;
- if verbose > 1
- printf("EbNo: %f Eb: %f var No: %f EbNo (meas): %f\n",
- EbNo, var(tx)*Ts/Fs, var(noise)/Fs, (var(tx)*Ts/Fs)/(var(noise)/Fs));
- end
-
- % Demodulator -----------------------------
-
- % non-coherent FSK demod
-
- rx_bb = rx;
- dc = zeros(M,nsam);
- for m=1:M
- dc(m,:) = rx_bb .* exp(-j*(0:nsam-1)*2*pi*f(m)/Fs);
- end
-
- rx_bits = zeros(1, nsym);
- for i=1:nsym
- st = (i-1)*Ts+1;
- en = st+Ts-1;
- for m=1:M
- int(m,i) = abs(sum(dc(m,st:en)));
- end
- if m == 2
- rx_bits(i) = int(1,i) < int(2,i);
- else
- [max_amp tone] = max([int(1,i) int(2,i) int(3,i) int(4,i)]);
- if tone == 1
- rx_bits(2*(i-1)+1:2*i) = [0 0];
- end
- if tone == 2
- rx_bits(2*(i-1)+1:2*i) = [0 1];
- end
- if tone == 3
- rx_bits(2*(i-1)+1:2*i) = [1 0];
- end
- if tone == 4
- rx_bits(2*(i-1)+1:2*i) = [1 1];
- end
- end
- end
-
- error_positions = xor(rx_bits, tx_bits);
- Nerrs = sum(error_positions);
- Terrs += Nerrs;
- Tbits += length(error_positions);
-
- TERvec(ne) = Terrs;
- BERvec(ne) = Terrs/Tbits;
-
- if verbose > 1
- figure(2)
- clf
- Rx = 10*log10(abs(fft(rx)));
- plot(Rx(1:Fs/2));
- axis([1 Fs/2 0 50]);
-
- figure(3)
- clf;
- subplot(211)
- plot(real(rx_bb(1:Ts*20)))
- subplot(212)
- Rx_bb = 10*log10(abs(fft(rx_bb)));
- plot(Rx_bb(1:3000));
- axis([1 3000 0 50]);
-
- figure(4);
- subplot(211)
- stem(abs(mark_int(1:100)));
- subplot(212)
- stem(abs(space_int(1:100)));
- end
-
- if verbose
- printf("EbNo (db): %3.2f Terrs: %d BER: %4.3f \n", aEsNodB - 10*log10(M/2), Terrs, Terrs/Tbits);
- end
- end
-
- sim_out.TERvec = TERvec;
- sim_out.BERvec = BERvec;
-endfunction
-
-
-function run_fsk_curves
- sim_in.M = 2;
- sim_in.Rs = 1200;
- sim_in.nbits = 12000;
- sim_in.EbNodB = 0:2:20;
- sim_in.verbose = 1;
-
- EbNo = 10 .^ (sim_in.EbNodB/10);
- fsk_theory.BERvec = 0.5*exp(-EbNo/2); % non-coherent BFSK demod
- fsk2_sim = fsk_ber_test(sim_in);
-
- sim_in.M = 4;
- fsk4_sim = fsk_ber_test(sim_in);
-
- % BER v Eb/No curves
-
- figure(1);
- clf;
- semilogy(sim_in.EbNodB, fsk_theory.BERvec,'r;2FSK theory;')
- hold on;
- semilogy(sim_in.EbNodB, fsk2_sim.BERvec,'g;2FSK sim;')
- semilogy(sim_in.EbNodB, fsk4_sim.BERvec,'b;4FSK sim;')
- hold off;
- grid("minor");
- axis([min(sim_in.EbNodB) max(sim_in.EbNodB) 1E-4 1])
- legend("boxoff");
- xlabel("Eb/No (dB)");
- ylabel("Bit Error Rate (BER)")
-
-end
-
-
-function run_fsk_single
- sim_in.M = 4;
- sim_in.Rs = 1200;
- sim_in.nbits = 5000;
- sim_in.EbNodB = 8;
- sim_in.verbose = 1;
-
- fsk_sim = fsk_ber_test(sim_in);
-endfunction
-
-
-rand('state',1);
-randn('state',1);
-graphics_toolkit ("gnuplot");
-
-run_fsk_curves
-%run_fsk_single
-
diff --git a/octave/newamp1_fbf.m b/octave/newamp1_fbf.m
deleted file mode 100644
index 69111c6..0000000
--- a/octave/newamp1_fbf.m
+++ /dev/null
@@ -1,144 +0,0 @@
-% newamp1_fbf.m
-%
-% Copyright David Rowe 2016
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Interactive Octave script to explore frame by frame operation of newamp1
-% spectral amplitude modelling.
-%
-% Usage:
-% Make sure codec2-dev is compiled with the -DDUMP option - see README for
-% instructions.
-% ~/codec2-dev/build_linux/src$ ./c2sim ../../raw/hts1a.raw --dump hts1a
-% $ cd ~/codec2-dev/octave
-% octave:14> newamp1_fbf("../build_linux/src/hts1a",50)
-
-
-function newamp1_fbf(samname, f=73, varargin)
- more off;
-
- newamp_700c; melvq;
- load train_120_1.txt; load train_120_2.txt;
- train_120_vq(:,:,1)= train_120_1; train_120_vq(:,:,2)= train_120_2; m=5;
-
- Fs = 8000; K = 20;
-
- vq = 0; eq_en = 0; pf = 0;
-
- % load up text files dumped from c2sim ---------------------------------------
-
- sn_name = strcat(samname,"_sn.txt");
- Sn = load(sn_name);
- sw_name = strcat(samname,"_sw.txt");
- Sw = load(sw_name);
- model_name = strcat(samname,"_model.txt");
- model = load(model_name);
- [frames tmp] = size(model);
-
- % pre-process
- [rate_K_surface sample_freqs_kHz] = resample_const_rate_f_mel(model(1:frames,:), K);
-
- % we need to know eq states on each frame
- eq = zeros(frames,K); an_eq = zeros(1,K);
- for ff=1:frames
- mean_f = mean(rate_K_surface(ff,:));
- rate_K_vec_no_mean = rate_K_surface(ff,:) - mean_f;
- [tmp an_eq] = front_eq(rate_K_vec_no_mean, an_eq);
- eq(ff,:) = an_eq;
- end
-
- % Keyboard loop --------------------------------------------------------------
-
- k = ' ';
- do
- fg = 1;
- s = [ Sn(2*f-1,:) Sn(2*f,:) ];
- figure(fg++); clf; plot(s); axis([1 length(s) -20000 20000]);
-
- Wo = model(f,1); L = model(f,2); Am = model(f,3:(L+2)); AmdB = 20*log10(Am);
- Am_freqs_kHz = (1:L)*Wo*4/pi;
-
- % plots ----------------------------------
-
- figure(fg++); clf;
- l = sprintf(";rate %d AmdB;g+-", L);
- plot((1:L)*Wo*4000/pi, AmdB, l);
- axis([1 4000 -20 80]);
- hold on;
- stem(sample_freqs_kHz*1000, rate_K_surface(f,:), ";rate K;b+-");
-
- % default
- rate_K_vec_ = rate_K_surface(f,:);
-
- mean_f = mean(rate_K_surface(f,:));
- rate_K_vec_no_mean = rate_K_surface(f,:) - mean_f;
- if eq_en
- rate_K_vec_no_mean -= eq(f,:);
- end
- rate_K_vec_no_mean_ = rate_K_vec_no_mean;
- if vq
- [res rate_K_vec_no_mean_ ind] = mbest(train_120_vq, rate_K_vec_no_mean, m);
- if pf
- rate_K_vec_no_mean_ = post_filter(rate_K_vec_no_mean_, sample_freqs_kHz, 1.5);
- end
- rate_K_vec_ = rate_K_vec_no_mean_ + mean_f;
- end
-
- % back to rate L
- model_(f,:) = resample_rate_L(model(f,:), rate_K_vec_, sample_freqs_kHz);
- Am_ = model_(f,3:(L+2)); AmdB_ = 20*log10(Am_);
- varL = var(AmdB - AmdB_);
-
- plot((1:L)*Wo*4000/pi, AmdB_,";AmdB bar;r+-");
- l = sprintf(";error var %3.2f dB;bk+-", varL);
- plot((1:L)*Wo*4000/pi, (AmdB - AmdB_), l);
- hold off;
-
- figure(3); clf;
- plot(sample_freqs_kHz*1000, 40+ rate_K_vec_no_mean, ";rate K no mean;g+-");
- axis([1 4000 -20 80]); hold on;
- plot(sample_freqs_kHz*1000, 40 + rate_K_vec_no_mean_, ";rate K no mean bar;r+-");
- varK = var(rate_K_vec_no_mean - rate_K_vec_no_mean_);
- l = sprintf(";error var %3.2f dB;bk+-", varK);
- plot(sample_freqs_kHz*1000, rate_K_vec_no_mean - rate_K_vec_no_mean_, l);
-
- plot(sample_freqs_kHz*1000, eq(f,:), ";eq;b+-");
- hold off;
-
- % interactive menu ------------------------------------------
-
- printf("\rframe: %d menu: n-next b-back q-quit v-vq[%d] p-pf[%d] e-eq[%d]", f, vq, pf, eq_en);
- fflush(stdout);
- k = kbhit();
-
- if k == 'v'
- if vq == 0; vq = 1; else vq = 0; end
- endif
- if k == 'p'
- if pf == 0; pf = 1; else pf = 0; end
- endif
- if k == 'e'
- if eq_en == 0; eq_en = 1; else eq_en = 0; end
- endif
- if k == 'n'
- f = f + 1;
- endif
- if k == 'b'
- f = f - 1;
- endif
-
- until (k == 'q')
- printf("\n");
-
-endfunction
-
-
-function ind = arg_exists(v, str)
- ind = 0;
- for i=1:length(v)
- if !ind && strcmp(v{i}, str)
- ind = i;
- end
- end
-endfunction
diff --git a/octave/nf_from_gr.m b/octave/nf_from_gr.m
deleted file mode 100644
index bd36d02..0000000
--- a/octave/nf_from_gr.m
+++ /dev/null
@@ -1,129 +0,0 @@
-% nf_from_gr.m
-% David Rowe Mar 2016
-
-#{
- Calculate NF from GNU Radio output samples in
- ...IQIQ... (32 bit float) sample files
-
- 1/ Take one sample with a -100dBm input carrier
- 2/ Take another sample with no signal (just rx noise)
- 3/ Set Fs, adjust st and en to use a chunk of spectrum without too
- many birdies.
-
- Gotchas:
-
- 1/ Inspect Figure(1), the time domain plots.
- 2/ Make sure plenty of ADC bits are being used with the noise-only sample,
- we don't want ADC quantisation noise to dominate. Aim for about half
- full scale.
- 3/ Also watch out for clipping on either sample.
-
-#}
-
-1;
-
-function det_nf(p_filename, n_filename, title, Fs, st, en, Pin_dB, real_file=0)
-
- if real_file
- % real samples files of 16 bit shorts
- fs=fopen(p_filename,"rb");
- p = fread(fs,Inf,"short");
- fclose(fs);
- fs=fopen(n_filename,"rb");
- pn = fread(fs,Inf,"short");
- fclose(fs);
- else
- % GNU radio complex file input
- p = load_comp(p_filename);
- pn = load_comp(n_filename);
- end
-
- % skip any start up transients
-
- tst = floor(0.1*Fs); ten = st + Fs - 1;
- P = fft(p(tst:ten));
- N = fft(pn(tst:ten));
-
- PdB = 20*log10(abs(P));
- NdB = 20*log10(abs(N));
-
- figure(1); clf;
- subplot(211); plot(real(p(tst:tst+floor(Fs*0.1))));
- subplot(212); plot(real(pn(tst:tst+floor(Fs*0.1))));
-
- figure(2); clf;
- subplot(211); plot(st:en, PdB(st:en));
- subplot(212); plot(st:en, NdB(st:en));
-
- #{
- ------------------------------------------------------------------------
-
- From Wikipedia: The Noise Figure is the difference in decibels
- (dB) between the noise output of the actual receiver to the noise
- output of an “ideal” receiver
-
- An ideal receiver would have an output noise power of:
-
- Nout_dB = 10log10(B) -174 + G_dB
-
- The -174 dBm/Hz figure is the thermal noise density at 25C, for
- every 1Hz of bandwidth your will get -174dBm of noise power. It's
- the lower limit set by the laws of physics. G_dB is the Rx gain. The
- 10log10(B) term takes into account the bandwidth of the Rx. A wider
- bandwidth means more total noise power.
-
- So if you have a 1Hz bandwidth, and a gain of 100dB, you would
- expect Nout_NdB = 0 -174 + 100 = -74dBm at the rx output with no
- signal. If you have a 1000Hz bandwidth receiver you would have NdB_out
- = 20 -174 + 100 = -44dBm of noise power at the output.
-
- To determine Noise Figure:
- 1) Sample the Rx output first with a test signal and then with noise only.
- 2) Find the Rx gain using the test signal.
- 3) Find the noise output power, then using the gain we can find the noise
- input power.
- 4) Normalise the noise input power to 1Hz noise bandwidth and
- compare to the thermal noise floor.
-
- ----------------------------------------------------------------------------
- #}
-
- % variance is the power of a sampled signal
-
- Pout_dB = 10*log10(var(P(st:en))); % Rx output power with test signal
- G_dB = Pout_dB - Pin_dB; % Gain of Rx
- Nout_dB = 10*log10(var(N(st:en))); % Rx output power with noise
- Nin_dB = Nout_dB - G_dB; % Rx input power with noise
- No_dB = Nin_dB - 10*log10(en-st); % Rx input power with noise in 1Hz bandwidth
- NF_dB = No_dB + 174; % compare to thermal noise to get NF
- printf("%10s: Pin: %4.1f Pout: %4.1f G: %4.1f NF: %3.1f dB\n", title, Pin_dB, Pout_dB, G_dB, NF_dB);
-endfunction
-
-
-% HackRF --------------------------
-
-%p_filename = "~/Desktop/blogs/nf/hackrf_100dbm_4MHz.bin";
-%n_filename = "~/Desktop/blogs/nf/hackrf_nosignal_4MHz.bin";
-p_filename = "~/codec2-dev/build_linux/unittest/hackrf_100dbm_4MHz.bin";
-n_filename = "~/codec2-dev/build_linux/unittest/hackrf_nosignal_4MHz.bin";
-det_nf(p_filename, n_filename, "HackRF", 4E6, 180E3, 600E3, -100);
-
-#{
-% RTL-SDR --------------------------
-
-p_filename = "~/Desktop/nf/neg100dBm_2MHz.bin";
-n_filename = "~/Desktop/nf/nosignal_2MHz.bin";
-det_nf(p_filename, n_filename, "RTL-SDR", 2E6, 100E3, 300E3, -100);
-
-% AirSpy -------------------------
-
-p_filename = "~/Desktop/nf/airspy_100dbm_2.5MSPS.bin";
-n_filename = "~/Desktop/nf/airspy_nosig_2.5MSPS.bin";
-det_nf(p_filename, n_filename, "AirSpy", 2.5E6, 100E3, 300E3, -100);
-
-% Fun Cube Dongle Pro Plus -------------------------
-
-p_filename = "~/Desktop/nf/fcdpp_100dbm_192khz.bin";
-n_filename = "~/Desktop/nf/fcdpp_nosig_192khz.bin";
-det_nf(p_filename, n_filename, "FunCube PP", 192E3, 25E3, 125E3, -100);
-#}
diff --git a/octave/nf_from_stdio.m b/octave/nf_from_stdio.m
deleted file mode 100644
index e1d38f2..0000000
--- a/octave/nf_from_stdio.m
+++ /dev/null
@@ -1,133 +0,0 @@
-% nf_from_gr.m
-% David Rowe Mar 2018
-
-#{
-
- Calculate NF in real time from 16 bit real samples from stdin
-
- 1/ Using gqrx:
-
- gqrx setup:
- Configure I/O devices:
- To switch on LNA bias for HackRF, in Configure I/O devices menu set:
- Device String: hackrf,bias=1
- To switch on LNA bias for airspy run for a few seconds this before starting gqrx:
- $ airspy_rx -r /dev/null -f 435 -b 1
- I used a sample rate of 250000 for Airspy R2, 3000000 for Airspy Mini
- Input options...: start with set all gain sliders set to maximum
- FFT Setting.....: freq Zoom to max
- Receiver Options: On spectrum display, drag filter width until it's about 12k
- Filter Shape Normal
- Mode USB
- Tune until tone is between 2 and 4 k
- Press UDP button
-
- Then in a Linux Term:
-
- $ nc -ul 7355 | octave --no-gui -qf nf_from_stdio.m 48000
-
- 2/ Using command line tools. Compile airspy tools and csdr from source:
-
- a) Airspy:
-
- $ airspy_rx -a 6000000 -l 14 -m 15 -v 15 -r - -f 434.998 -b 1 | \
- csdr convert_s16_f | csdr fir_decimate_cc 50 | csdr convert_f_s16 | \
- octave --no-gui -qf ~/codec2-dev/octave/nf_from_stdio.m 120000 complex
-
- Note: we tuned a few kHz down to put the test tone in the 2000 to 4000 Hz range.
-
- b) HackRF:
-
- Term 1:
-
- $ ~/codec2-dev/octave$ nc -ul 7355 | octave --no-gui -qf nf_from_stdio.m 80000 complex
-
- Term 2:
-
- $ hackrf_transfer -r - -f 434995000 -s 4000000 -a 1 -p 1 -l 40 -g 32 | \
- csdr convert_s8_f | csdr fir_decimate_cc 50 | csdr convert_f_s16 | \
- nc localhost -u 7355
-
- Note: HackRF needed a bit of tuning to get test tone in 2000 to 4000 Hz range. This
- can be tricky with the command line method, easier with gqrx.
-
- c) rtlsdr (assuming sig gen set to 144.5MHz, -100dBm)
-
- Term 1:
-
- $ ./rtl_sdr -g 50 -s 2400000 -f 144.498E6 - | csdr convert_u8_f | csdr fir_decimate_cc 50 | \
- csdr convert_f_s16 | octave --no-gui -qf ~/codec2/octave/nf_from_stdio.m 48000 complex
-
- TODO:
- [ ] work out why noise power st bounces around so much, signal power seems stable
- [ ] reduce CPU load, in particular of plotting
-#}
-
-graphics_toolkit ("gnuplot")
-
-% command line arguments
-
-arg_list = argv ();
-if nargin == 0
- printf("\nusage: %s FsHz [real|complex] [testToneLeveldBm]\n\n", program_name());
- exit(0);
-end
-
-Fs = str2num(arg_list{1});
-shorts_per_sample = 1;
-
-if nargin == 2
- if strcmp(arg_list{2}, "real")
- shorts_per_sample = 1;
- end
- if strcmp(arg_list{2}, "complex")
- shorts_per_sample = 2;
- end
-end
-
-Pin_dB = -100; % level of input test tone
-if nargin == 3
- Pin_dB = str2num(arg_list{3});
-end
-
-printf("Fs: %d shorts_per_sample: %d Pin_dB: %f\n", Fs, shorts_per_sample, Pin_dB);
-
-[s,c] = fread(stdin, shorts_per_sample*Fs, "short");
-
-while c
- if shorts_per_sample == 2
- s = s(1:2:end)+j*s(2:2:end);
- end
- S = fft(s.*hanning(Fs));
- SdB = 20*log10(abs(S));
- figure(1); plot(real(s)); axis([0 Fs -4E4 4E4]);
- figure(2); plot(SdB); axis([0 12000 40 180]);
-
- % assume sine wave is between 2000 and 4000 Hz, and dominates energy in that
- % region. Noise is between 5000 - 10000 Hz
-
- sig_st = 2000; sig_en = 5000;
- noise_st = 6000; noise_en = 10000;
-
- % find peak and sum power a few bins either side, this ensure we don't capture
- % too much noise as well
-
- [pk pk_pos] = max(abs(S));
- if pk_pos > 5
- Pout_dB1 = 10*log10(sum(abs(S(pk_pos-5:pk_pos+5)).^2)); % Rx output power with test signal
- else
- Pout_dB1 = 0;
- end
-
- Pout_dB = 10*log10(sum(abs(S(sig_st:sig_en)).^2)); % Rx output power with test signal
- G_dB = Pout_dB - Pin_dB; % Gain of Rx
- Nout_dB = 10*log10(sum(abs(S(noise_st:noise_en)).^2)/(noise_en-noise_st)); % Rx output power with noise
- Nin_dB = Nout_dB - G_dB; % Rx input power with noise
- No_dB = Nin_dB; %- 10*log10(noise_en-noise_st); % Rx input power with noise in 1Hz bandwidth
- NF_dB = No_dB + 174; % compare to thermal noise to get NF
- printf("Pout: %4.1f %d %4.1f Nout: %4.1f G: %4.1f No: %4.1f NF: %3.1f dB\n", Pout_dB, pk_pos, Pout_dB1, Nout_dB, G_dB, No_dB, NF_dB);
-
- pause(2);
- [s,c] = fread(stdin, shorts_per_sample*Fs, "short");
-endwhile
-
diff --git a/octave/oqpsk.m b/octave/oqpsk.m
deleted file mode 100644
index f308617..0000000
--- a/octave/oqpsk.m
+++ /dev/null
@@ -1,521 +0,0 @@
-% oqpsk.m
-% David Rowe Jan 2017
-%
-% Unfiltered OQPSK modem implementation and simulations to test,
-% derived from GMSK modem in gmsk.m
-%
-% Usage: see "choose one of these to run" at the end of this file.
-
-rand('state',1);
-randn('state',1);
-graphics_toolkit ("gnuplot");
-format
-more off;
-
-% init modem states
-
-function oqpsk_states = oqpsk_init(oqpsk_states, Rs)
-
- % general
-
- verbose = oqpsk_states.verbose;
- oqpsk_states.Fs = 4*Rs;
- oqpsk_states.Rs = Rs;
- oqpsk_states.bps = 2; % two bit/symbol for QPSK
-
- M = oqpsk_states.M = oqpsk_states.Fs/oqpsk_states.Rs;
- assert(floor(M) == M, "oversampling factor M must be an integer");
- assert(floor(M/2) == M/2, "(oversampling factor M)/2 must be an integer to offset QPSK");
-endfunction
-
-
-% Gray coded QPSK modulation function
-
-function symbol = qpsk_mod(two_bits)
- two_bits_decimal = sum(two_bits .* [2 1]);
- switch(two_bits_decimal)
- case (0) symbol = 1;
- case (1) symbol = j;
- case (2) symbol = -j;
- case (3) symbol = -1;
- endswitch
-endfunction
-
-
-% Gray coded QPSK demodulation function
-
-function two_bits = qpsk_demod(symbol)
- if isscalar(symbol) == 0
- printf("only works with scalars\n");
- return;
- end
- bit0 = real(symbol*exp(j*pi/4)) < 0;
- bit1 = imag(symbol*exp(j*pi/4)) < 0;
- two_bits = [bit1 bit0];
-endfunction
-
-
-% Unfiltered OQPSK modulator
-
-function [tx tx_symb] = oqpsk_mod(oqpsk_states, tx_bits)
- M = oqpsk_states.M;
- bps = oqpsk_states.bps;
- nsym = length(tx_bits)/bps;
- nsam = nsym*M;
- verbose = oqpsk_states.verbose;
-
- % Map bits to Gray coded QPSK symbols
-
- tx_symb = zeros(1,nsym);
-
- for i=1:nsym
- tx_symb(i) = qpsk_mod(tx_bits(2*i-1:2*i))*exp(j*pi/4);
- end
-
- % Oversample by M (sample and hold) to create unfiltered QPSK
-
- tx = zeros(1, nsam);
- for i=1:nsym
- tx((i-1)*M+1:(i*M)) = tx_symb(i);
- end
-
- % delay Q arm by half of a symbol to make OQPSK
-
- tx = [real(tx) zeros(1,M/2)] + j*[zeros(1,M/2) imag(tx)];
-endfunction
-
-
-#{
-
- Unfiltered OQPSK demodulator function, with (optional) phase and
- timing estimation. Adapted from Fig 8 of [1]. See also gmsk.m and
- [2].
-
- Note demodulator returns phase corrected symbols sampled at ideal
- timing instant. These symbols may have a m*pi/2 phase ambiguity due
- to properties of phase tracking loop. The caller is responsible for
- determining this ambiguity and recovering the actual bits.
-
- [1] GMSK demodulator in IEEE Trans on Comms, Muroyta et al, 1981,
- "GSM Modulation for Digital Radio Telephony".
-
- [2] GMSK Modem Simulation, http://www.rowetel.com/?p=3824
-
-#}
-
-
-function [rx_symb rx_int filt_log dco_log timing_adj Toff] = oqpsk_demod(oqpsk_states, rx)
- M = oqpsk_states.M;
- Rs = oqpsk_states.Rs;
- Fs = oqpsk_states.Fs;
- nsam = length(rx);
- nsym = floor(nsam/M);
- verbose = oqpsk_states.verbose;
-
- timing_angle_log = zeros(1,length(rx));
- rx_int = zeros(1,length(rx));
- dco_log = filt_log = zeros(1,nsam);
-
- % Unfiltered PSK - integrate energy in symbols M long in re and im arms
-
- rx_int = conv(rx,ones(1,M))/M;
-
- % phase and fine frequency tracking and correction ------------------------
-
- if oqpsk_states.phase_est
-
- % DCO design from "Introduction To Phase-Lock Loop System Modeling", Wen Li
- % http://www.ece.ualberta.ca/~ee401/parts/data/PLLIntro.pdf
-
- eta = 0.707;
- wn = 2*pi*10*(Rs/4800); % (Rs/4800) -> found reducing the BW beneficial with falling Rs
- Ts = 1/Fs;
- g1 = 1 - exp(-2*eta*wn*Ts);
- g2 = 1 + exp(-2*eta*wn*Ts) - 2*exp(-eta*wn*Ts)*cos(wn*Ts*sqrt(1-eta*eta));
- Gpd = 2/pi;
- Gvco = 1;
- G1 = g1/(Gpd*Gvco); G2 = g2/(Gpd*Gvco);
- %printf("g1: %e g2: %e G1: %e G2: %e\n", g1, g2, G1, G2);
-
- filt_prev = dco = lower = ph_err_filt = ph_err = 0;
- end
-
- if oqpsk_states.timing_est
- % w is the ref sine wave at the timing clock frequency
- % tw is the length of the window used to estimate timing
-
- tw = 200*M;
- k = 1;
- xr_log = []; xi_log = [];
- w_log = [];
- timing_clock_phase = 0;
- timing_angle = 0;
- timing_angle_log = zeros(1,nsam);
- end
-
- % Sample by sample processing loop for timing and phase est. Note
- % this operates at sample rate Fs, unlike many PSK modems that
- % operate at the symbol rate Rs
-
- for i=1:nsam
-
- if oqpsk_states.timing_est
-
- % update sample timing estimate every tw samples, free wheel
- % rest of the time
-
- if mod(i,tw) == 0
- l = i - tw+1;
- xr = abs(real(rx_int(l:l+tw-1)));
- xi = abs(imag(rx_int(l:l+tw-1)));
- w = exp(j*(l:l+tw-1)*2*pi*Rs/Fs);
- X = xr * w';
- timing_clock_phase = timing_angle = angle(X);
- k++;
- xr_log = [xr_log xr];
- xi_log = [xi_log xi];
- w_log = [w_log w];
- else
- timing_clock_phase += (2*pi)/M;
- end
- timing_angle_log(i) = timing_angle;
- end
-
- if oqpsk_states.phase_est
-
- % PLL per-sample processing
-
- rx_int(i) *= exp(-j*dco);
- ph_err = sign(real(rx_int(i))*imag(rx_int(i)))*cos(timing_clock_phase);
- lower = ph_err*G2 + lower;
- filt = ph_err*G1 + lower;
- dco_log(i) = dco;
- dco = dco + filt;
- filt_log(i) = filt;
-
- end
-
- end
-
- % final adjustment of timing output to take into account slowly
- % moving estimates due to sample clock offset. Unwrap ensures that
- % when timing angle jumps from -pi to pi we move to the next symbol
- % and frame sync isn't broken
-
- timing_adj = timing_angle_log*M/(2*pi);
- timing_adj_uw = unwrap(timing_angle_log)*M/(2*pi);
- % Toff = floor(2*M+timing_adj);
- Toff = floor(timing_adj_uw+0.5);
-
- % sample integrator output at correct timing instant
-
- k = 1;
- re_syms = im_syms = zeros(1,nsym);
- rx_symb = [];
- for i=M:M:nsam
- if i-Toff(i)+M/2 <= nsam
- re_syms(k) = real(rx_int(i-Toff(i)));
- im_syms(k) = imag(rx_int(i-Toff(i)+M/2));
- %re_syms(k) = real(rx_int(i));
- %im_syms(k) = imag(rx_int(i));
- rx_symb = [rx_symb re_syms(k) + j*im_syms(k)];
- k++;
- end
- end
-
-endfunction
-
-
-% Test modem over a range Eb/No points in an AWGN channel. Can
-% simulate a variety of channel impairments and performs ambiguity
-% resolution.
-
-function sim_out = oqpsk_test(sim_in)
- bitspertestframe = sim_in.bitspertestframe;
- nbits = sim_in.nbits;
- EbNodB = sim_in.EbNodB;
- verbose = sim_in.verbose;
- Rs = 4800;
-
- oqpsk_states.verbose = verbose;
- oqpsk_states.coherent_demod = sim_in.coherent_demod;
- oqpsk_states.phase_est = sim_in.phase_est;
- oqpsk_states.timing_est = sim_in.timing_est;
- oqpsk_states = oqpsk_init(oqpsk_states, Rs);
- M = oqpsk_states.M;
- Fs = oqpsk_states.Fs;
- Rs = oqpsk_states.Rs;
- sample_clock_offset_ppm = sim_in.sample_clock_offset_ppm;
-
- tx_testframe = round(rand(1, bitspertestframe));
- ntestframes = floor(nbits/bitspertestframe);
- tx_bits = [];
- for i=1:ntestframes
- tx_bits = [tx_bits tx_testframe];
- end
-
- for ne = 1:length(EbNodB)
- aEbNodB = EbNodB(ne);
- EbNo = 10^(aEbNodB/10);
- variance = Fs/(Rs*EbNo*oqpsk_states.bps);
-
- [tx tx_symb] = oqpsk_mod(oqpsk_states, tx_bits);
- if sample_clock_offset_ppm
- tx = resample(tx, 1E6, 1E6-sample_clock_offset_ppm);
- end
- nsam = length(tx);
-
- phi = sim_in.phase_offset + 2*pi*sim_in.freq_offset*(1:nsam)/M;
-
- noise = sqrt(variance/2)*(randn(1,nsam) + j*randn(1,nsam));
- st = 1+sim_in.timing_offset; en = length(tx);
- rx = tx(st:en).*exp(j*phi(st:en)) + noise(st:en);
-
- [rx_symb rx_int filt_log dco_log timing_adj Toff] = oqpsk_demod(oqpsk_states, rx);
-
- % OK so the phase and timing estimators get us close (e.g. a good
- % scatter diagram), but no banana just yet. One problem is the
- % PLL can lock up on mulitples of pi/2. Combinations of phase
- % offsets can confuse the timing estimator. One tricky example is a
- % phase offset of pi/2 which swaps I & Q, and with OQPSK (unlike
- % MSK and friends) we can't easily tell which is I and which is Q
- % after a phase rotation, e.g. could be IQIQIQI or QIQIQIQ
-
- % So we need to determine the ambiguities:
- % a) could be m*pi/2 rotations of phase
- % b) could be I and Q swapped by timing est
- % c) time alignment of test frame
-
- nsymb = bitspertestframe/oqpsk_states.bps;
- nrx_symb = length(rx_symb);
- rx_bits = zeros(1, bitspertestframe);
- atx_symb = tx_symb(1:nsymb);
-
- % Treat I and Q as separate sequences, each with their own unique
- % word. In our case the UW is the whole test frame. Correlate rx
- % sequence with tx sequence at each possible offset through the
- % received symbols to find the test frames. Note we also
- % correlate I of tx with Q of rx to trap any IQ swaps.
-
- % The sign of the I and Q correlation lets us sort out the pi/2
- % phase rotation issue.
-
- nerrs_tot = 0; nbits_tot = 0;
-
- max_corr = real(atx_symb) * real(atx_symb)';
- for offset=2:nrx_symb-nsymb+1
- corr_ii(offset) = real(atx_symb) * real(rx_symb(offset:offset+nsymb-1))'/max_corr;
- corr_qq(offset) = imag(atx_symb) * imag(rx_symb(offset:offset+nsymb-1))'/max_corr;
- corr_iq(offset) = real(atx_symb) * imag(rx_symb(offset:offset+nsymb-1))'/max_corr;
- corr_qi(offset) = imag(atx_symb) * real(rx_symb(offset:offset+nsymb-1))'/max_corr;
- %printf("offset: %2d ii: % 5f qq: % 5f iq: % 5f qi: % 5f\n",
- %offset, corr_ii(offset), corr_qq(offset), corr_iq(offset), corr_qi(offset));
-
- if abs(corr_ii(offset)) > 0.8
-
- % no IQ swap, or time offset
-
- i_sign = sign(corr_ii(offset));
- q_sign = sign(corr_qq(offset));
- arx_symb = i_sign*real(rx_symb(offset:offset+nsymb-1)) + j*q_sign*imag(rx_symb(offset:offset+nsymb-1));
-
- for i=1:nsymb
- rx_bits(2*i-1:2*i) = qpsk_demod(arx_symb(i)*exp(-j*pi/4));
- end
- nerrs = sum(xor(tx_testframe, rx_bits));
- if verbose > 2
- printf("offset: %5d swap: %d i_sign: % 2.1f q_sign: % 2.1f nerr: %d\n",
- offset, 0, i_sign, q_sign, nerrs);
- end
- nerrs_tot += nerrs;
- nbits_tot += bitspertestframe;
- end
-
- if abs(corr_qi(offset)) > 0.8
-
- % IQ swap, I part in Q part of symbol before
-
- i_sign = sign(corr_iq(offset-1));
- q_sign = sign(corr_qi(offset));
- arx_symb = i_sign*imag(rx_symb(offset-1:offset+nsymb-2)) + j*q_sign*real(rx_symb(offset:offset+nsymb-1));
-
- for i=1:nsymb
- rx_bits(2*i-1:2*i) = qpsk_demod(arx_symb(i)*exp(-j*pi/4));
- end
- nerrs = sum(xor(tx_testframe, rx_bits));
- if verbose > 1
- printf("offset: %5d swap: %d i_sign: % 2.1f q_sign: % 2.1f nerr: %d\n",
- offset, 1, i_sign, q_sign, nerrs);
- end
- nerrs_tot += nerrs;
- nbits_tot += bitspertestframe;
- end
- end
-
- TERvec(ne) = nerrs_tot;
- BERvec(ne) = nerrs_tot/nbits_tot;
-
- if verbose > 0
- printf("EbNo dB: %3.1f Nbits: %d Nerrs: %d BER: %4.3f BER Theory: %4.3f\n",
- aEbNodB, nbits_tot, nerrs_tot, BERvec(ne), 0.5*erfc(sqrt(EbNo)));
- end
-
- if find(sim_in.plots == 1)
- figure(1); clf;
- subplot(211)
- stem(real(tx))
- title('Tx samples');
- ylabel('Inphase');
- subplot(212)
- stem(imag(tx))
- ylabel('Quadrature');
- end
-
- if find(sim_in.plots == 2)
- figure(2); clf;
- f = fftshift(fft(rx));
- Tx = 20*log10(abs(f));
- plot((1:length(f))*Fs/length(f) - Fs/2, Tx)
- grid;
- title('OQPSK Demodulator Input Spectrum');
- end
-
- if find(sim_in.plots == 3)
- figure(3); clf;
- nplot = min(16, nbits/oqpsk_states.bps);
- title('Rx Integrator');
- subplot(211)
- stem(real(rx_int(1:nplot*M)))
- axis([1 nplot*M -1 1])
- subplot(212)
- stem(imag(rx_int(1:nplot*M)))
- axis([1 nplot*M -1 1])
- end
-
- if find(sim_in.plots == 4)
- figure(4); clf;
- subplot(211);
- plot(filt_log);
- title('PLL filter')
- subplot(212);
- plot(dco_log);
- title('PLL DCO phase');
- end
-
- if find(sim_in.plots == 5)
- figure(5); clf;
- subplot(211)
- plot(timing_adj);
- title('Timing est');
- subplot(212)
- plot(Toff);
- title('Timing est unwrap');
- end
-
- if find(sim_in.plots == 6)
- figure(6); clf;
- st = floor(0.5*nrx_symb);
- plot(rx_symb(st:nrx_symb), '+');
- title('Scatter Diagram');
- axis([-1.5 1.5 -1.5 1.5])
- end
-
- if find(sim_in.plots == 7)
- figure(7); clf;
- subplot(211)
- plot(corr_ii);
- axis([1 length(corr_ii) -1.2 1.2]);
- title('corr ii');
- subplot(212)
- plot(corr_qi);
- axis([1 length(corr_ii) -1.2 1.2]);
- title('corr qi');
- end
-
- if find(sim_in.plots == 8)
- figure(8); clf;
- subplot(211);
- stem(real(arx_symb));
- title('Rx symbols')
- subplot(212);
- stem(imag(arx_symb));
- end
-
- if find(sim_in.plots == 9)
- figure(9); clf;
- subplot(211)
- stem(tx_testframe(1:min(20,length(rx_bits))))
- title('Tx Bits')
- subplot(212)
- stem(rx_bits(1:min(20,length(rx_bits))))
- title('Rx Bits')
- end
- end
-
- sim_out.TERvec = TERvec;
- sim_out.BERvec = BERvec;
- sim_out.Rs = oqpsk_states.Rs;
-endfunction
-
-
-function run_oqpsk_single
- sim_in.coherent_demod = 1;
- sim_in.phase_est = 1;
- sim_in.timing_est = 1;
- sim_in.bitspertestframe = 100;
- sim_in.nbits = 10000;
- sim_in.EbNodB = 4;
- sim_in.verbose = 1;
- sim_in.phase_offset = 3*pi/4; % in radians
- sim_in.timing_offset = 4; % in samples 0..M-1
- sim_in.freq_offset = 0.001; % fraction of Symbol Rate
- sim_in.plots = [1 2 4 5 6 7];
- sim_in.sample_clock_offset_ppm = 100;
-
- sim_out = oqpsk_test(sim_in);
-endfunction
-
-
-% Generate a bunch of BER versus Eb/No curves for various demods
-
-function run_oqpsk_curves
- sim_in.coherent_demod = 1;
- sim_in.EbNodB = 2:8;
- sim_in.verbose = 1;
- sim_in.phase_est = 1;
- sim_in.timing_est = 1;
- sim_in.bitspertestframe = 100;
- sim_in.nbits = 50000;
- sim_in.phase_offset = 3*pi/4; % in radians
- sim_in.timing_offset = 4; % in samples 0..M-1
- sim_in.freq_offset = 0.001; % fraction of Symbol Rate
- sim_in.plots = [];
- sim_in.sample_clock_offset_ppm = 0;
-
- oqpsk_coh = oqpsk_test(sim_in);
-
- Rs = oqpsk_coh.Rs;
- EbNo = 10 .^ (sim_in.EbNodB/10);
- oqpsk_theory.BERvec = 0.5*erfc(sqrt(EbNo));
-
- % BER v Eb/No curves
-
- figure;
- clf;
- semilogy(sim_in.EbNodB, oqpsk_theory.BERvec,'r+-;OQPSK theory;')
- hold on;
- semilogy(sim_in.EbNodB, oqpsk_coh.BERvec,'g+-;OQPSK sim;')
- hold off;
- grid("minor");
- axis([min(sim_in.EbNodB) max(sim_in.EbNodB) 1E-4 1])
- legend("boxoff");
- xlabel("Eb/No (dB)");
- ylabel("Bit Error Rate (BER)")
-endfunction
-
-
-% Choose one of these to run ------------------------------------------
-
-run_oqpsk_single
-%run_oqpsk_curves
-
diff --git a/octave/papr_test.m b/octave/papr_test.m
deleted file mode 100644
index 3785e25..0000000
--- a/octave/papr_test.m
+++ /dev/null
@@ -1,407 +0,0 @@
-% papr_test.m
-%
-% Experiments with PAPR reduction using clipping/compression
-%
-% OFDM Tx -> compress -> filter -> normalise power -> channel -> OFDM Rx
-
-#{
- TODO:
- [ ] option for normalised power after clipper
- [ ] experiment to plot those curves
-#}
-
-1;
-
-function symbol = qpsk_mod(two_bits)
- two_bits_decimal = sum(two_bits .* [2 1]);
- switch(two_bits_decimal)
- case (0) symbol = 1;
- case (1) symbol = j;
- case (2) symbol = -j;
- case (3) symbol = -1;
- endswitch
-endfunction
-
-function two_bits = qpsk_demod(symbol)
- bit0 = real(symbol*exp(j*pi/4)) < 0;
- bit1 = imag(symbol*exp(j*pi/4)) < 0;
- two_bits = [bit1 bit0];
-endfunction
-
-function papr = calc_papr(tx)
- papr = 10*log10(max(abs(tx).^2)/mean(abs(tx).^2));
-end
-
-% test PAPR calculation with a two tone signal of known PAPR (3dB)
-function test_papr
- f1=800; f2=1200; Fs=8000; n=(0:Fs-1);
- tx=exp(j*2*pi*n*f1/Fs) + exp(j*2*pi*n*f2/Fs);
- papr = calc_papr(tx);
- assert(abs(papr-3.0) < 0.05, 'test_papr() failed!')
-end
-
-% "Genie" OFDM modem simulation that assumes ideal sync
-
-function [ber papr] = run_sim(Nc, Nsym, EbNodB, channel='awgn', plot_en=0, filt_en=0, method="", threshold=1, norm_ebno=0)
- rand('seed',1);
- randn('seed',1);
-
- M = 160; % number of samples in each symbol
- bps = 2; % two bits per symbol for QPSK
- Ncp = 16; % cyclic prefix samples
- Fs = 8000;
-
- phase_est = 1; % perform phase estimation/correction
- timing = Ncp;
-
- if strcmp(method,"diversity")
- % total power of tx symbol after combination the same. Scatter plot positions
- % different but also twice as much noise (bandwidth)
- Nd = 2; gain = 1/sqrt(2);
- else
- Nd = 1; gain = 1.0;
- end
-
- if strcmp(channel,'multipath')
- dopplerSpreadHz = 1; path_delay = Ncp/2;
- Nsam = floor(Nsym*(M+Ncp)*1.1);
- spread1 = doppler_spread(dopplerSpreadHz, Fs, Nsam);
- spread2 = doppler_spread(dopplerSpreadHz, Fs, Nsam);
- end
-
- papr_log = [];
- for e=1:length(EbNodB)
- % generate a 2D array of QPSK symbols
-
- Nphases = 2^bps;
- tx_phases = pi/2*floor((rand(Nsym,Nc)*Nphases));
- if strcmp(method,"diversity")
- % duplicate carriers but with opposite phase
- tx_phases = [tx_phases (tx_phases-pi/2)];
- end
- tx_sym = gain*exp(j*tx_phases);
-
- % carrier frequencies, centre about 0
- st = floor(Nc*Nd/2);
- w = 2*pi/M*(-st:-st+Nc*Nd-1);
-
- % generate OFDM signal
-
- tx = [];
- for s=1:Nsym
- atx = zeros(1,M);
- for c=1:Nc*Nd
- atx += exp(j*(0:M-1)*w(c))*tx_sym(s,c);
- end
- % insert cyclic prefix and build up stream of time domain symbols
- % note CP costs us 10*log10((Ncp+M)/M) in Eb, as energy in CP isn't used for demodulation
- tx = [tx atx(end-Ncp+1:end) atx];
- end
- Nsam = length(tx);
-
- if strcmp(channel,'multipath')
- assert(length(spread1) >= Nsam);
- assert(length(spread2) >= Nsam);
- end
-
- % bunch of PAPR reduction options
- tx_ = tx;
-
- % determine threshold based on CDF
- cdf = empirical_cdf((1:Nc),abs(tx));
- if strcmp(method, "clip") || strcmp(method, "diversity") || strcmp(method, "compand")
- if threshold < 1
- threshold_level = find(cdf >= threshold)(1);
- else
- threshold_level = 10*Nc;
- end
-
- % printf("threshold: %f threshold_level: %f\n", threshold, threshold_level);
- end
-
- if strcmp(method, "clip") || strcmp(method, "diversity")
- ind = find(abs(tx) > threshold_level);
- tx_(ind) = threshold_level*exp(j*angle(tx(ind)));
- end
- if strcmp(method, "compand")
- # power law compander x = a*y^power, y = (x/a) ^ (1/power)
- power=2; a=threshold_level/(threshold_level^power);
- tx_mag = (abs(tx)/a) .^ (1/power);
- tx_ = tx_mag.*exp(j*angle(tx));
- end
-
- if filt_en
- Nfilt=80;
- b = fir1(Nfilt,2*Nc*Nd/M);
- tx_ = filter(b,1,[tx_ zeros(1,Nfilt/2)]);
- tx_ = [tx_(Nfilt/2+1:end)];
- end
-
- rx = tx_;
-
- % multipath channel
-
- if phase_est
- % estimate phase of each symbol before multipath simulation
-
- rx_phase1 = zeros(Nsym,Nc);
- for s=1:Nsym
- st = (s-1)*(M+Ncp)+1+timing; en = st+M-1;
- for c=1:Nc*Nd
- rx_phase1(s,c) = sum(exp(-j*(0:M-1)*w(c)) .* rx(st:en))/M;
- end
- end
- end
-
- if strcmp(channel,'multipath')
- rx = spread1(1:Nsam).*rx + spread2(1:Nsam).*[zeros(1,path_delay) rx(1:end-path_delay)];
- end
-
- % normalise power after multipath, so that Eb/No is set up
- % correctly
-
- if norm_ebno == 0
- norm = sqrt(mean(abs(tx_).^2)/mean(abs(rx).^2));
- else
- % normalise after clipper, this makes norm_pwr constant for all test
- % conditions
- norm = sqrt(mean(abs(tx).^2)/mean(abs(rx).^2));
- end
- rx *= norm;
- norm_pwr = 10*log10(mean(abs(rx).^2));
-
- if phase_est
- % auxiliary rx to get ideal phase ests on signal after multipath but before AWGN noise is added
-
- rx_phase = zeros(Nsym,Nc);
- for s=1:Nsym
- st = (s-1)*(M+Ncp)+1+timing; en = st+M-1;
- for c=1:Nc*Nd
- arx_sym = sum(exp(-j*(0:M-1)*w(c)) .* rx(st:en))/M;
- rx_phase(s,c) = arx_sym * conj(rx_phase1(s,c));
- end
- end
- rx_phase = exp(j*arg(rx_phase));
- end
-
- % AWGN channel
-
- EsNodB = EbNodB(e) + 10*log10(bps);
- variance = M/(10^(EsNodB/10));
- noise = sqrt(variance/2)*randn(1,Nsam) + j*sqrt(variance/2)*randn(1,Nsam);
- rx += noise;
-
- % demodulate
- rx_sym = zeros(Nsym,Nc);
- for s=1:Nsym
- st = (s-1)*(M+Ncp)+1+timing; en = st+M-1;
- for c=1:Nc*Nd
- rx_sym(s,c) = sum(exp(-j*(0:M-1)*w(c)) .* rx(st:en))/M;
- if phase_est rx_sym(s,c) *= conj(rx_phase(s,c)); end
- end
-
- if strcmp(method,"diversity")
- for c=1:Nc
- rx_sym(s,c) += rx_sym(s,c+Nc)*exp(j*pi/2);
- end
- end
- end
-
- % count bit errors
-
- Tbits = Terrs = 0; ErrPerSym = zeros(1,Nsym);
- for s=1:Nsym
- Nerrs = 0;
- for c=1:Nc
- tx_bits = qpsk_demod(tx_sym(s,c));
- rx_bits = qpsk_demod(rx_sym(s,c));
- Tbits += bps;
- Nerrs += sum(xor(tx_bits,rx_bits));
- end
- ErrPerSym(s) = Nerrs;
- Terrs += Nerrs;
- end
-
- if plot_en
- figure(1); clf;
- plot(abs(tx(1:5*M))); hold on; plot(abs(tx_(1:5*M))); hold off;
- axis([0 5*M 0 max(abs(tx))]);
- figure(2); clf; [hh nn] = hist(abs(tx),25,1);
- plotyy(nn,hh,1:Nc,cdf); title('PDF and CDF'); grid;
- figure(3); clf; plot(real(rx_sym(:,1:Nc)), imag(rx_sym(:,1:Nc)), '+'); axis([-2 2 -2 2]);
- figure(4); clf; Tx_ = 10*log10(abs(fft(tx_))); plot(fftshift(Tx_));
- mx = 10*ceil(max(Tx_)/10); axis([1 length(Tx_) mx-60 mx]);
- figure(5); plot_specgram(real(rx.*exp(j*2*pi*(0:Nsam-1)/4)));
- figure(6); clf; stem(ErrPerSym);
- end
-
- papr1 = calc_papr(tx);
- papr2 = calc_papr(tx_);
- papr_log = [papr_log papr2];
- ber(e) = Terrs/Tbits;
- printf("EbNodB: %4.1f %3.1f %4.1f PAPR: %5.2f %5.2f Tbits: %6d Terrs: %6d BER: %5.3f\n",
- EbNodB(e), norm, norm_pwr, papr1, papr2, Tbits, Terrs, ber(e))
- end
-
- papr = mean(papr_log);
-end
-
-% BER versus Eb/No curves -------------------------------------
-
-% first pass at trying out a few different schemes
-function curves_experiment1(Nc=8, channel='awgn', Nsym=1000, EbNodB=2:8)
-
- [ber1 papr1] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1);
- [ber2 papr2] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.8);
- [ber3 papr3] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.6);
- [ber4 papr4] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "compand", threshold=0.6);
- [ber5 papr5] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "diversity", threshold=0.6);
-
- figure(7); clf;
- semilogy(EbNodB, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB, ber2,sprintf('r+-;clip 0.8 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber3,sprintf('g+-;clip 0.6 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber4,sprintf('c+-;compand 0.6 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber5,sprintf('bk+-;diversity 0.6 %3.1f;',papr5),'markersize', 10, 'linewidth', 2);
- hold off;
- axis([min(EbNodB) max(EbNodB) 1E-3 1E-1]); grid;
- xlabel('Eb/No'); title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp1_%s_BER_EbNo.png", channel);
- print(fn,"-dpng");
-
- figure(8); clf;
- semilogy(EbNodB+papr1, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB+papr2, ber2,sprintf('r+-;clip 0.8 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr3, ber3,sprintf('g+-;clip 0.6 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr4, ber4,sprintf('c+-;compand 0.6 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr5, ber5,sprintf('bk+-;diversity 0.6 %3.1f;',papr5),'markersize', 10, 'linewidth', 2);
- hold off;
- xlabel('Peak Eb/No');
- axis([min(EbNodB)+papr2 max(EbNodB)+papr1 1E-3 1E-1]); grid; title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp1_%s_BER_peakEbNo.png", channel);
- print(fn,"-dpng");
-end
-
-
-% vary threshold and plot BER v Eb/No curves
-function curves_experiment2(Nc=8, channel='awgn', Nsym=1000, EbNodB=2:16)
-
- [ber1 papr1] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1);
- [ber2 papr2] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.8);
- [ber3 papr3] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.6);
- [ber4 papr4] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.4);
- [ber5 papr5] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.2);
- [ber6 papr6] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "diversity", threshold=0.8);
-
- figure(7); clf;
- semilogy(EbNodB, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB, ber2,sprintf('r+-;clip 0.8 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber3,sprintf('g+-;clip 0.6 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber4,sprintf('c+-;clip 0.4 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber5,sprintf('bk+-;clip 0.2 %3.1f;',papr5),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber6,sprintf('m+-;diversity 0.8 %3.1f;', papr6),'markersize', 10, 'linewidth', 2);
- hold off;
- axis([min(EbNodB) max(EbNodB) 1E-3 1E-1]); grid;
- xlabel('Eb/No'); title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp2_Nc%d_%s_BER_EbNo.png", Nc, channel);
- print(fn,"-dpng");
-
- figure(8); clf;
- semilogy(EbNodB+papr1, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB+papr2, ber2,sprintf('r+-;clip 0.8 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr3, ber3,sprintf('g+-;clip 0.6 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr4, ber4,sprintf('c+-;clip 0.4 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr5, ber5,sprintf('bk+-;clip 0.2 %3.1f;',papr5),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr6, ber6,sprintf('m+-;diversity 0.8 %3.1f;', papr6),'markersize', 10, 'linewidth', 2);
- hold off;
- xlabel('Peak Eb/No');
- axis([min(EbNodB)+papr2 max(EbNodB)+papr1 1E-3 1E-1]); grid; title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp2_Nc%d_%s_BER_peakEbNo.png", Nc, channel);
- print(fn,"-dpng");
-end
-
-% PAPR against number of carriers Nc
-function curves_experiment3(Nsym=3000)
-
- paper = zeros(1,32);
- Nc = 2:2:32;
- for i = 1:length(Nc)
- aNc = Nc(i);
- [aber apapr] = run_sim(aNc, Nsym, 100);
- papr(aNc) = apapr;
- end
-
- figure(9); clf;
- plot(Nc, papr(Nc)); xlabel('Number of Carriers Nc'); ylabel('PAPR (dB)'); grid;
- fn = sprintf("papr_exp3_Nc.png");
- print(fn,"-dpng");
-end
-
-% focus on diversity - vary threshold and plot BER v Eb/No curves
-function curves_experiment4(Nc=8, channel='multipath', Nsym=3000, EbNodB=2:2:16)
-
- [ber1 papr1] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1);
- [ber2 papr2] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "diversity", threshold=1);
- [ber3 papr3] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "diversity", threshold=0.8);
- [ber4 papr4] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "diversity", threshold=0.6);
-
- figure(7); clf;
- semilogy(EbNodB, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB, ber2,sprintf('r+-;diversity 1.0 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber3,sprintf('g+-;diversity 0.8 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber4,sprintf('c+-;diversity 0.6 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- hold off;
- axis([min(EbNodB) max(EbNodB) 1E-3 1E-1]); grid;
- xlabel('Eb/No'); title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp4_Nc%d_%s_BER_EbNo.png", Nc, channel);
- print(fn,"-dpng");
-
- figure(8); clf;
- semilogy(EbNodB+papr1, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB+papr2, ber2,sprintf('r+-;diversity 1.0 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr3, ber3,sprintf('g+-;diversity 0.8 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB+papr4, ber4,sprintf('c+-;diversity 0.6 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- hold off;
- xlabel('Peak Eb/No');
- axis([min(EbNodB)+papr4 max(EbNodB)+papr1 1E-3 1E-1]); grid; title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp4_Nc%d_%s_BER_peakEbNo.png", Nc, channel);
- print(fn,"-dpng");
-end
-
-% plot BER v Eb/No curves for clipping with normalised Eb/No after clipping
-function curves_experiment5(Nc=8, channel='awgn', Nsym=1000, EbNodB=2:10)
-
- [ber1 papr1] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "", threshold=1, norm=1);
- [ber2 papr2] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.8, norm=1);
- [ber3 papr3] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.6, norm=1);
- [ber4 papr4] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.4, norm=1);
- [ber5 papr5] = run_sim(Nc, Nsym, EbNodB, channel, 0, filt_en=1, "clip", threshold=0.2, norm=1);
-
- figure(7); clf;
- semilogy(EbNodB, ber1,sprintf('b+-;vanilla OFDM %3.1f;',papr1),'markersize', 10, 'linewidth', 2); hold on;
- semilogy(EbNodB, ber2,sprintf('r+-;clip 0.8 %3.1f;',papr2),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber3,sprintf('g+-;clip 0.6 %3.1f;',papr3),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber4,sprintf('c+-;clip 0.4 %3.1f;',papr4),'markersize', 10, 'linewidth', 2);
- semilogy(EbNodB, ber5,sprintf('bk+-;clip 0.2 %3.1f;',papr5),'markersize', 10, 'linewidth', 2);
- hold off;
- axis([min(EbNodB) max(EbNodB) 1E-3 1E-1]); grid;
- xlabel('Eb/No'); title(sprintf("%s Nc = %d", channel, Nc))
- fn = sprintf("papr_exp5_Nc%d_%s_BER_EbNo.png", Nc, channel);
- print(fn,"-dpng");
-end
-
-pkg load statistics;
-more off;
-
-test_papr;
-
-% single point with lots of plots -----------
-
-%run_sim(8, 1000, EbNo=100, channel='awgn', plot_en=1, filt_en=1);
-%run_sim(8, 8, EbNo=100, channel='awgn', plot_en=1, filt_en=1, "diversity", threshold=0.8);
-%run_sim(8, 1000, EbNo=10, channel='multipath', plot_en=1, filt_en=0, "diversity", threshold=5);
-%curves_experiment2(Nc=16, 'awgn', Nsym=1000);
-curves_experiment2(Nc=16,'multipath', Nsym=3000, EbNodB=2:2:16);
-%curves_experiment3()
-%curves_experiment4()
-%curves_experiment5(Nc=16)
diff --git a/octave/phase_noise.m b/octave/phase_noise.m
deleted file mode 100644
index 37e933c..0000000
--- a/octave/phase_noise.m
+++ /dev/null
@@ -1,72 +0,0 @@
-% phase_noise.m
-% David Nov 2019
-
-% Close-in look at phase noise. Feed in a off-air sample file of a
-% sine wave, extracts the phase noise contour and returns the Doppler
-% spreading function that can be used to model the channel in
-% simulations
-
-function spread_FsHz = phase_noise(file_name)
- Fs = 8000;
- s = load_raw(file_name);
- % skip past wave header
- s = [zeros(256,1); s(256:end)];
- S = abs(fft(s(1:Fs).*hanning(Fs)));
- [mx mx_bin] = max(S);
- ftone = mx_bin-1;
-
- figure(1); clf;
- plot(20*log10(S(1:Fs/2)))
- title('Input Spectrum');
-
- % downshift to baseband and LPF. We just want the sinusoid with as little
- % additive AWGN noise as possible
- sbb = s' .* exp(-j*(1:length(s))*2*pi*ftone/Fs);
- [b a] = cheby1(4, 1, 20/Fs);
- sbb_lpf = filter(b,a,sbb);
-
- spread_fsHz = sbb_lpf;
-
- % estimate and remove fine freq offset, and HF phase noise
-
- st = Fs; en = 20*Fs;
- phase = unwrap(angle(sbb_lpf(st:en)));
- fine_freq = mean(phase(2:end) - phase(1:end-1));
- sbb_lpf_fine = sbb_lpf .* exp(-j*(1:length(sbb_lpf))*fine_freq);
- phase = unwrap(angle(sbb_lpf_fine(st:en)));
-
- printf("length: %3.2fs freq: %5.1f\n", length(s)/Fs, ftone+fine_freq*Fs/(2*pi));
-
- figure(2); clf;
- plot3((st:en)/Fs, real(sbb_lpf_fine(st:en)),imag(sbb_lpf_fine(st:en)))
- title('Polar phase trajectory');
-
- figure(3); clf;
- S2 = fftshift(fft(sbb_lpf_fine(Fs:Fs*11)));
- [mx mx_bin] = max(abs(S2));
- S2dB = 20*log10(abs(S2));
- mxdB = 10*ceil(max(S2dB)/10);
- x = -10:0.1:10;
- plot(x,S2dB(mx_bin-100:mx_bin+100));
- axis([-10 10 mxdB-40 mxdB])
- title('Close in Phase Noise Spectrum');
- xlabel('Freq (Hz)');
- grid;
-
- figure(5); clf;
- t = (st:en)/Fs;
- plot(t, phase,'b;phase;');
- title('Unwrapped Phase');
- xlabel('Time (sec)')
- ylabel('Phase (radians)')
-
- figure(6); clf;
- beta = 0.00001;
- rate_of_change_Hz = filter(beta, [1 -(1-beta)],phase(2:end) - phase(1:end-1))*Fs/pi;
- plot(t(2:end), rate_of_change_Hz)
- title('Rate of change of phase (Hz)');
- xlabel('Time (sec)')
- ylabel('Freq (Hz)')
-
- spread_FsHz = sbb_lpf_fine/std(sbb_lpf_fine);
-end
diff --git a/octave/pitch_test.m b/octave/pitch_test.m
deleted file mode 100644
index 3fe0d1a..0000000
--- a/octave/pitch_test.m
+++ /dev/null
@@ -1,39 +0,0 @@
-% pitch_test.m
-% David Rowe Sep 2009
-% Constructs a sequence to test the pitch estimator
-
-function pitch_test(samname)
- M=320;
- F=200;
-
- fs=fopen(samname,"wb");
-
- f0 = 100;
- for f=1:200
- Wo=2*pi*f0/8000;
- P=2*pi/Wo;
- L = floor(pi/Wo);
- A = 10000/L;
- phi = zeros(1,L);
- s = zeros(1,M);
-
- for m=1:L
- s = s + A*cos(m*Wo*(0:(M-1)) + phi(m));
- endfor
-
- figure(1);
- clf;
- plot(s);
-
- fwrite(fs,s,"short");
-
- f0 = f0 + 5;
- if (f0 > 400)
- f0 = 100;
- endif
- endfor
-
- fclose(fs);
-
-endfunction
-
diff --git a/octave/pl.m b/octave/pl.m
deleted file mode 100644
index 0d54788..0000000
--- a/octave/pl.m
+++ /dev/null
@@ -1,45 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plots a raw speech sample file, you can optionally specify the start and end
-% samples and create a large and small PNGs
-
-function pl(samname1, start_sam, end_sam, pngname)
-
- fs=fopen(samname1,"rb");
- s=fread(fs,Inf,"short");
-
- st = 1;
- en = length(s);
- if (nargin >= 2)
- st = start_sam;
- endif
- if (nargin >= 3)
- en = end_sam;
- endif
-
- figure(1);
- clf;
- plot(s(st:en));
- axis([1 en-st 1.1*min(s) 1.1*max(s)]);
-
- if (nargin == 4)
-
- % small image
-
- __gnuplot_set__ terminal png size 420,300
- ss = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
- eval(ss)
- replot;
-
- % larger image
-
- __gnuplot_set__ terminal png size 800,600
- ss = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
- eval(ss)
- replot;
-
- endif
-
-endfunction
diff --git a/octave/pl2.m b/octave/pl2.m
deleted file mode 100644
index a25c6a2..0000000
--- a/octave/pl2.m
+++ /dev/null
@@ -1,44 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-
-function pl2(samname1, samname2, start_sam, end_sam, offset)
-
- fs1=fopen(samname1,"rb");
- s1=fread(fs1,Inf,"short");
- fs2=fopen(samname2,"rb");
- s2=fread(fs2,Inf,"short");
-
- st1 = st2 = 1;
- en1 = en2 = length(s1);
- if (nargin >= 3)
- st1 = st2 = start_sam;
- endif
- if (nargin >= 4)
- en1 = en2 = end_sam;
- endif
-
- if (nargin == 5)
- st2 += offset
- en2 += offset
- endif
-
- figure(1);
- clf;
- subplot(211);
- l1 = strcat("r;",samname1,";");
- plot(s1(st1:en1), l1); grid minor;
- axis([1 en1-st1 min(s1(st1:en1)) max(s1(st1:en1))]);
- subplot(212);
- l2 = strcat("r;",samname2,";");
- plot(s2(st2:en2),l2); grid minor;
- axis([1 en2-st2 min(s1(st2:en2)) max(s1(st2:en2))]);
-
- figure(2)
- plot(s1(st1:en1)-s2(st2:en2)); grid minor;
-
- f=fopen("diff.raw","wb");
- d = s1(st1:en1)-s2(st2:en2);
- fwrite(f,d,"short");
-
-endfunction
diff --git a/octave/plamp.m b/octave/plamp.m
deleted file mode 100644
index 1d575b8..0000000
--- a/octave/plamp.m
+++ /dev/null
@@ -1,135 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plot ampltiude modelling information from dump files.
-
-function plamp(samname, f, samname2)
-
- % switch some stuff off to unclutter display
-
- plot_sw = 0;
-
- sn_name = strcat(samname,"_sn.txt");
- Sn = load(sn_name);
-
- sw_name = strcat(samname,"_sw.txt");
- Sw = load(sw_name);
-
- sw__name = strcat(samname,"_sw_.txt");
- if (file_in_path(".",sw__name))
- Sw_ = load(sw__name);
- endif
-
- ew_name = strcat(samname,"_ew.txt");
- if (file_in_path(".",ew_name))
- Ew = load(ew_name);
- endif
-
- rk_name = strcat(samname,"_rk.txt");
- if (file_in_path(".",rk_name))
- Rk = load(rk_name);
- endif
-
- model_name = strcat(samname,"_model.txt");
- model = load(model_name);
-
- modelq_name = strcat(samname,"_qmodel.txt");
- if (file_in_path(".",modelq_name))
- modelq = load(modelq_name);
- endif
-
- pw_name = strcat(samname,"_pw.txt");
- if (file_in_path(".",pw_name))
- Pw = load(pw_name);
- endif
-
- lsp_name = strcat(samname,"_lsp.txt");
- if (file_in_path(".",lsp_name))
- lsp = load(lsp_name);
- endif
-
- phase_name = strcat(samname,"_phase.txt");
- if (file_in_path(".",phase_name))
- phase = load(phase_name);
- endif
-
- phase_name_ = strcat(samname,"_phase_.txt");
- if (file_in_path(".",phase_name_))
- phase_ = load(phase_name_);
- endif
-
- snr_name = strcat(samname,"_snr.txt");
- if (file_in_path(".",snr_name))
- snr = load(snr_name);
- endif
-
- % optional second file, for exploring post filter
-
- if nargin == 3
- model2_name = strcat(samname2,"_model.txt");
- model2 = load(model2_name);
- sn2_name = strcat(samname2,"_sn.txt");
- Sn2 = load(sn2_name);
-
- sw_name2 = strcat(samname2,"_sw.txt");
- Sw2 = load(sw_name2);
- end
-
- k = ' ';
- do
- figure(1);
- clf;
- s = [ Sn(2*f-1,:) Sn(2*f,:) ];
- plot(s,'b');
- if (nargin == 3)
- s2 = [ Sn2(2*f-1,:) Sn2(2*f,:) ];
- hold on; plot(s2,'r'); hold off;
- end
- axis([1 length(s) -30000 30000]);
-
- figure(2);
- Wo = model(f,1);
- L = model(f,2);
- Am = model(f,3:(L+2));
- plot((1:L)*Wo*4000/pi, 20*log10(Am),";Am;+-b");
- axis([1 4000 -10 80]);
- hold on;
- if plot_sw; plot((0:255)*4000/256, Sw(f,:),";Sw;b"); end
-
- if (nargin == 3)
- Wo2 = model2(f,1);
- L2 = model2(f,2);
- Am2 = model2(f,3:(L2+2));
- plot((1:L2)*Wo2*4000/pi, 20*log10(Am2),";Am2;+-r" );
- if plot_sw; plot((0:255)*4000/256, Sw2(f,:),";Sw2;r"); end
- endif
-
- hold off; grid minor;
-
- % interactive menu
-
- printf("\rframe: %d menu: n-next b-back p-png s-plot_sw q-quit", f);
- fflush(stdout);
- k = kbhit();
- if k == 'n'; f = f + 1; endif
- if k == 'b'; f = f - 1; endif
- if k == 's'
- if plot_sw; plot_sw = 0; else; plot_sw = 1; end
- endif
- % optional print to PNG
-
- if (k == 'p')
- figure(1);
- pngname = sprintf("%s_%d_sn.png",samname,f);
- print(pngname, '-dpng', "-S800,600")
-
- figure(2);
- pngname = sprintf("%s_%d_sw.png",samname,f);
- print(pngname, '-dpng', "-S800,600")
- endif
-
- until (k == 'q')
- printf("\n");
-
-endfunction
diff --git a/octave/plinterp.m b/octave/plinterp.m
deleted file mode 100644
index 794a085..0000000
--- a/octave/plinterp.m
+++ /dev/null
@@ -1,11 +0,0 @@
-load ../unittest/tinterp_prev.txt;
-load ../unittest/tinterp_interp.txt;
-load ../unittest/tinterp_next.txt;
-
-clf;
-plot(tinterp_prev(:,1), 20.0*log10(tinterp_prev(:,2)),";prev;")
-hold on;
-plot(tinterp_interp(:,1), 20.0*log10(tinterp_interp(:,2)),'g+-;interp;')
-plot(tinterp_next(:,1), 20.0*log10(tinterp_next(:,2)),'ro-;next;')
-hold off;
-axis([0 pi 0 80])
diff --git a/octave/pllpcpf.m b/octave/pllpcpf.m
deleted file mode 100644
index 924e045..0000000
--- a/octave/pllpcpf.m
+++ /dev/null
@@ -1,150 +0,0 @@
-% Copyright David Rowe 2012
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plot amplitude modelling information from dump files to test and develop
-% LPC post filter.
-
-function pllpcpf(samname, f)
-
- % switch some stuff off to unclutter display
-
- plot_Am = 0;
- plot_Amq = 0;
- plot_err = 0;
- plot_lsp = 0;
- plot_snr = 0;
- plot_vsnr = 0;
- plot_sw = 0;
- plot_pw = 1;
- plot_pwb = 1;
- plot_rw = 1;
-
- sn_name = strcat(samname,"_sn.txt");
- Sn = load(sn_name);
-
- sw_name = strcat(samname,"_sw.txt");
- Sw = load(sw_name);
-
- sw__name = strcat(samname,"_sw_.txt");
- if (file_in_path(".",sw__name))
- Sw_ = load(sw__name);
- endif
-
- model_name = strcat(samname,"_model.txt");
- model = load(model_name);
-
- modelq_name = strcat(samname,"_qmodel.txt");
- if (file_in_path(".",modelq_name))
- modelq = load(modelq_name);
- endif
-
- % Pw (LPC synth filter spectrum) before post filter
-
- pwb_name = strcat(samname,"_pwb.txt");
- if (file_in_path(".",pwb_name))
- Pwb = load(pwb_name);
- endif
-
- % Rw (Post filter spectrum)
-
- rw_name = strcat(samname,"_rw.txt");
- if (file_in_path(".",rw_name))
- Rw = load(rw_name);
- endif
-
- % Pw (LPC synth filter spectrum) after post filter
-
- pw_name = strcat(samname,"_pw.txt");
- if (file_in_path(".",pw_name))
- Pw = load(pw_name);
- endif
-
-
- Ew_on = 1;
- k = ' ';
- do
- figure(1);
- clf;
- s = [ Sn(2*f-1,:) Sn(2*f,:) ];
- size(s);
- plot(s);
- axis([1 length(s) -20000 20000]);
-
- figure(2);
- clf;
- Wo = model(f,1);
- L = model(f,2);
- Am = model(f,3:(L+2));
- if plot_Am
- plot((1:L)*Wo*4000/pi, 20*log10(Am),";Am;r");
- end
- axis([1 4000 -10 80]);
- hold on;
- if plot_sw
- plot((0:255)*4000/256, Sw(f,:),";Sw;");
- end
-
- if (file_in_path(".",modelq_name))
-
- Amq = modelq(f,3:(L+2));
- if plot_Amq
- plot((1:L)*Wo*4000/pi, 20*log10(Amq),";Amq;g" );
- end
-
- if (file_in_path(".",pwb_name) && plot_pwb)
- plot((0:255)*4000/256, 10*log10(Pwb(f,:)),";Pwb;r");
- endif
-
- if (file_in_path(".",rw_name) && plot_rw)
- plot((0:255)*4000/256, 10*log10(Rw(f,:)),";Rw;b");
- endif
-
- if (file_in_path(".",pw_name) && plot_pw)
- plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;g.");
- endif
-
- signal = Am * Am';
- noise = (Am-Amq) * (Am-Amq)';
- snr1 = 10*log10(signal/noise);
- Am_err_label = sprintf(";Am error SNR %4.2f dB;m",snr1);
- if plot_err
- plot((1:L)*Wo*4000/pi, 20*log10(Amq) - 20*log10(Am), Am_err_label);
- end
- endif
-
-
- hold off;
-
- % interactive menu
-
- printf("\rframe: %d menu: n-next b-back p-png q-quit", f);
- fflush(stdout);
- k = kbhit();
- if (k == 'n')
- f = f + 1;
- endif
- if (k == 'b')
- f = f - 1;
- endif
-
- % optional print to PNG
-
- if (k == 'p')
- figure(1);
- pngname = sprintf("%s_%d_sn.png",samname,f);
- print(pngname, '-dpng', "-S500,500")
- pngname = sprintf("%s_%d_sn_large.png",samname,f);
- print(pngname, '-dpng', "-S800,600")
-
- figure(2);
- pngname = sprintf("%s_%d_sw.png",samname,f);
- print(pngname, '-dpng', "-S500,500")
- pngname = sprintf("%s_%d_sw_large.png",samname,f);
- print(pngname, '-dpng', "-S1200,800")
- endif
-
- until (k == 'q')
- printf("\n");
-
-endfunction
diff --git a/octave/pllsp.m b/octave/pllsp.m
deleted file mode 100644
index 0606d3c..0000000
--- a/octave/pllsp.m
+++ /dev/null
@@ -1,46 +0,0 @@
-% Copyright David Rowe 2010
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plots a bunch of information related to LSP quantisation:
-% - speech file
-% - LSPs before and after quantisation
-% - SNR for each frame
-%
-% Note: there is a 160 sample (two frame delay) from the when a sample
-% enters the input buffer until it is at the centre of the analysis window
-
-function pllsp(rawfile,
- dumpfile_prefix_lpc_only,
- dumpfile_prefix_lsp,
- start_f, end_f)
-
- fs=fopen(rawfile,"rb");
- s=fread(fs,Inf,"short");
-
- lpc_snr_name = strcat(dumpfile_prefix_lpc_only,"_lpc_snr.txt");
- lpc10_snr = load(lpc_snr_name);
- lpc_snr_name = strcat(dumpfile_prefix_lsp,"_lpc_snr.txt");
- lsp_snr = load(lpc_snr_name);
-
- lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
- lsps = load(lsp_name);
- [m,n]=size(lsps);
- lsp = lsps(1:2:m,:);
- lsp_ = lsps(2:2:m,:);
-
- figure(1);
- clf;
- subplot(211);
- sp = s((start_f-2)*80:(end_f-2)*80);
- plot(sp);
-
- subplot(212);
- plot(lpc10_snr((start_f+1):end_f)-lsp_snr((start_f+1):end_f));
-
- figure(2);
- plot((4000/pi)*lsp((start_f+1):end_f,:));
- hold on;
- plot((4000/pi)*lsp_((start_f+1):end_f,:),'+-');
- hold off;
-endfunction
diff --git a/octave/pllspdt.m b/octave/pllspdt.m
deleted file mode 100644
index c711aa4..0000000
--- a/octave/pllspdt.m
+++ /dev/null
@@ -1,27 +0,0 @@
-% pllspdt.m
-% Copyright David Rowe 2010
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Test script to plot differences in LSps between frames
-
-function pllspdt(rawfile,dumpfile_prefix_lsp,lspn, start_f, end_f)
-
- fs=fopen(rawfile,"rb");
- s=fread(fs,Inf,"short");
-
- lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
- lsps = load(lsp_name);
- [m,n]=size(lsps);
- lsp = lsps(1:2:m,:);
- lsp_ = lsps(2:2:m,:);
- lspdt = lsp(2:m/2,:) - lsp(1:m/2-1,:);
-
- figure(1);
- clf;
- sp = s((start_f-2)*80:(end_f-2)*80);
- plot(sp);
-
- figure(2);
- plot((4000/pi)*lspdt((start_f+1):end_f,lspn));
-endfunction
diff --git a/octave/plnlp.m b/octave/plnlp.m
deleted file mode 100644
index 01b4931..0000000
--- a/octave/plnlp.m
+++ /dev/null
@@ -1,134 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plot NLP states from dump files.
-
-function plnlp(samname, f)
-
- sn_name = strcat(samname,"_sn.txt");
- Sn = load(sn_name);
-
- sw_name = strcat(samname,"_sw.txt");
- Sw = load(sw_name);
-
- fw_name = strcat(samname,"_fw.txt");
- if (file_in_path(".",fw_name))
- fw = load(fw_name);
- endif
-
- e_name = strcat(samname,"_e.txt");
- if (file_in_path(".",e_name))
- e = load(e_name);
- endif
-
- p_name = strcat(samname,".p");
- if (file_in_path(".",p_name))
- p = load(p_name);
- endif
-
- sq_name = strcat(samname,"_sq.txt");
- if (file_in_path(".",sq_name))
- sq = load(sq_name);
- endif
-
- dec_name = strcat(samname,"_dec.txt");
- if (file_in_path(".",dec_name))
- dec = load(dec_name);
- endif
-
- do
- figure(1);
- clf;
- s = [ Sn(2*f-1,:) Sn(2*f,:) ];
- plot(s, ";Sn;");
- grid
- axis([1 length(s) -20000 20000]);
-
- figure(2);
- plot((0:255)*4000/256, Sw(f,:),";Sw;");
- grid
- axis([1 4000 -10 80]);
- hold on;
-
- f0 = 8000/p(f);
- Wo = 2*pi/p(f);
- L = floor(pi/Wo);
- f0_label = sprintf("b;P=%3.1f F0=%3.0f;",p(f),f0);
- for m=1:L-1
- plot([ m*Wo*4000/pi m*Wo*4000/pi], [10 60], 'b');
- endfor
- plot([ L*Wo*4000/pi L*Wo*4000/pi], [10 60], f0_label);
-
- hold off;
-
- if (file_in_path(".",fw_name))
- figure(3);
- if (file_in_path(".",e_name))
- subplot(211);
- endif
- plot((0:255)*800/256, fw(f,:)/max(fw(f,:)), ";Fw;");
- axis([1 400 0 1]);
- if (file_in_path(".",e_name))
- subplot(212);
- e_concat = [ e(2*f-1,:) e(2*f,:) ];
- plot(e_concat(1:400)/max(e_concat(1:400)), "+;MBE E(f);");
- axis([1 400 0 1]);
- endif
- endif
-
- if (file_in_path(".",sq_name))
- figure(4);
- sq_concat = [ sq(2*f-1,:) sq(2*f,:) ];
- axis
- plot(sq_concat, ";sq;");
- endif
-
- if (file_in_path(".",dec_name))
- figure(5);
- plot(dec(f,:), ";dec;");
- endif
-
- figure(2);
-
- % interactive menu
-
- printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
- fflush(stdout);
- k = kbhit();
- if (k == 'n')
- f = f + 1;
- endif
- if (k == 'b')
- f = f - 1;
- endif
-
- % optional print to PNG
-
- if (k == 'p')
-
- pngname = sprintf("%s_%d",samname,f);
-
- % small image
-
- __gnuplot_set__ terminal png size 420,300
- ss = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
- eval(ss)
- replot;
-
- % larger image
-
- __gnuplot_set__ terminal png size 800,600
- ss = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
- eval(ss)
- replot;
-
- % for some reason I need this to stop large plot getting wiped
- __gnuplot_set__ output "/dev/null"
-
- endif
-
- until (k == 'q')
- printf("\n");
-
-endfunction
diff --git a/octave/plphase.m b/octave/plphase.m
deleted file mode 100644
index c12422e..0000000
--- a/octave/plphase.m
+++ /dev/null
@@ -1,198 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plot phase modelling information from dump files.
-
-function plphase(samname, f)
-
- sn_name = strcat(samname,"_sn.txt");
- Sn = load(sn_name);
-
- sw_name = strcat(samname,"_sw.txt");
- Sw = load(sw_name);
-
- model_name = strcat(samname,"_model.txt");
- model = load(model_name);
-
- sw__name = strcat(samname,"_sw_.txt");
- if (file_in_path(".",sw__name))
- Sw_ = load(sw__name);
- endif
-
- pw_name = strcat(samname,"_pw.txt");
- if (file_in_path(".",pw_name))
- Pw = load(pw_name);
- endif
-
- ak_name = strcat(samname,"_ak.txt");
- if (file_in_path(".",ak_name))
- ak = load(ak_name);
- endif
-
- phase_name = strcat(samname,"_phase.txt");
- if (file_in_path(".",phase_name))
- phase = load(phase_name);
- endif
-
- phase_name_ = strcat(samname,"_phase_.txt");
- if (file_in_path(".",phase_name_))
- phase_ = load(phase_name_);
- endif
-
- snr_name = strcat(samname,"_snr.txt");
- if (file_in_path(".",snr_name))
- snr = load(snr_name);
- endif
-
- sn_name_ = strcat(samname,".raw");
- if (file_in_path(".",sn_name_))
- fs_ = fopen(sn_name_,"rb");
- sn_ = fread(fs_,Inf,"short");
- endif
-
- k = ' ';
- do
- figure(1);
- clf;
- s = [ Sn(2*f-1,:) Sn(2*f,:) ];
- plot(s);
- grid;
- axis([1 length(s) -20000 20000]);
- if (k == 'p')
- pngname = sprintf("%s_%d_sn",samname,f);
- png(pngname);
- endif
-
- figure(2);
- Wo = model(f,1);
- L = model(f,2);
- Am = model(f,3:(L+2));
- plot((1:L)*Wo*4000/pi, 20*log10(Am),"r;Am;");
- axis([1 4000 -10 80]);
- hold on;
- plot((0:255)*4000/256, Sw(f,:),";Sw;");
- grid;
-
- if (file_in_path(".",sw__name))
- plot((0:255)*4000/256, Sw_(f,:),"g;Sw_;");
- endif
-
- if (file_in_path(".",pw_name))
- plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;");
- endif
-
- if (file_in_path(".",snr_name))
- snr_label = sprintf(";phase SNR %4.2f dB;",snr(f));
- plot(1,1,snr_label);
- endif
-
- % phase model - determine SNR and error spectrum for phase model 1
-
- if (file_in_path(".",phase_name_))
- orig = Am.*exp(j*phase(f,1:L));
- synth = Am.*exp(j*phase_(f,1:L));
- signal = orig * orig';
- noise = (orig-synth) * (orig-synth)';
- snr_phase = 10*log10(signal/noise);
-
- phase_err_label = sprintf("g;phase_err SNR %4.2f dB;",snr_phase);
- plot((1:L)*Wo*4000/pi, 20*log10(orig-synth), phase_err_label);
- endif
-
- hold off;
- if (k == 'p')
- pngname = sprintf("%s_%d_sw",samname,f);
- png(pngname);
- endif
-
- if (file_in_path(".",phase_name))
- figure(3);
- plot((1:L)*Wo*4000/pi, phase(f,1:L)*180/pi, "-o;phase;");
- axis;
- if (file_in_path(".", phase_name_))
- hold on;
- plot((1:L)*Wo*4000/pi, phase_(f,1:L)*180/pi, "g;phase after;");
- grid
- hold off;
- endif
- if (k == 'p')
- pngname = sprintf("%s_%d_phase",samname,f);
- png(pngname);
- endif
- endif
-
- % synthesised speech
-
- if (file_in_path(".",sn_name_))
- figure(4);
- s_ = sn_((f-3)*80+1:(f+1)*80);
- plot(s_);
- axis([1 length(s_) -20000 20000]);
- if (k == 'p')
- pngname = sprintf("%s_%d_sn_",samname,f)
- png(pngname);
- endif
- endif
-
- if (file_in_path(".",ak_name))
- figure(5);
- axis;
- akw = ak(f,:);
- weight = 1.0 .^ (0:length(akw)-1);
- akw = akw .* weight;
- H = 1./fft(akw,8000);
- subplot(211);
- plot(20*log10(abs(H(1:4000))),";LPC mag spec;");
- grid;
- subplot(212);
- plot(angle(H(1:4000))*180/pi,";LPC phase spec;");
- grid;
- if (k == 'p')
- % stops multimode errors from gnuplot, I know not why...
- figure(2);
- figure(5);
-
- pngname = sprintf("%s_%d_lpc",samname,f);
- png(pngname);
- endif
- endif
-
-
- % autocorrelation function to research voicing est
-
- %M = length(s);
- %sw = s .* hanning(M)';
- %for k=0:159
- % R(k+1) = sw(1:320-k) * sw(1+k:320)';
- %endfor
- %figure(4);
- %R_label = sprintf(";R(k) %3.2f;",max(R(20:159))/R(1));
- %plot(R/R(1),R_label);
- %grid
-
- figure(2);
-
- % interactive menu
-
- printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
- fflush(stdout);
- k = kbhit();
- if (k == 'n')
- f = f + 1;
- endif
- if (k == 'b')
- f = f - 1;
- endif
-
- % optional print to PNG
-
- if (k == 'p')
- pngname = sprintf("%s_%d",samname,f);
- png(pngname);
- endif
-
- until (k == 'q')
- printf("\n");
-
-endfunction
diff --git a/octave/plpitch.m b/octave/plpitch.m
deleted file mode 100644
index 69ad533..0000000
--- a/octave/plpitch.m
+++ /dev/null
@@ -1,36 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% plpitch.m
-% Plots two pitch tracks on top of each other, used for comparing pitch
-% estimators
-
-function plpitch(pitch1_name, pitch2_name, start_fr, end_fr)
-
- pitch1 = load(pitch1_name);
- pitch2 = load(pitch2_name);
-
- st = 1;
- en = length(pitch1);
- if (nargin >= 3)
- st = start_fr;
- endif
- if (nargin >= 4)
- en = end_fr;
- endif
-
- figure(1);
- clf;
- l1 = strcat("r;",pitch1_name,";")
- l1
- st
- en
- plot(pitch1(st:en), l1);
- axis([1 en-st 20 160]);
- l2 = strcat("g;",pitch2_name,";");
- hold on;
- plot(pitch2(st:en),l2);
- hold off;
-endfunction
-
diff --git a/octave/plvoicing.m b/octave/plvoicing.m
deleted file mode 100644
index a531747..0000000
--- a/octave/plvoicing.m
+++ /dev/null
@@ -1,89 +0,0 @@
-% Copyright David Rowe 2009
-% This program is distributed under the terms of the GNU General Public License
-% Version 2
-%
-% Plot voicing information from sample and dump files.
-%
-% samfilename is the raw source file, e.g. "../raw/hts1a.raw"
-% samname is the dumpfile prefix, e.g. "../src/hts1a"
-%
-% There is a 160 sample (two frame delay) from the when a sample
-% enters the input buffer until it is at the centre of the analysis window
-
-function plvoicing(samfilename, samname, start_f, end_f, pngname)
-
- fs=fopen(samfilename,"rb");
- s=fread(fs,Inf,"short");
-
- snr_name = strcat(samname,"_snr.txt");
- snr = load(snr_name);
- model_name = strcat(samname,"_model.txt");
- model = load(model_name);
-
- Wo = model((start_f+1):end_f,1);
- F0 = Wo*4000/pi;
- dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
-
- % work out LP and HP energy
-
- for f=(start_f+1):end_f
- L = model(f,2);
- Am = model(f,3:(L+2));
- L2 = floor(L/2);
- elow = Am(1:L2) * Am(1:L2)';
- ehigh = Am(L2:L) * Am(L2:L)';
- erat(f-(start_f+1)+1) = 10*log10(elow/ehigh);
- endfor
-
- figure(1);
- clf;
- sp = s((start_f-2)*80:(end_f-2)*80);
- plot(sp);
- hold on;
- vhigh = snr((start_f+1):end_f) > 7;
- vlow = snr((start_f+1):end_f) > 4;
-
- % test correction based on erat
-
- vlowadj = vlow;
-
- for f=1:length(erat)-1
- if (vlow(f) == 0)
- if (erat(f) > 10)
- vlowadj(f) = 1;
- endif
- endif
- if (vlow(f) == 1)
- if (erat(f) < -10)
- vlowadj(f) = 0;
- endif
- if (abs(dF0(f)) > 15)
- vlowadj(f) = 0;
- endif
- endif
- endfor
-
- x = 1:(end_f-start_f);
- plot(x*80,snr((start_f+1):end_f)*1000,';SNRdB x 1000;g+');
- plot(x*80,-8000 + vhigh*2000,';7dB thresh;g');
- plot(x*80,-11000 + vlowadj*2000,';vlow with corr;g');
- plot(x*80,erat*1000,';elow/ehigh in dB;r');
- plot(x*80,-14000 + vlow*2000,';4dB thresh;r');
- hold off;
- grid
- if (nargin == 5)
- print(pngname, "-dpng", "-S500,500")
- endif
-
- figure(2)
- Wo = model((start_f+1):end_f,1);
- F0 = Wo*4000/pi;
- dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
- %plot(dF0,'+--')
- %hold on;
- %plot([ 1 length(dF0) ], [10 10] ,'r')
- %plot([ 1 length(dF0) ], [-10 -10] ,'r')
- %axis([1 length(dF0) -50 50])
- %hold off;
- plot(F0,'+--')
-endfunction
diff --git a/octave/power_from_stdio.m b/octave/power_from_stdio.m
deleted file mode 100644
index a4dbddc..0000000
--- a/octave/power_from_stdio.m
+++ /dev/null
@@ -1,27 +0,0 @@
-% power_from_gr.m
-% David Rowe June 2018
-%
-% Measure power of signal from stdio, used for SNR tests from analog radios
-
-#{
- $ rec -t raw -r 8000 -s -2 -c 1 - -q | octave --no-gui -qf power_from_stdio.m
-#}
-
-graphics_toolkit ("gnuplot")
-
-Fs = 48000; % sample rate in Hz
-shorts_per_sample = 1; % real samples
-
-[s,c] = fread(stdin, shorts_per_sample*Fs, "short");
-
-while c
- S = fft(s.*hanning(Fs));
- SdB = 20*log10(abs(S));
- figure(1); plot(real(s)); axis([0 Fs -3E4 3E4]);
- figure(2); plot(SdB); axis([0 12000 40 160]);
-
- printf("power: %f dB\n", 10*log10(var(s)));
- %pause(2);
- [s,c] = fread(stdin, shorts_per_sample*Fs, "short");
-endwhile
-
diff --git a/octave/pulse.m b/octave/pulse.m
deleted file mode 100644
index 223389e..0000000
--- a/octave/pulse.m
+++ /dev/null
@@ -1,37 +0,0 @@
-% pulse.m
-% David Rowe August 2009
-%
-% Experiments with human pulse perception for sinusoidal codecs
-
-function pulse(samname)
-
- A = 1000;
- K = 16000;
- N = 80;
- frames = K/N;
- s = zeros(1,K);
-
- for f=1:frames
- % lets try placing np random pulses in every frame
-
- P = 20 + (160-20)*rand(1,1);
- Wo = 2*pi/P;
- L = floor(pi/Wo);
- sf = zeros(1,N);
- for m=1:L/2:L
- pos = floor(rand(1,1)*N)+1;
- %pos = 50;
- for l=m:m+L/2-1
- sf = sf + A*cos(l*Wo*((f-1)*N+1:f*N) - pos*l*Wo);
- endfor
- endfor
- s((f-1)*N+1:f*N) = sf;
- endfor
-
- plot(s(1:250));
-
- fs=fopen(samname,"wb");
- fwrite(fs,s,"short");
- fclose(fs);
-endfunction
-
diff --git a/octave/save_array_c_header.m b/octave/save_array_c_header.m
deleted file mode 100644
index 1fd87bb..0000000
--- a/octave/save_array_c_header.m
+++ /dev/null
@@ -1,14 +0,0 @@
-% save_array_c_header.m
-%
-% David Rowe Sep 2015
-
-function save_array_c_header(array, array_name, filename)
- f=fopen(filename,"wt");
- fprintf(f,"/* Generated by save_array_c_header.m Octave function */\n\n");
- fprintf(f,"const float %s[]={\n", array_name);
- for m=1:length(array)-1
- fprintf(f," % .16f,\n",array(m));
- endfor
- fprintf(f," % .16f\n};\n",array(length(array)));
- fclose(f);
-endfunction
diff --git a/octave/save_comp.m b/octave/save_comp.m
deleted file mode 100644
index b8e663f..0000000
--- a/octave/save_comp.m
+++ /dev/null
@@ -1,12 +0,0 @@
-% save_comp.m
-% David Rowe Aug 2020
-
-function save_comp(fn, iq)
- l = length(iq);
- s = zeros(1,2*l);
- s(1:2:2*l) = real(iq);
- s(2:2:2*l) = imag(iq);
- fs=fopen(fn,"wb");
- s = fwrite(fs,s,"float32");
- fclose(fs);
-endfunction
diff --git a/octave/save_f32.m b/octave/save_f32.m
deleted file mode 100644
index 62214d4..0000000
--- a/octave/save_f32.m
+++ /dev/null
@@ -1,12 +0,0 @@
-% save_f32.m
-% David Rowe Sep 2021
-%
-% save a matrix to .f32 binary files in row-major order
-
-function save_f32(fn, m)
- f=fopen(fn,"wb");
- [r c] = size(m);
- mlinear = reshape(m', 1, r*c);
- fwrite(f, mlinear, 'float32');
- fclose(f);
-endfunction
diff --git a/octave/save_hackrf.m b/octave/save_hackrf.m
deleted file mode 100644
index 5dda704..0000000
--- a/octave/save_hackrf.m
+++ /dev/null
@@ -1,13 +0,0 @@
-% save_hackrf.m
-%
-% David Rowe Aug 2020
-
-function save_hackrf(fn,iq)
- l = length(iq);
- s = zeros(1,2*l);
- s(1:2:2*l) = real(iq);
- s(2:2:2*l) = imag(iq);
- fs = fopen(fn,"wb");
- fwrite(fs,s,"schar");
- fclose(fs);
-endfunction
diff --git a/octave/save_raw.m b/octave/save_raw.m
deleted file mode 100644
index 7f17277..0000000
--- a/octave/save_raw.m
+++ /dev/null
@@ -1,7 +0,0 @@
-% save_raw.m
-% David Rowe 9 Feb 2015
-
-function s = save_raw(fn,s)
- fs=fopen(fn,"wb");
- fwrite(fs,s,"short");
-endfunction
diff --git a/octave/snr_curves_plot.m b/octave/snr_curves_plot.m
deleted file mode 100644
index 8a2e234..0000000
--- a/octave/snr_curves_plot.m
+++ /dev/null
@@ -1,262 +0,0 @@
-% snr_curves_plot.m
-%
-% Companion script for unittest/raw_data_curves
-
-1;
-
-function state_vec = set_graphics_state_print()
- textfontsize = get(0,"defaulttextfontsize");
- linewidth = get(0,"defaultlinelinewidth");
- markersize = get(0, "defaultlinemarkersize");
- set(0, "defaulttextfontsize", 16);
- set(0, "defaultaxesfontsize", 16);
- set(0, "defaultlinelinewidth", 1);
- state_vec = [textfontsize linewidth markersize];
-endfunction
-
-function set_graphics_state_screen(state_vec)
- textfontsize = state_vec(1);
- linewidth = state_vec(2);
- markersize = state_vec(3);
- set(0, "defaulttextfontsize", textfontsize);
- set(0, "defaultaxesfontsize", textfontsize);
- set(0, "defaultlinelinewidth", linewidth);
- set(0, "defaultlinemarkersize", markersize);
-endfunction
-
-function [snr_ch per] = snr_scatter(source, mode, channel, colour)
- suffix = sprintf("_%s_%s_%s",source, mode, channel);
- snr = load(sprintf("snr%s.txt",suffix));
- offset = load(sprintf("offset%s.txt",suffix));
- snr -= offset;
- snr_x = []; snrest_y = [];
- for i=1:length(snr)
- fn = sprintf('snrest%s_%d.txt',suffix,i);
- if exist(fn,'file') == 2
- snrest=load(fn);
- if i == length(snr)
- plot(snr(i)*ones(1,length(snrest)), snrest, sprintf('%s;%s %s;',colour,source,mode));
- else
- plot(snr(i)*ones(1,length(snrest)), snrest, sprintf('%s',colour));
- end
- snr_x = [snr_x snr(i)]; snrest_y = [snrest_y mean(snrest)];
- end
- end
- plot(snr_x, snrest_y, sprintf('%s', colour));
-endfunction
-
-function [snr_ch per] = per_snr(mode, colour)
- snrch = load(sprintf("snrch_%s.txt",mode));
- snroffset = load(sprintf("snroffset_%s.txt",mode));
- snrch -= snroffset;
- per = load(sprintf("per_%s.txt",mode));
- plot(snrch, per, sprintf('%so-;%s;', colour, mode));
-endfunction
-
-function snrest_snr_screen(source, channel)
- clf; hold on;
- snr_scatter(source, 'datac0', channel,'b+-')
- snr_scatter(source, 'datac1', channel,'g+-')
- snr_scatter(source, 'datac3', channel,'r+-')
- snr_scatter(source, 'datac4', channel,'c+-')
- snr_scatter(source, 'datac13', channel,'m+-')
- xlabel('SNR (dB)'); ylabel('SNRest (dB)'); grid('minor');
- axis([-12 12 -12 12]);
- a = axis;
- plot([a(1) a(2)],[a(1) a(2)],'bk-');
- hold off; grid;
- if strcmp(source,'ctx')
- title(sprintf('SNR estimate versus SNR (%s) (no compression)', channel));
- else
- title(sprintf('SNR estimate versus SNR (%s) (with compression)', channel));
- end
- legend('location','northwest');
-endfunction
-
-function snrest_snr_print(source, channel)
- state_vec = set_graphics_state_print();
- snrest_snr_screen(source, channel);
- print(sprintf("snrest_snr_%s.png", source), "-dpng", "-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-function ber_per_v_snr(source, mode, channel, colour)
- suffix = sprintf("_%s_%s_%s.txt",source, mode, channel);
- snr = load(sprintf("snr%s",suffix));
- offset = load(sprintf("offset%s",suffix));
- snr -= offset;
- ber = load(sprintf("ber%s",suffix)) + 1E-6;
- per = load(sprintf("per%s",suffix)) + 1E-6;
- semilogy(snr, ber, sprintf('%s;%s %s ber;', colour, source, mode));
- semilogy(snr, per, sprintf('%s;%s %s per;', colour, source, mode),'linewidth',3,'markersize',10);
-endfunction
-
-function per_v_snr(source, mode, channel, colour)
- suffix = sprintf("_%s_%s_%s.txt",source, mode, channel);
- snr = load(sprintf("snr%s",suffix));
- offset = load(sprintf("offset%s",suffix));
- snr -= offset;
- per = load(sprintf("per%s",suffix)) + 1E-6;
- if strcmp(channel,"awgn")
- semilogy(snr, per, sprintf('%s;%s %s;', colour, mode, channel));
- else
- semilogy(snr, per, sprintf('%s;%s %s;', colour, mode, channel),'linewidth',3,'markersize',10);
- end
-endfunction
-
-function thruput_v_snr(source, mode, channel, colour)
- suffix = sprintf("_%s_%s_%s.txt",source, mode, channel);
- snr = load(sprintf("snr%s",suffix));
- offset = load(sprintf("offset%s",suffix));
- snr -= offset;
- per = load(sprintf("per%s",suffix)) + 1E-6;
- if strcmp(mode,"datac0") Rb=291; end;
- if strcmp(mode,"datac1") Rb=980; end;
- if strcmp(mode,"datac3") Rb=321; end;
- if strcmp(mode,"datac4") Rb=87; end;
- if strcmp(mode,"datac13") Rb=65; end;
- if strcmp(channel,"awgn")
- plot(snr, Rb*(1-per), sprintf('%s;%s %s;', colour, mode, channel));
- else
- plot(snr, Rb*(1-per), sprintf('%s;%s %s;', colour, mode, channel),'linewidth',3,'markersize',10);
- end
-endfunction
-
-function octave_ch_noise_screen(channel)
- clf; hold on;
- ber_per_v_snr('oct','datac0',channel,'bo-')
- ber_per_v_snr('ch' ,'datac0',channel,'bx-')
- ber_per_v_snr('oct','datac1',channel,'go-')
- ber_per_v_snr('ch' ,'datac1',channel,'gx-')
- ber_per_v_snr('oct','datac3',channel,'ro-')
- ber_per_v_snr('ch' ,'datac3',channel,'rx-')
- xlabel('SNR (dB)'); grid;
- hold off;
- if strcmp(channel,"awgn")
- axis([-6 8 1E-3 1]);
- else
- axis([-2 12 1E-3 1]);
- end
- title(sprintf('Comparsion of Measuring SNR from Octave and ch tool (%s)', channel));
-endfunction
-
-function octave_ch_noise_print(channel)
- state_vec = set_graphics_state_print();
- octave_ch_noise_screen(channel);
- print(sprintf("octave_ch_noise_%s.png", channel), "-dpng","-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-function octave_c_tx_screen(channel)
- clf; hold on;
- ber_per_v_snr('oct','datac0',channel,'bo-')
- ber_per_v_snr('ctx','datac0',channel,'bx-')
- ber_per_v_snr('oct','datac1',channel,'go-')
- ber_per_v_snr('ctx','datac1',channel,'gx-')
- ber_per_v_snr('oct','datac3',channel,'ro-')
- ber_per_v_snr('ctx','datac3',channel,'rx-')
- xlabel('SNR (dB)'); grid;
- hold off;
- if strcmp(channel,"awgn")
- axis([-6 8 1E-3 1]);
- else
- axis([-2 12 1E-3 1]);
- end
- title(sprintf('Comparsion of Octave Tx and C Tx (no compression) (%s)', channel));
-endfunction
-
-function octave_c_tx_print(channel)
- state_vec = set_graphics_state_print();
- octave_c_tx_screen(channel);
- print(sprintf("octave_c_tx_%s.png", channel), "-dpng","-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-function octave_c_tx_comp_screen(channel)
- clf; hold on;
- ber_per_v_snr('oct','datac0',channel,'bo-')
- ber_per_v_snr('ctxc','datac0',channel,'bx-')
- ber_per_v_snr('oct','datac1',channel,'go-')
- ber_per_v_snr('ctxc','datac1',channel,'gx-')
- ber_per_v_snr('oct','datac3',channel,'ro-')
- ber_per_v_snr('ctxc','datac3',channel,'rx-')
- xlabel('SNR (dB)'); grid;
- hold off;
- if strcmp(channel,"awgn")
- axis([-6 8 1E-3 1]);
- else
- axis([-2 12 1E-3 1]);
- end
- title(sprintf('Comparsion of Octave Tx and C Tx (with compression) (%s)', channel));
-endfunction
-
-function octave_c_tx_comp_print(channel)
- state_vec = set_graphics_state_print();
- octave_c_tx_comp_screen(channel);
- print(sprintf("octave_c_tx_comp_%s.png", channel), "-dpng","-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-% composite AWGN and MPP for compressed
-function c_tx_comp_screen
- clf; hold on;
- per_v_snr('ctxc','datac0','awgn','bo-')
- per_v_snr('ctxc','datac1','awgn','go-')
- per_v_snr('ctxc','datac3','awgn','ro-')
- per_v_snr('ctxc','datac4','awgn','co-')
- per_v_snr('ctxc','datac13','awgn','mo-')
- per_v_snr('ctxc','datac0','mpp','bx-')
- per_v_snr('ctxc','datac1','mpp','gx-')
- per_v_snr('ctxc','datac3','mpp','rx-')
- per_v_snr('ctxc','datac4','mpp','cx-')
- per_v_snr('ctxc','datac13','mpp','mx-')
- xlabel('SNR (dB)'); ylabel('PER'); grid;
- hold off;
- axis([-10 10 1E-3 1]);
- title('PER of C Raw Data Modes (with compression)');
-endfunction
-
-function c_tx_comp_print;
- state_vec = set_graphics_state_print();
- c_tx_comp_screen;
- print("c_tx_comp.png", "-dpng","-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-function c_tx_comp_thruput_screen
- clf; hold on;
- thruput_v_snr('ctxc','datac0','awgn','bo-')
- thruput_v_snr('ctxc','datac1','awgn','go-')
- thruput_v_snr('ctxc','datac3','awgn','ro-')
- thruput_v_snr('ctxc','datac4','awgn','co-')
- thruput_v_snr('ctxc','datac13','awgn','mo-')
- thruput_v_snr('ctxc','datac0','mpp','bx-')
- thruput_v_snr('ctxc','datac1','mpp','gx-')
- thruput_v_snr('ctxc','datac3','mpp','rx-')
- thruput_v_snr('ctxc','datac4','mpp','cx-')
- thruput_v_snr('ctxc','datac13','mpp','mx-')
- xlabel('SNR (dB)'); ylabel('bits/s'); grid;
- hold off;
- axis([-10 10 0 1000]);
- title(' Throughput for C Tx (with compression)');
- legend('location','west');
-endfunction
-
-function c_tx_comp_thruput_print;
- state_vec = set_graphics_state_print;
- c_tx_comp_thruput_screen;
- print("c_tx_comp_thruput.png", "-dpng","-S1000,800");
- set_graphics_state_screen(state_vec);
-endfunction
-
-#{
-figure(1); octave_ch_noise_screen;
-figure(2); octave_c_tx_screen;
-figure(3); octave_c_tx_comp_screen
-figure(4); snrest_snr_screen;
-
-figure(5); octave_ch_noise_print;
-figure(6); octave_c_tx_print;
-figure(7); octave_c_tx_comp_print;
-figure(8); snrest_snr_print;
-#}
diff --git a/octave/tdetphase.m b/octave/tdetphase.m
deleted file mode 100644
index 8d7f96c..0000000
--- a/octave/tdetphase.m
+++ /dev/null
@@ -1,84 +0,0 @@
-% tdetphase.m
-% David Rowe August 2017
-%
-% Testing Hilbert Transform recover of phase from magnitude spectra
-
-newamp;
-Fs = 8000;
-
-w = 2*pi*500/Fs; gamma = 0.95
-ak = [1 -2*gamma*cos(w) gamma*gamma];
-Nfft = 512;
-
-% Test 1 - compare phase from freqz for 2nd order system (all pole filter)
-% - uses internal test of determine_phase()
-
-h = freqz(1,ak,Nfft/2);
-
-% note dummy_model not used, as determine_phase() is used in test mode
-
-L = 20; Wo = pi/(L+1);
-dummy_model = [Wo L ones(1,L)];
-phase = determine_phase(dummy_model, 1, Nfft, ak);
-
-fg = 1;
-figure(fg++); clf;
-subplot(211); plot(20*log10(abs(h))); title('test 1');
-subplot(212); plot(angle(h)); hold on; plot(phase(1:Nfft/2),'g'); hold off;
-
-% Test 2 - feed in harmonic magnitudes
-
-F0 = 100; Wo = 2*pi*F0/Fs; L = floor(pi/Wo);
-Am = zeros(1,L);
-for m=1:L
- b = round(m*Wo*Nfft/(2*pi));
- Am(m) = abs(h(b));
-end
-AmdB = 20*log10(Am);
-model = [Wo L Am];
-[phase Gdbfk s] = determine_phase(model, 1, Nfft);
-
-fftx = (1:Nfft/2)*(Fs/Nfft);
-harmx = (1:L)*Wo*Fs/(2*pi);
-
-figure(fg++); clf;
-subplot(211); plot(fftx, Gdbfk(1:Nfft/2));
-subplot(212); plot(s(1:Nfft/2))
-
-figure(fg++); clf;
-subplot(211); plot(fftx, 20*log10(abs(h)));
- hold on; plot(harmx, AmdB, 'g+'); plot(fftx, Gdbfk(1:Nfft/2), 'r'); hold off;
-subplot(212); plot(fftx, angle(h)); hold on; plot(fftx, phase(1:Nfft/2),'g'); hold off;
-
-% Test 3 - Use real harmonic amplitudes
-
-model = load("../build_linux/src/hts1a_model.txt");
-phase_orig = load("../build_linux/src/hts1a_phase.txt");
-
-f = 184;
-Wo = model(f,1); L = model(f,2); Am = model(f,3:L+2); AmdB = 20*log10(Am);
-[phase Gdbfk s] = determine_phase(model, f, Nfft);
-
-fftx = (1:Nfft/2)*(Fs/Nfft);
-harmx = (1:L)*Wo*Fs/(2*pi);
-
-figure(fg++); clf;
-subplot(211); plot(fftx, Gdbfk(1:Nfft/2));
-subplot(212); plot(s(1:Nfft/2))
-
-figure(fg++); clf;
-subplot(211); plot(harmx, AmdB, 'g+');
- hold on; plot(fftx, Gdbfk(1:Nfft/2), 'r'); hold off;
-subplot(212); plot(fftx, phase(1:Nfft/2),'g');
-
-% synthesise using phases
-
-N = 320;
-s = s_phase = zeros(1,N);
-for m=1:L/4
- s = s + Am(m)*cos(m*Wo*(1:N) + phase_orig(f,m));
- b = round(m*Wo*Nfft/(2*pi));
- s_phase = s_phase + Am(m)*cos(m*Wo*(1:N) + phase(b));
-end
-figure(fg++); clf;
-subplot(211); plot(s); subplot(212); plot(s_phase,'g');
diff --git a/octave/test_dqpsk2.m b/octave/test_dqpsk2.m
deleted file mode 100644
index d421d62..0000000
--- a/octave/test_dqpsk2.m
+++ /dev/null
@@ -1,465 +0,0 @@
-% test_dqpsk2.m
-% David Rowe April 2014
-%
-% DQPSK modem simulation inclduing filtering to test modulating modem
-% tx power based on speech energy. Unlike test_dpsk runs at sample
-% rate Fs.
-
-1;
-
-% main test function
-
-function sim_out = ber_test(sim_in)
- Fs = 8000;
-
- verbose = sim_in.verbose;
- framesize = sim_in.framesize;
- Ntrials = sim_in.Ntrials;
- Esvec = sim_in.Esvec;
- phase_offset = sim_in.phase_offset;
- w_offset = sim_in.w_offset;
- plot_scatter = sim_in.plot_scatter;
- Rs = sim_in.Rs;
- hf_sim = sim_in.hf_sim;
- Nhfdelay = floor(sim_in.hf_delay_ms*Fs/1000);
- Nc = sim_in.Nc;
- symbol_amp = sim_in.symbol_amp;
-
- bps = 2;
- Nsymb = framesize/bps;
- for k=1:Nc
- prev_sym_tx(k) = qpsk_mod([0 0]);
- prev_sym_rx(k) = qpsk_mod([0 0]);
- end
-
- % design root nyquist (root raised cosine) filter and init tx and rx filter states
-
- alpha = 0.5; T=1/Fs; Nfiltsym=7; M=Fs/Rs;
- if floor(Fs/Rs) != Fs/Rs
- printf("oversampling ratio must be an integer\n");
- return;
- end
- hrn = gen_rn_coeffs(alpha, T, Rs, Nfiltsym, M);
- Nfilter = length(hrn);
-
- % convert "spreading" samples from 1kHz carrier at Fs to complex
- % baseband, generated by passing a 1kHz sine wave through PathSim
- % with the ccir-poor model, enabling one path at a time.
-
- Fc = 1000;
- fspread = fopen("../raw/sine1k_2Hz_spread.raw","rb");
- spread1k = fread(fspread, "int16")/10000;
- fclose(fspread);
- fspread = fopen("../raw/sine1k_2ms_delay_2Hz_spread.raw","rb");
- spread1k_2ms = fread(fspread, "int16")/10000;
- fclose(fspread);
-
- % down convert to complex baseband
- spreadbb = spread1k.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k))');
- spreadbb_2ms = spread1k_2ms.*exp(-j*(2*pi*Fc/Fs)*(1:length(spread1k_2ms))');
-
- % remove -2000 Hz image
- b = fir1(50, 5/Fs);
- spread = filter(b,1,spreadbb);
- spread_2ms = filter(b,1,spreadbb_2ms);
-
- % discard first 1000 samples as these were near 0, probably as
- % PathSim states were ramping up. Transpose for convenience
-
- spread = transpose(spread(1000:length(spread)));
- spread_2ms = transpose(spread_2ms(1000:length(spread_2ms)));
-
- % Determine "gain" of HF channel model, so we can normalise
- % carrier power during HF channel sim to calibrate SNR. I imagine
- % different implementations of ccir-poor would do this in
- % different ways, leading to different BER results. Oh Well!
-
- hf_gain = 1.0/sqrt(var(spread)+var(spread_2ms));
-
- % Start Simulation ----------------------------------------------------------------
-
- for ne = 1:length(Esvec)
- EsNodB = Esvec(ne);
- EsNo = 10^(EsNodB/10);
-
- variance = Fs/(Rs*EsNo);
- if verbose > 1
- printf("EsNo (dB): %f EsNo: %f variance: %f\n", EsNodB, EsNo, variance);
- end
-
- Terrs = 0; Tbits = 0;
-
- tx_symb_log = [];
- rx_symb_log = [];
- noise_log = [];
- sim_out.errors_log = [];
- sim_out.tx_baseband_log = [];
- sim_out.rx_filt_log = [];
- symbol_amp_index = 1;
-
- % init filter memories and LOs
-
- tx_filter_memory = zeros(Nc, Nfilter);
- rx_filter_memory = zeros(Nc, Nfilter);
- s_delay_line_filt = zeros(Nc, Nfiltsym);
- phase_tx = ones(1,Nc);
- phase_rx = ones(1,Nc);
- Fcentre = 1500; Fsep = (1+alpha)*Rs;
- freq = Fcentre + Fsep*((-Nc/2+0.5):(Nc/2-0.5));
- freq = exp(j*freq*2*pi/Fs);
-
- % init HF channel
-
- sc = 1; hf_n = 1;
- hf_sim_delay_line = zeros(1,M+Nhfdelay);
- freq_sample_hz = Fcentre + ((Fsep*(-Nc/2)):50:(Fsep*(Nc/2)));
- freq_sample_rads = (2*pi/Fs)*freq_sample_hz;
- hf_model = ones(Ntrials*Nsymb/Nc, length(freq_sample_rads)); % defaults for plotting surface
-
- % bunch of outputs we log for graphing
-
- sim_out.errors_log = [];
- sim_out.Nerrs = [];
- sim_out.snr_log = [];
- sim_out.hf_model_pwr = [];
- sim_out.tx_fdm_log = [];
- C_log = [];
-
- for nn = 1: Ntrials
-
- tx_bits = round( rand( 1, framesize ) );
-
- % modulate --------------------------------------------
-
- s = zeros(1, Nsymb);
- for i=1:Nc:Nsymb
- for k=1:Nc
- tx_symb = qpsk_mod(tx_bits(2*(i-1+k-1)+1:2*(i+k-1)));
- s_qpsk(i+k-1) = tx_symb;
- tx_symb *= prev_sym_tx(k);
- prev_sym_tx(k) = tx_symb;
- s(i+k-1) = symbol_amp(symbol_amp_index)*tx_symb;
- end
- end
- symbol_amp_index++;
- s_ch = s;
-
- % Now we start processing frame Nc symbols at a time to model parallel carriers
-
- tx_fdm_sym_log = [];
- for i=1:Nc:Nsymb
-
- % Delay tx symbols to match delay due to filters. qpsk
- % (rather than dqpsk) symbols used for convenience as
- % it's easy to shift symbols than pairs of bits
-
- s_delay_line_filt(:,1:Nfiltsym-1) = s_delay_line_filt(:,2:Nfiltsym);
- s_delay_line_filt(:,Nfiltsym) = s_qpsk(i:i+Nc-1);
- s_qpsk(i:i+Nc-1) = s_delay_line_filt(:,1);
- for k=1:Nc
- tx_bits(2*(i-1+k-1)+1:2*(i+k-1)) = qpsk_demod(s_qpsk(i+k-1));
- end
-
- % tx filter
-
- tx_baseband = zeros(Nc,M);
-
- % tx filter each symbol, generate M filtered output samples for each symbol.
- % Efficient polyphase filter techniques used as tx_filter_memory is sparse
-
- tx_filter_memory(:,Nfilter) = s(i:i+Nc-1);
-
- for k=1:M
- tx_baseband(:,k) = M*tx_filter_memory(:,M:M:Nfilter) * hrn(M-k+1:M:Nfilter)';
- end
- tx_filter_memory(:,1:Nfilter-M) = tx_filter_memory(:,M+1:Nfilter);
- tx_filter_memory(:,Nfilter-M+1:Nfilter) = zeros(Nc,M);
-
- sim_out.tx_baseband_log = [sim_out.tx_baseband_log tx_baseband];
-
- % upconvert
-
- tx_fdm = zeros(1,M);
-
- for c=1:Nc
- for k=1:M
- phase_tx(c) = phase_tx(c) * freq(c);
- tx_fdm(k) = tx_fdm(k) + tx_baseband(c,k)*phase_tx(c);
- end
- end
-
- sim_out.tx_fdm_log = [sim_out.tx_fdm_log tx_fdm];
-
- % HF channel
-
- if hf_sim
- hf_sim_delay_line(1:Nhfdelay) = hf_sim_delay_line(M+1:M+Nhfdelay);
- hf_sim_delay_line(Nhfdelay+1:M+Nhfdelay) = tx_fdm;
-
- tx_fdm = tx_fdm.*spread(sc:sc+M-1) + hf_sim_delay_line(1:M).*spread_2ms(sc:sc+M-1);
- tx_fdm *= hf_gain;
-
- % sample HF channel spectrum in middle of this symbol for plotting
-
- hf_model(hf_n,:) = hf_gain*(spread(sc+M/2) + exp(-j*freq_sample_rads*Nhfdelay)*spread_2ms(sc+M/2));
-
- sc += M;
- hf_n++;
- end
-
- tx_fdm_sym_log = [tx_fdm_sym_log tx_fdm ];
-
- % AWGN noise and phase/freq offset channel simulation
- % 0.5 factor ensures var(noise) == variance , i.e. splits power between Re & Im
-
- noise = sqrt(variance*0.5)*(randn(1,M) + j*randn(1,M));
- noise_log = [noise_log noise];
-
- % apply frequency and phase offset and noise
-
- for k=1:M
- rx_fdm(k) = tx_fdm(k)*exp(j*phase_offset) + noise(k);
- phase_offset += w_offset;
- end
-
- % downconvert
-
- rx_baseband = zeros(Nc,M);
- for c=1:Nc
- for k=1:M
- phase_rx(c) = phase_rx(c) * freq(c);
- rx_baseband(c,k) = rx_fdm(k)*phase_rx(c)';
- end
- end
-
- % rx filter
-
- rx_filter_memory(:,Nfilter-M+1:Nfilter) = rx_baseband;
- rx_filt = rx_filter_memory * hrn';
- rx_filter_memory(:,1:Nfilter-M) = rx_filter_memory(:,1+M:Nfilter);
- sim_out.rx_filt_log = [sim_out.rx_filt_log rx_filt];
-
- s_ch(i:i+Nc-1) = rx_filt;
- end
-
- % est HF model power for entire code frame (which could be several symbols)
-
- if hf_sim
- frame_hf_model = reshape(hf_model(hf_n-Nsymb/Nc:hf_n-1,:),1,(Nsymb/Nc)*length(freq_sample_hz));
- sim_out.hf_model_pwr = [sim_out.hf_model_pwr mean(abs(frame_hf_model).^2)];
- else
- sim_out.hf_model_pwr = [sim_out.hf_model_pwr 1];
- end
-
- % "genie" SNR estimate
-
- snr = (tx_fdm_sym_log*tx_fdm_sym_log')/(M*variance);
- sim_out.snr_log = [sim_out.snr_log snr];
-
- % de-modulate
-
- rx_bits = zeros(1, framesize);
- for i=1:Nc:Nsymb
- for k=1:Nc
- rx_symb = s_ch(i+k-1);
- tmp = rx_symb;
- rx_symb *= conj(prev_sym_rx(k)/abs(prev_sym_rx(k)));
- prev_sym_rx(k) = tmp;
- rx_bits((2*(i-1+k-1)+1):(2*(i+k-1))) = qpsk_demod(rx_symb);
- rx_symb_log = [rx_symb_log rx_symb];
- end
- end
-
- % ignore data until we have enough frames to fill filter memory
- % then count errors
-
- if nn > ceil(Nfiltsym/(Nsymb/Nc))
- error_positions = xor(rx_bits, tx_bits);
- sim_out.errors_log = [sim_out.errors_log error_positions];
- Nerrs = sum(error_positions);
- sim_out.Nerrs = [sim_out.Nerrs Nerrs];
- Terrs += Nerrs;
- Tbits += length(tx_bits);
- end
-
- end
-
- TERvec(ne) = Terrs;
- BERvec(ne) = Terrs/Tbits;
-
- if verbose
- printf("EsNo (dB): %f Terrs: %d BER %f ", EsNodB, Terrs, Terrs/Tbits);
- printf("\n");
- end
- if verbose > 1
- printf("Terrs: %d BER %f C %f N %f Es %f No %f Es/No %f\n\n", Terrs,
- Terrs/Tbits, var(sim_out.tx_fdm_log), var(noise_log),
- var(sim_out.tx_fdm_log)/(Nc*Rs), var(noise_log)/Fs, (var(sim_out.tx_fdm_log)/(Nc*Rs))/(var(noise_log)/Fs));
- end
- end
-
- Ebvec = Esvec - 10*log10(bps);
-
- sim_out.BERvec = BERvec;
- sim_out.Ebvec = Ebvec;
- sim_out.TERvec = TERvec;
-
- if plot_scatter
- figure(2);
- clf;
- scat = rx_symb_log(Nfiltsym*Nc:length(rx_symb_log)) .* exp(j*pi/4);
- plot(real(scat), imag(scat),'+');
- title('Scatter plot');
-
- figure(3);
- clf;
- y = 1:Rs*2;
- EsNodBSurface = 20*log10(abs(hf_model(y,:))) + EsNodB;
- mesh(1:length(freq_sample_hz),y,EsNodBSurface);
- grid
- title('HF Channel Es/No');
- end
-
-endfunction
-
-% Gray coded QPSK modulation function
-
-function symbol = qpsk_mod(two_bits)
- two_bits_decimal = sum(two_bits .* [2 1]);
- switch(two_bits_decimal)
- case (0) symbol = 1;
- case (1) symbol = j;
- case (2) symbol = -j;
- case (3) symbol = -1;
- endswitch
-endfunction
-
-% Gray coded QPSK demodulation function
-
-function two_bits = qpsk_demod(symbol)
- if isscalar(symbol) == 0
- printf("only works with scalars\n");
- return;
- end
- bit0 = real(symbol*exp(j*pi/4)) < 0;
- bit1 = imag(symbol*exp(j*pi/4)) < 0;
- two_bits = [bit1 bit0];
-endfunction
-
-function sim_in = standard_init
- sim_in.verbose = 1;
- sim_in.plot_scatter = 0;
-
- sim_in.Esvec = 5:15;
- sim_in.Ntrials = 100;
- sim_in.framesize = 64;
- sim_in.Rs = 100;
- sim_in.Nc = 8;
-
- sim_in.phase_offset = 0;
- sim_in.w_offset = 0;
- sim_in.phase_noise_amp = 0;
-
- sim_in.hf_delay_ms = 2;
- sim_in.hf_sim = 0;
- sim_in.hf_phase_only = 0;
- sim_in.hf_mag_only = 0;
-endfunction
-
-function awgn_hf_ber_curves()
- sim_in = standard_init();
-
- Ebvec = sim_in.Esvec - 10*log10(2);
- BER_theory = 0.5*erfc(sqrt(10.^(Ebvec/10)));
-
- dpsk_awgn = ber_test(sim_in);
- sim_in.hf_sim = 1;
- dpsk_hf = ber_test(sim_in);
-
- figure(1);
- clf;
- semilogy(Ebvec, BER_theory,'r;QPSK theory;')
- hold on;
- semilogy(dpsk_awgn.Ebvec, dpsk_awgn.BERvec,'g;DQPSK;')
- semilogy(dpsk_hf.Ebvec, dpsk_hf.BERvec,'g;DQPSK HF;')
- hold off;
- xlabel('Eb/N0')
- ylabel('BER')
- grid("minor")
- axis([min(Ebvec) max(Ebvec) 1E-3 1])
-end
-
-sim_in = standard_init();
-
-% energy file sampled every 10ms
-
-load ../src/ve9qrp.txt
-pdB=10*log10(ve9qrp);
-for i=1:length(pdB)
- if pdB(i) < 0
- pdB(i) = 0;
- end
-end
-
-% Down sample to 40ms rate used for 1300 bit/s codec, every 4th sample is transmitted
-
-pdB = pdB(4:4:length(pdB));
-
-% Use linear mapping function in dB domain to map to symbol power
-
-%power_map_x = [ 0 20 24 40 50 ];
-%power_map_y = [--6 -6 0 6 6];
-power_map_x = [ 0 50 ];
-power_map_y = [ -15 12];
-mapped_pdB = interp1(power_map_x, power_map_y, pdB);
-
-sim_in.symbol_amp = 10 .^ (mapped_pdB/20);
-%sim_in.symbol_amp = ones(1,length(pdB));
-sim_in.plot_scatter = 1;
-sim_in.verbose = 2;
-sim_in.hf_delay_ms = 2;
-sim_in.hf_sim = 1;
-sim_in.Esvec = 10;
-sim_in.Ntrials = 400;
-
-dqpsk_pwr_hf = ber_test(sim_in);
-
-% note: need way to test that power is aligned with speech
-
-figure(4)
-clf;
-plot((1:sim_in.Ntrials)*80*4, pdB(1:sim_in.Ntrials));
-hold on;
-plot((1:sim_in.Ntrials)*80*4, mapped_pdB(1:sim_in.Ntrials),'r');
-hold off;
-
-figure(5)
-clf;
-s = load_raw("../raw/ve9qrp.raw");
-M=320; M_on_2 = M/2; % processing delay between input speech and centre of analysis window
-subplot(211)
-plot(M_on_2:(M_on_2-1+sim_in.Ntrials*M),s(1:sim_in.Ntrials*M))
-hold on;
-plot((1:sim_in.Ntrials)*M, 5000*sim_in.symbol_amp(1:sim_in.Ntrials),'r');
-hold off;
-axis([1 sim_in.Ntrials*M -3E4 3E4]);
-subplot(212)
-plot(real(dqpsk_pwr_hf.tx_fdm_log));
-
-
-figure(6)
-clf;
-plot((1:sim_in.Ntrials)*M, 20*log10(sim_in.symbol_amp(1:sim_in.Ntrials)),'b;Es (dB);');
-hold on;
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.hf_model_pwr),'g;Fading (dB);');
-plot((1:sim_in.Ntrials)*M, 10*log10(dqpsk_pwr_hf.snr_log),'r;Es/No (dB);');
-
-ber = dqpsk_pwr_hf.Nerrs/sim_in.framesize;
-ber_clip = ber;
-ber_clip(find(ber > 0.2)) = 0.2;
-plot((1:length(ber_clip))*M, -20+100*ber_clip,'k;BER (0-20%);');
-hold off;
-axis([1 sim_in.Ntrials*M -20 20])
-
-fep=fopen("dqpsk_errors_pwr.bin","wb"); fwrite(fep, dqpsk_pwr_hf.errors_log, "short"); fclose(fep);
-fber=fopen("ber.bin","wb"); fwrite(fber, ber, "float"); fclose(fber);
diff --git a/octave/trellis.m b/octave/trellis.m
deleted file mode 100644
index 01649ec..0000000
--- a/octave/trellis.m
+++ /dev/null
@@ -1,594 +0,0 @@
-% trellis.m
-% David Rowe July 2021
-%
-% Testing trellis decoding of Codec 2 Vector Quantiser (VQ)
-% information. Uses soft decision information, probablility of state
-% transitions, and left over redundancy to correct errors on VQ
-% reception.
-%
-% VQ indexes are transmitted as codewords mapped to +-1
-%
-% y = c + n
-%
-% where c is the transmitted codeword, y is the received codeword,
-% and n is Gaussian noise.
-%
-% This script generates the test data files:
-%
-% cd codec2/build_linux
-% ../script/train_trellis.sh
-%
-% Results so far (August 2021):
-%
-% 1/ 2dB improvement with nstages=3, dec=1
-% 2/ No useful improvement with nstages=3, dec=4. This is required for a practical codec to
-% get a useful bit rate.
-
-1;
-
-% converts a decimal value to a soft dec binary value
-function c = dec2sd(dec, nbits)
-
- % convert to binary
-
- c = zeros(1,nbits);
- for j=0:nbits-1
- mask = 2.^j;
- if bitand(dec,mask)
- c(nbits-j) = 1;
- end
- end
-
- % map to +/- 1
-
- c = -1 + 2*c;
-endfunction
-
-
-% y is vector of received soft decision values (e.g +/-1 + noise)
-function [txp indexes] = ln_tx_codeword_prob_given_rx_codeword_y(y, nstates, C)
- nbits = length(y);
- np = 2.^nbits;
-
- % Find log probability of all possible transmitted codewords
- txp = C * y';
-
- % return most probable codewords (number of states to search)
- [txp indexes] = sort(txp,"descend");
- txp = txp(1:nstates);
- indexes = indexes(1:nstates) - 1;
-endfunction
-
-% A matrix of all possible tx codewords C, one per row
-function C = precompute_C(nbits)
- np = 2.^nbits;
-
- C = zeros(np, nbits);
- for r=0:np-1
- C(r+1,:) = dec2sd(r,nbits);
- end
-
-endfunction
-
-
-% work out transition probability matrix, given lists of current and next
-% candidate codewords
-
-function tp = calculate_tp(vq, sd_table, h_table, indexes_current, indexes_next, verbose)
- ntxcw = length(indexes_current);
- tp = zeros(ntxcw, ntxcw);
- for txcw_current=1:ntxcw
- index_current = indexes_current(txcw_current);
- for txcw_next=1:ntxcw
- index_next = indexes_next(txcw_next);
- dist = vq(index_current+1,:) - vq(index_next+1,:);
- sd = mean(dist.^2);
- p = prob_from_hist(sd_table, h_table, sd);
- if bitand(verbose, 0x2)
- printf("index_current: %d index_next: %d sd: %f p: %f\n", index_current, index_next, sd, p);
- end
- tp(txcw_current, txcw_next) = log(p);
- end
- end
-endfunction
-
-
-% y is the sequence received soft decision codewords, each row is one
-% codeword in time. sd_table and h_table map SD to
-% probability. Returns the most likely transmitted VQ index ind in the
-% middle of the codeword sequence y. We search the most likely ntxcw
-% tx codewords out of 2^nbits possibilities.
-
-function ind = find_most_likely_index(y, vq, C, sd_table, h_table, nstages, ntxcw, verbose)
- [ncodewords nbits] = size(y);
-
- % populate the nodes of the trellis with the most likely transmitted codewords
- txp = zeros(nstages, ntxcw); indexes = zeros(nstages, ntxcw);
- for s=1:nstages
- [atxp aindexes] = ln_tx_codeword_prob_given_rx_codeword_y(y(s,:), ntxcw, C);
- txp(s,:) = atxp;
- indexes(s,:) = aindexes;
- end
-
- if verbose
- printf("rx_codewords:\n");
- for r=1:ncodewords
- for c=1:nbits
- printf("%7.2f", y(r,c));
- end
- printf("\n");
- end
-
- printf("\nProbability of each tx codeword index/binary/ln(prob):\n");
- printf(" ");
- for s=1:nstages
- printf("Time n%+d ", s - (floor(nstages/2)+1));
- end
- printf("\n");
-
- for i=1:ntxcw
- printf("%d ", i);
- for s=1:nstages
- ind = indexes(s,i);
- printf("%4d %12s %5.2f ", ind, dec2bin(ind,nbits), txp(s, i));
- end
- printf("\n");
- end
- printf("\n");
- end
-
- % Determine transition probability matrix for each stage, this
- % changes between stages as lists of candidate tx codewords
- % changes
-
- tp = zeros(nstages, ntxcw, ntxcw);
- for s=1:nstages-1
- if verbose printf("Calc tp(%d,:,:)\n", s), end
- tp(s,:,:) = calculate_tp(vq, sd_table, h_table, indexes(s,:), indexes(s+1,:), verbose);
- end
-
- if verbose
- printf("Evaluation of all possible paths:\n");
- printf(" ");
- for s=1:nstages
- printf(" n%+d", s - (floor(nstages/2)+1));
- end
- printf(" indexes");
- printf(" ");
-
- for s=1:nstages
- printf(" txp(%d)", s-1);
- if s < nstages
- printf(" tp(%d,%d) ", s-1,s);
- end
- end
- printf(" prob max_prob\n");
- end
-
- % OK lets search all possible paths and find most probable
-
- n = ones(1,nstages); % current node at each stage through trellis, describes current path
- max_prob = -100;
- do
-
- if bitand(verbose, 0x4)
- printf(" ");
- for s=1:nstages
- printf("%4d", n(s)-1);
- end
- printf(" ");
- for s=1:nstages
- printf("%4d ", indexes(s,n(s)));
- end
- end
-
- % find the probability of current path
- prob = 0;
- for s=1:nstages
- prob += txp(s, n(s));
- if bitand(verbose,0x4)
- printf("%8.2f ", txp(s, n(s)));
- end
- if s < nstages
- prob += tp(s, n(s), n(s+1));
- if bitand(verbose,0x4)
- printf("%8.2f ", tp(s, n(s), n(s+1)));
- end
- end
- end
-
- if (prob > max_prob)
- max_prob = prob;
- max_n = n;
- end
-
- if bitand(verbose,0x4)
- printf("%9.2f %9.2f\n", prob, max_prob);
- end
-
- % next path
-
- s = nstages;
- n(s)++;
- while (s && (n(s) == (ntxcw+1)))
- n(s) = 1;
- s--;
- if s > 0
- n(s)++;
- end
- end
- until (sum(n) == nstages)
-
- middle = floor(nstages/2)+1;
- ind = indexes(middle, max_n(middle));
- if verbose
- printf("\nMost likely path through nodes... ");
- for s=1:nstages
- printf("%4d ", max_n(s)-1);
- end
- printf("\nMost likely path through indexes: ");
- for s=1:nstages
- printf("%4d ", indexes(s,max_n(s)));
- end
- printf("\nMost likely VQ index at time n..: %4d\n", ind);
- end
-endfunction
-
-
-% Given a normalised histogram, estimate probability from SD
-function p = prob_from_hist(sd_table, h_table, sd)
- p = interp1 (sd_table, h_table, sd, "extrap", "nearest");
-endfunction
-
-
-% Calculate a normalised histogram of the SD of adjacent frames from
-% a file of output vectors from the VQ.
-function [sd_table h_table] = vq_hist(vq_output_fn, dec=1)
- K=20; K_st=2+1; K_en=16+1;
- vq_out = load_f32(vq_output_fn, K);
- [r c]= size(vq_out);
- diff = vq_out(dec+1:end,K_st:K_en) - vq_out(1:end-dec,K_st:K_en);
- % Octave efficient way to determine MSE or each row of matrix
- sd_adj = meansq(diff');
- [h_table sd_table] = hist(sd_adj,100,1);
- h_table = max(h_table, 1E-5);
-endfunction
-
-
-% vector quantise a sequence of target input vectors, returning the VQ indexes and
-% quantised vectors target_
-function [indexes target_] = vector_quantiser(vq, target, verbose=1)
- [vq_size K] = size(vq);
- [ntarget tmp] = size(target);
- target_ = zeros(ntarget,K);
- indexes = zeros(1,ntarget);
- for i=1:ntarget
- best_e = 1E32;
- for ind=1:vq_size
- e = sum((vq(ind,:)-target(i,:)).^2);
- if verbose printf("i: %d ind: %d e: %f\n", i, ind, e), end;
- if e < best_e
- best_e = e;
- best_ind = ind;
- end
- end
- if verbose printf("best_e: %f best_ind: %d\n", best_e, best_ind), end;
- target_(i,:) = vq(best_ind,:); indexes(i) = best_ind;
- end
-endfunction
-
-
-% faster version of vector quantiser
-function [indexes target_] = vector_quantiser_fast(vq, target, verbose=1)
- [vq_size K] = size(vq);
- [ntarget tmp] = size(target);
- target_ = zeros(ntarget,K);
- indexes = zeros(1,ntarget);
-
- % pre-compute energy of each VQ vector
- vqsq = zeros(vq_size,1);
- for i=1:vq_size
- vqsq(i) = vq(i,:)*vq(i,:)';
- end
-
- % use efficient matrix multiplies to search for best match to target
- for i=1:ntarget
- best_e = 1E32;
- e = vqsq - 2*(vq * target(i,:)');
- [best_e best_ind] = min(e);
- if verbose printf("best_e: %f best_ind: %d\n", best_e, best_ind), end;
- target_(i,:) = vq(best_ind,:); indexes(i) = best_ind;
- end
-endfunction
-
-
-% VQ a target sequence of frames then run a test using vanilla uncoded/trellis decoder
-function results = run_test(target, vq, sd_table, h_table, ntxcw, nstages, EbNo, verbose)
- [frames tmp] = size(target);
- [vq_length tmp] = size(vq);
- nbits = log2(vq_length);
- nerrors = 0;
- nerrors_vanilla = 0;
- tbits = 0;
- nframes = 0;
- nper = 0;
- nper_vanilla = 0;
-
- C = precompute_C(nbits);
-
- % Vector Quantise target vectors sequence
- [tx_indexes target_ ] = vector_quantiser_fast(vq, target, verbose);
- % use convention of indexes starting from 0
- tx_indexes -= 1;
- % mean SD of VQ with no errors
- diff = target - target_;
- mse_noerrors = mean(diff(:).^2);
-
- % construct tx symbol codewords from VQ indexes
- tx_codewords = zeros(frames, nbits);
- for f=1:frames
- tx_codewords(f,:) = dec2sd(tx_indexes(f), nbits);
- end
-
- rx_codewords = tx_codewords + randn(frames, nbits)*sqrt(1/(2*EbNo));
- rx_indexes = zeros(1,frames);
- rx_indexes_vanilla = ones(1,frames);
-
- ns2 = floor(nstages/2);
- for f=ns2+1:frames-ns2
- %if f==10 verbose = 1+0x2, else verbose = 0;, end
- if verbose
- printf("f: %d tx_indexes: ", f);
- for i=f-ns2:f+ns2
- printf("%d ", tx_indexes(i));
- end
- printf("\n");
- end
- tx_bits = tx_codewords(f,:) > 0;
- if verbose
- printf("tx_bits: ");
- for i=1:nbits
- printf("%d",tx_bits(i));
- end
- printf("\n");
- end
- rx_bits_vanilla = rx_codewords(f,:) > 0;
- rx_indexes(f) = find_most_likely_index(rx_codewords(f-ns2:f+ns2,:)*EbNo,
- vq, C, sd_table, h_table, nstages, ntxcw, verbose);
- rx_bits = dec2sd(rx_indexes(f), nbits) > 0;
- rx_indexes_vanilla(f) = sum(rx_bits_vanilla .* 2.^(nbits-1:-1:0));
- errors = sum(xor(tx_bits, rx_bits));
- nerrors += errors;
- if errors nper++;, end
- errors = sum(xor(tx_bits, rx_bits_vanilla));
- nerrors_vanilla += errors;
- if errors nper_vanilla++;, end
- if verbose
- printf("[%d] %d %d\n", f, nerrors, nerrors_vanilla);
- end
- tbits += nbits;
- nframes++;
- end
-
- EbNodB = 10*log10(EbNo);
- target = target(ns2+1:frames-ns2,:);
- target_vanilla_ = vq(rx_indexes_vanilla(ns2+1:frames-ns2)+1,:);
- target_ = vq(rx_indexes(ns2+1:frames-ns2)+1,:);
- diff_vanilla = target - target_vanilla_;
- mse_vanilla = mean(diff_vanilla(:).^2);
- diff = target - target_;
- mse = mean(diff(:).^2);
- printf("Eb/No: %3.2f dB nframes: %2d nerrors %3d %3d BER: %4.3f %4.3f PER: %3.2f %3.2f mse: %3.2f %3.2f %3.2f\n",
- EbNodB, nframes, nerrors, nerrors_vanilla, nerrors/tbits, nerrors_vanilla/tbits,
- nper/nframes, nper_vanilla/nframes,
- mse_noerrors, mse, mse_vanilla);
- results.ber = nerrors/tbits;
- results.ber_vanilla = nerrors_vanilla/tbits;
- results.per = nper/nframes;
- results.per_vanilla = nper_vanilla/nframes;
- results.mse_noerrors = mse_noerrors;
- results.mse = mse;
- results.mse_vanilla = mse_vanilla;
- results.tx_indexes = tx_indexes;
- results.rx_indexes = rx_indexes;
- results.rx_indexes_vanilla = rx_indexes_vanilla;
-endfunction
-
-% Simulations ---------------------------------------------------------------------
-
-% top level function to set up and run a test
-function [results target_] = test_trellis(target_fn, nframes=100, dec=1, ntxcw=8, nstages=3, EbNodB=3, verbose=0)
- K = 20; K_st=2+1; K_en=16+1;
- vq_fn = "../build_linux/vq_stage1_bs004.f32";
- vq_output_fn = "../build_linux/all_speech_8k_test.f32";
-
- % load VQ
- vq = load_f32(vq_fn, K);
- [vq_size tmp] = size(vq);
- vqsub = vq(:,K_st:K_en);
-
- % load file of VQ-ed vectors to train up SD PDF estimator
- [sd_table h_table] = vq_hist(vq_output_fn, dec);
-
- % load sequence of target vectors we wish to VQ
- target = load_f32(target_fn, K);
-
- % limit test to the first nframes vectors
- if nframes != -1
- last = nframes;
- else
- last = length(target);
- end
- target = target(1:dec:last,K_st:K_en);
-
- % run a test
- EbNo=10^(EbNodB/10);
- results = run_test(target, vqsub, sd_table, h_table, ntxcw, nstages, EbNo, verbose);
- if verbose
- for f=2:nframes-1
- printf("f: %03d tx_index: %04d rx_index: %04d\n", f, results.tx_indexes(f), results.rx_indexes(f));
- end
- end
-
- % return full band vq-ed vectors
- target_ = zeros(last,K);
- target_(1:dec:last,:) = vq(results.rx_indexes+1,:);
-
- % use linear interpolation to restore original frame rate
- for f=1:dec:last-dec
- prev = f; next = f + dec;
- for g=prev+1:next-1
- cnext = (g-prev)/dec; cprev = 1 - cnext;
- target_(g,:) = cprev*target_(prev,:) + cnext*target_(next,:);
- %printf("f: %d g: %d cprev: %f cnext: %f\n", f, g, cprev, cnext);
- end
- end
-endfunction
-
-% Plot histograms of SD at different decimations in time
-function vq_hist_dec(vq_output_fn)
- figure(1); clf;
- [sd_table h_table] = vq_hist(vq_output_fn, dec=1);
- plot(sd_table, h_table, "b;dec=1;");
- hold on;
- [sd_table h_table] = vq_hist(vq_output_fn, dec=2);
- plot(sd_table, h_table, "r;dec=2;");
- [sd_table h_table] = vq_hist(vq_output_fn, dec=3);
- plot(sd_table, h_table, "g;dec=3;");
- [sd_table h_table] = vq_hist(vq_output_fn, dec=4);
- plot(sd_table, h_table, "c;dec=4;");
- hold off;
- axis([0 300 0 0.5])
- xlabel("SD dB*dB"); title('Histogram of SD(n,n+1)');
-endfunction
-
-% Automated tests for vanilla and fast VQ search functions
-function test_vq(vq_fn)
- K=20;
- vq = load_f32(vq_fn, K);
- vq_size = 100;
- target = vq(1:vq_size,:);
- indexes = vector_quantiser(target,target, verbose=0);
- assert(indexes == 1:vq_size);
- printf("Vanilla OK!\n");
- indexes = vector_quantiser_fast(target,target, verbose=0);
- assert(indexes == 1:vq_size);
- printf("Fast OK!\n");
-endfunction
-
-% Test trellis decoding a single vector in a sequence of 3
-function ind = run_test_single(tx_codewords, ntxcw, var, verbose)
- nstages = 3;
- nbits = 2;
-
- rx_codewords = tx_codewords + randn(nstages, nbits)*var;
- vq = [0 0 0 1;
- 0 0 1 0;
- 0 1 0 0;
- 1 0 0 0];
- sd_table = [0 1 2 4];
- h_table = [0.5 0.25 0.15 0.1];
- C = precompute_C(nbits);
- ind = find_most_likely_index(rx_codewords, vq, C, sd_table, h_table, nstages, ntxcw, verbose);
-endfunction
-
-% Series of single point sanity checks
-function test_single
- printf("Single vector decode tests....\n");
- ind = run_test_single([-1 -1; -1 -1; -1 -1], ntxcw=1, var=0, verbose=0);
- assert(ind == 0);
- printf("00 with no noise OK!\n");
-
- ind = run_test_single([-1 1; 1 1; -1 1], ntxcw=1, var=0, verbose=0);
- assert(ind == 3);
- printf("11 with no noise OK!\n");
-
- ind = run_test_single([-1 -1; -1 1; -1 -1], ntxcw=4, var=1, verbose=0);
- assert(ind == 1);
- printf("01 with noise OK!\n");
-endfunction
-
-% BPSK simulation to check noise injection
-function test_bpsk_ber
- nbits = 12;
- frames = 10000;
- tx_codewords = zeros(frames,nbits);
- tx_bits = zeros(frames,nbits);
- for f=1:frames
- tx_codewords(f,:) = dec2sd(f, nbits);
- tx_bits(f,:) = tx_codewords(f,:) > 0;
- end
-
- EbNodB = 5;
- EbNo = 10^(EbNodB/10);
- rx_codewords = tx_codewords + randn(frames, nbits)*sqrt(1/(2*EbNo));
- rx_bits = rx_codewords > 0;
- nerrors = sum(xor(tx_bits, rx_bits)(:));
- tbits = frames*nbits;
- printf("EbNo: %4.2f dB tbits: %d errs: %d BER: %4.3f %4.3f\n", EbNodB, tbits, nerrors, nerrors/tbits, 0.5*erfc(sqrt(EbNo)));
-endfunction
-
-% generate sets of curves
-function [EbNodB rms_sd] = run_curves(frames=100, dec=1, nstages=5)
- results_log = [];
- EbNodB = [0 1 2 3 4 5];
- target_fn = "../build_linux/all_speech_8k_lim.f32";
-
- for i=1:length(EbNodB)
- results = test_trellis(target_fn, frames, dec, ntxcw=8, nstages, EbNodB(i), verbose=0);
- results_log = [results_log results];
- end
- for i=1:length(results_log)
- ber(i) = results_log(i).ber;
- ber_vanilla(i) = results_log(i).ber_vanilla;
- per(i) = results_log(i).per;
- per_vanilla(i) = results_log(i).per_vanilla;
- rms_sd_noerrors(i) = sqrt(results_log(i).mse_noerrors);
- rms_sd(i) = sqrt(results_log(i).mse);
- rms_sd_vanilla(i) = sqrt(results_log(i).mse_vanilla);
- end
-
- figure(1); clf; semilogy(EbNodB, ber_vanilla, "r+-;uncoded;"); hold on;
- semilogy(EbNodB, ber, "g+-;trellis;"); hold off;
- grid('minor'); title(sprintf("BER dec=%d nstages=%d",dec,nstages));
- print("-dpng", sprintf("trellis_dec_%d_ber.png",dec));
-
- figure(2); clf; semilogy(EbNodB, per_vanilla, "r+-;uncoded;"); hold on;
- semilogy(EbNodB, per, "g+-;trellis;");
- grid('minor'); title(sprintf("PER dec=%d nstages=%d",dec,nstages));
- print("-dpng", sprintf("trellis_dec_%d_per.png",dec));
-
- figure(3); clf; plot(EbNodB, rms_sd_noerrors, "b+-;no errors;"); hold on;
- plot(EbNodB, rms_sd_vanilla, "r+-;uncoded;");
- plot(EbNodB, rms_sd, "g+-;trellis;"); hold off;
- grid('minor'); title(sprintf("RMS SD dec=%d nstages=%d",dec,nstages));
- print("-dpng", sprintf("trellis_dec_%d_rms_sd.png",dec));
-endfunction
-
-function vq_file(vq_fn, dec, EbNodB, in_fn, out_fn)
- [results target_] = test_trellis(in_fn, nframes=-1, dec, ntxcw=8, nstages=3, EbNodB, verbose=0);
- save_f32(out_fn, target_);
-endfunction
-
-% -------------------------------------------------------------------
-
-more off;
-randn('state',1);
-
-% uncomment one of the below to run a test or simulation
-
-% These two tests show where we are at:
-%test_trellis(target_fn, nframes=600, dec=1, ntxcw=8, nstages=3, EbNodB=3, verbose=0);
-%test_trellis(target_fn, nframes=600, dec=4, ntxcw=8, nstages=3, EbNodB=3, verbose=0);
-
-%run_curves(600,1)
-%run_curves(600,2)
-%run_curves(600,4)
-%[EbNodB rms_sd] = run_curves(30*100,3,3)
-
-%test_trellis(target_fn, nframes=200, dec=1, ntxcw=1, nstages=3, EbNodB=3, verbose=0);
-%test_trellis(target_fn, nframes=100, dec=2, ntxcw=8, nstages=3, EbNodB=3, verbose=0);
-%test_vq("../build_linux/vq_stage1.f32");
-%vq_hist_dec("../build_linux/all_speech_8k_test.f32");
-%test_single
-%test_bpsk_ber
diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m
deleted file mode 100644
index 3e57b9a..0000000
--- a/octave/vq_700c_eq.m
+++ /dev/null
@@ -1,366 +0,0 @@
-% vq_700c.m
-% David Rowe May 2019
-%
-% Researching Codec 2 700C VQ equaliser ideas
-% See also scripts/train_700c_quant.sh, tnewamp1.m
-
-melvq;
-newamp_700c;
-
-% general purpose plot function for looking at averages of K-band
-% sequences in scripts dir and VQs:
-% vq_700c_plots({"hts2a.f32" "vk5qi.f32" "train_120_1.txt"})
-
-function vq_700c_plots(fn_array)
- K = 20; rate_K_sample_freqs_kHz = mel_sample_freqs_kHz(K);
- freq_Hz = rate_K_sample_freqs_kHz * 1000;
-
- figure(1); clf; hold on; axis([200 4000 40 90]); title('Max Hold');
- figure(2); clf; hold on; axis([200 4000 0 40]); title('Average');
-
- for i=1:length(fn_array)
- [dir name ext] = fileparts(fn_array{i});
- if strcmp(ext, ".f32")
- % f32 feature file
- fn = sprintf("../build_linux/%s%s", name, ext)
- bands = load_f32(fn , K);
- else
- % text file (e.g. existing VQ)
- bands = load(fn_array{i});
- end
- % for max hold: break into segments of Nsec, find max, average maximums
- % this avoids very rare global peaks setting the max
- Nsec = 10; Tframe = 0.01; frames_per_seg = Nsec/Tframe
- Nsegs = floor(length(bands)/frames_per_seg)
- max_holds = zeros(Nsegs, K);
- if Nsegs == 0
- max_holds = max(bands)
- else
- for s=1:Nsegs
- st = (s-1)*frames_per_seg+1; en = st + frames_per_seg - 1;
- max_holds(s,:) = max(bands(st:en,:));
- end
- max_holds = mean(max_holds);
- end
- figure(1); plot(freq_Hz, max_holds, '+-', 'linewidth', 2);
- figure(2); plot(freq_Hz, mean(bands), '+-', 'linewidth', 2);
- end
- figure(1); legend(fn_array); grid; xlabel('Freq (Hz)'); ylabel('Amp dB');
- figure(2); legend(fn_array); grid; xlabel('Freq (Hz)'); ylabel('Amp dB');
-endfunction
-
-
-% limit mean of each vector to between lower_lim and upper_lim
-function vout = limit_vec(vin, lower_lim, upper_lim)
- m = mean(vin');
- vout = zeros(size(vin));
- for i=1:length(vin)
- vec_no_mean = vin(i,:) - m(i);
- if m(i) < lower_lim
- m(i) = lower_lim;
- end
- if m(i) > upper_lim
- m(i) = upper_lim;
- end
- vout(i,:) = vec_no_mean + m(i);
- end
-endfunction
-
-
-% single stage vq a target matrix
-function errors = vq_targets(vq, targets)
- errors = [];
- for i=1:length(targets)
- [mse_list index_list] = search_vq(vq, targets(i,:), 1);
- error = targets(i,:) - vq(index_list(1),:);
- errors = [errors; error];
- end
-endfunction
-
-
-% single stage vq a target matrix with adaptive EQ, this didn't work
-
-function [errors eqs] = vq_targets_adap_eq(vq, targets, eqs)
- errors = []; gain=0.02;
- eq = eqs(end,:);
- for i=1:length(targets)
- t = targets(i,:) - eq;
- mean(t)
- %t -= mean(t);
- [mse_list index_list] = search_vq(vq, t, 1);
- error = t - vq(index_list(1),:);
- eq = (1-gain)*eq + gain*error;
- errors = [errors; error]; eqs = [eqs; eq];
- end
-endfunction
-
-
-% single stage vq a target matrix with block adaptive EQ, this works
-% well with nblock == 10
-
-function [errors eq] = vq_targets_block_eq(vq, targets, eq, nblock)
- errors = []; n = 0; [tmp K] = size(vq); error_eq = zeros(1,K); gain=0.20;
- for i=1:length(targets)
- t = targets(i,:) - eq;
- [mse_list index_list] = search_vq(vq, t, 1);
- error = t - vq(index_list(1),:);
- error_eq += error;
- errors = [errors; error];
- n++;
- if n == nblock
- eq = 0.99*eq + gain*error_eq/nblock;
- n = 0; error_eq = zeros(1,K);
- end
- end
-endfunction
-
-
-% two stage mbest VQ a target matrix
-
-function [errors targets_] = vq_targets2(vq1, vq2, targets)
- vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5;
- [errors targets_] = mbest(vqset, targets, m);
-endfunction
-
-
-% two stage mbest VQ a target matrix, with adap_eq
-
-function [errors targets_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, eq)
- vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5; gain=0.02;
- errors = []; targets_ = [];
- for i=1:length(targets)
- t = targets(i,:)-eq;
- t -= mean(t')';
- [error target_ indexes] = mbest(vqset, t, m);
- % use first stage VQ as error driving adaptive EQ
- eq_error = t - vq1(indexes(1),:);
- eq = (1-gain)*eq + gain*eq_error;
- errors = [errors; error]; targets_ = [targets_; target_];
- end
-endfunction
-
-
-% Given target and vq matrices, estimate eq via two metrics. First
-% metric seems to work best. Both uses first stage VQ error for EQ
-
-function [eq1 eq2] = est_eq(vq, targets)
- [ntargets K] = size(targets);
- [nvq K] = size(vq);
-
- eq1 = zeros(1,K); eq2 = zeros(1,K);
- for i=1:length(targets)
- [mse_list index_list] = search_vq(vq, targets(i,:), 1);
-
- % eq metric 1: average of error for best VQ entry
- eq1 += targets(i,:) - vq(index_list(1),:);
-
- % eq metric 2: average of error across all VQ entries
- for j=1:nvq
- eq2 += targets(i,:) - vq(j,:);
- end
- end
-
- eq1 /= ntargets;
- eq2 /= (ntargets*nvq);
-endfunction
-
-function [targets e] = load_targets(fn_target_f32)
- nb_features = 41;
- K = 20;
-
- % .f32 files are in scripts directory, first K values rate_K_no_mean vectors
- [dir name ext] = fileparts(fn_target_f32);
- fn = sprintf("../script/%s_feat.f32", name);
- feat = load_f32(fn, nb_features);
- e = feat(:,1);
- targets = feat(:,2:K+1);
-endfunction
-
-% rather simple EQ in front of VQ
-
-function [eqs ideal] = est_eq_front(targets)
- [tmp K] = size(targets);
- ideal = [ 8 10 12 14 14*ones(1,K-1-4) -20];
- eq = zeros(1,K); gain = 0.02;
- eqs = [];
- for i=1:length(targets)
- update = targets(i,:) - ideal;
- eq = (1-gain)*eq + gain*update;
- eq(find(eq < 0)) = 0;
- eqs = [eqs; eq];
- end
-endfunction
-
-function table_across_samples
- K = 20;
-
- % VQ is in .txt file in this directory, we have two to choose from. train_120 is the Codec 2 700C VQ,
- % train_all_speech was trained up from a different, longer database, as a later exercise
- vq_name = "train_120";
- #vq_name = "train_all_speech";
- vq1 = load(sprintf("%s_1.txt", vq_name));
- vq2 = load(sprintf("%s_2.txt", vq_name));
-
- printf("----------------------------------------------------------------------------------\n");
- printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n");
- printf("----------------------------------------------------------------------------------\n");
-
- fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"};
- #fn_targets = {"cq_freedv_8k_lfboost"};
- figs=1;
- for i=1:length(fn_targets)
-
- % load target and estimate eq
- [targets e] = load_targets(fn_targets{i});
- eq1 = est_eq(vq1, targets);
- eq2s = est_eq_front(targets);
- % for these simulation uses fixed EQ sample, rather than letting it vary frame by frame
- eq2 = eq2s(end,:);
-
- % first stage VQ -----------------
-
- errors1 = vq_targets(vq1, targets);
- errors1_eq1 = vq_targets(vq1, targets-eq1);
- errors1_eq2 = vq_targets(vq1, targets-eq2);
-
- % two stage mbest VQ --------------
-
- [errors2 targets_] = vq_targets2(vq1, vq2, targets);
- [errors2_eq1 targets_eq1_] = vq_targets2(vq1, vq2, targets-eq1);
- [errors2_eq2 targets_eq2_] = vq_targets2(vq1, vq2, targets-eq2);
-
- % save to .f32 files for listening tests
- if strcmp(vq_name,"train_120")
- save_f32(sprintf("../script/%s_vq2.f32", fn_targets{i}), targets_);
- save_f32(sprintf("../script/%s_vq2_eq1.f32", fn_targets{i}), targets_eq1_);
- save_f32(sprintf("../script/%s_vq2_eq2.f32", fn_targets{i}), targets_eq2_);
- else
- save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_);
- save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_);
- end
- printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i},
- var(targets(:)), var(errors1(:)), var(errors1_eq1(:)), var(errors1_eq2(:)),
- var(errors2(:)), var(errors2_eq1(:)), var(errors2_eq2(:)));
-
- figure(figs++); clf;
- %plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off;
- plot(mean(targets),'g;mean(targets);'); hold on; plot(mean(vq1),'g;mean(vq1);'); plot(eq2,'r;eq2;'); hold off;
- title(fn_targets{i}); axis([1 K -20 30]);
- end
-endfunction
-
-
-% interactve, menu driven frame by frame plots
-
-function interactive(fn_vq_txt, fn_target_f32)
- K = 20;
- vq = load("train_120_1.txt");
- [targets e] = load_targets(fn_target_f32);
- eq1 = est_eq(vq, targets);
-
- [errors1_eq2 eqs2] = vq_targets_adap_eq(vq, targets, zeros(1,K));
- [errors1_eq2 eqs2] = vq_targets_adap_eq(vq, targets, eqs2(end,:));
- eq2 = eqs2(end,:);
-
- figure(1); clf;
- mesh(e+targets)
- figure(2); clf;
- plot(eq1,'b;eq1;')
- hold on;
- plot(mean(targets),'c;mean(targets);'); plot(eq2,'g;eq2;');
- hold off;
- figure(3); clf; mesh(eqs2); title('eq2 evolving')
-
- % enter single step loop
- f = 20; neq = 0; eq=zeros(1,K);
- do
- figure(4); clf;
- t = targets(f,:) - eq;
- [mse_list index_list] = search_vq(vq, t, 1);
- error = t - vq(index_list(1),:);
- plot(e(f)+t,'b;target;');
- hold on;
- plot(e(f)+vq(index_list,:),'g;vq;');
- plot(error,'r;error;');
- plot(eq,'c;eq;');
- plot([1 K],[e(f) e(f)],'--')
- hold off;
- axis([1 K -20 80])
- % interactive menu
-
- printf("\r f: %2d eq: %d ind: %3d var: %3.1f menu: n-next b-back e-eq q-quit", f, neq, index_list(1), var(error));
- fflush(stdout);
- k = kbhit();
-
- if k == 'n' f+=1; end
- if k == 'e'
- neq++;
- end
- if neq == 3 neq = 0; end
- if neq == 0 eq = zeros(1,K); end
- if neq == 1 eq = eq1; end
- if neq == 2 eq = eqs2(f,:); end
- if k == 'b' f-=1; end
- until (k == 'q')
- printf("\n");
-endfunction
-
-
-% Experiment to test iterative approach of block update and remove
-% mean (ie frame energy), shows some promise at reducing HF energy
-% over several iterations while not affecting already good samples
-
-function experiment_iterate_block(fn_vq_txt, fn_target_f32)
- K = 20;
- vq = load("train_120_1.txt");
- [targets e] = load_targets(fn_target_f32);
-
- figure(1); clf;
- plot(mean(targets),'b;mean(targets);');
- hold on;
- plot(mean(vq), 'g;mean(vq);');
- figure(2); clf; hold on;
- eq = zeros(1,K);
- for i=1:3
- [errors eq] = vq_targets_block_eq(vq, targets, eq, 10);
- figure(1); plot(mean(targets-eq));
- figure(2); plot(eq);
- printf("i: %d %6.2f\n", i, var(errors(:)))
- end
-endfunction
-
-% Experiment to test EQ of input (before) VQ. We set a threshold on
-% when to equalise, so we don't upset already flat-ish samples. This
-% is the algorithm used for C at the time of writing (newamp1.c, newamp_700c.m)
-
-function experiment_front_eq(fn_vq_txt, fn_target_f32)
- K = 20;
- vq = load("train_120_1.txt");
- [targets e] = load_targets(fn_target_f32);
-
- [eqs ideal] = est_eq_front(targets);
-
- figure(1); clf;
- plot(mean(targets),'b;mean(targets);');
- hold on;
- plot(ideal, 'g;ideal;');
- plot(eqs(end,:), 'r;eq;');
- plot(mean(targets)-eqs(end,:), 'c;equalised;');
- plot(mean(vq),'b--;mean(vq);');
- hold off;
- figure(2); clf; mesh(eqs(1:100,:)); title('EQ weights over time');
- ylabel('Time (frames'); xlabel('Freq (mel)');
-endfunction
-
-more off
-
-% choose one of these to run first
-% You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files
-
-%interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32")
-%table_across_samples;
-%vq_700c_plots({"all_speech_8k.f32" "all_speech_8k_hp300.f32" "dev-clean-8k.f32" "train_8k.f32" } )
-%vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_ref.f32" "hts1a.f32" "vk5qi.f32"})
-%experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32")
-%experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32")
-%experiment_front_eq("train_120_1.txt", "cq_freedv_8k_lfboost.f32")
diff --git a/octave/vq_compare.m b/octave/vq_compare.m
deleted file mode 100644
index 0a156c1..0000000
--- a/octave/vq_compare.m
+++ /dev/null
@@ -1,349 +0,0 @@
-% vq_compare.m
-% David Rowe Sep 2021
-%
-% Compare the Eb/No performance of Vector Quantisers (robustness to bit errors) using
-% Spectral Distortion (SD) measure.
-
-#{
- usage:
-
- 1. Generate the initial VQ (vq_stage1.f32) and input test vector file (all_speech_8k_lim.f32):
-
- cd codec2/build_linux
- ../script/train_trellis.sh
-
- 2. Run the Psuedo-Gray binary switch tool to optimise the VQ against single bit errors:
-
- ./misc/vq_binary_switch -d 20 vq_stage1.f32 vq_stage1_bs001.f32 -m 5000 --st 2 --en 16 -f
-
- This can take a while, but if you ctrl-C at any time it will have saved the most recent optimised VQ.
-
- 3. Run this script to compare the two VQs:
-
- octave:34> vq_compare
-#}
-
-
-function vq_compare(action="run_curves", vq_fn, dec=1, EbNodB=3, in_fn, out_fn)
- more off;
- randn('state',1);
- graphics_toolkit("gnuplot");
-
- if strcmp(action, "run_curves")
- run_curves(30*100);
- end
- if strcmp(action, "vq_file")
- vq_file(vq_fn, dec, EbNodB, in_fn, out_fn)
- end
-endfunction
-
-
-% -------------------------------------------------------------------
-
-% converts a decimal value to a soft dec binary value
-function c = dec2sd(dec, nbits)
-
- % convert to binary
-
- c = zeros(1,nbits);
- for j=0:nbits-1
- mask = 2.^j;
- if bitand(dec,mask)
- c(nbits-j) = 1;
- end
- end
-
- % map to +/- 1
-
- c = -1 + 2*c;
-endfunction
-
-% fast version of vector quantiser
-function [indexes target_] = vector_quantiser_fast(vq, target, verbose=1)
- [vq_size K] = size(vq);
- [ntarget tmp] = size(target);
- target_ = zeros(ntarget,K);
- indexes = zeros(1,ntarget);
-
- % pre-compute energy of each VQ vector
- vqsq = zeros(vq_size,1);
- for i=1:vq_size
- vqsq(i) = vq(i,:)*vq(i,:)';
- end
-
- % use efficient matrix multiplies to search for best match to target
- for i=1:ntarget
- best_e = 1E32;
- e = vqsq - 2*(vq * target(i,:)');
- [best_e best_ind] = min(e);
- if verbose printf("best_e: %f best_ind: %d\n", best_e, best_ind), end;
- target_(i,:) = vq(best_ind,:); indexes(i) = best_ind;
- end
-endfunction
-
-
-% VQ a target sequence of frames then run a test using vanilla uncoded/trellis decoder
-function results = run_test(target, vq, EbNo, verbose)
- [frames tmp] = size(target);
- [vq_length tmp] = size(vq);
- nbits = log2(vq_length);
- nerrors = 0;
- tbits = 0;
- nframes = 0;
- nper = 0;
-
- % Vector Quantise target vectors sequence
- [tx_indexes target_ ] = vector_quantiser_fast(vq, target, verbose);
- % use convention of indexes starting from 0
- tx_indexes -= 1;
- % mean SD of VQ with no errors
- diff = target - target_;
- mse_noerrors = mean(diff(:).^2);
-
- % construct tx symbol codewords from VQ indexes
- tx_codewords = zeros(frames, nbits);
- for f=1:frames
- tx_codewords(f,:) = dec2sd(tx_indexes(f), nbits);
- end
-
- rx_codewords = tx_codewords + randn(frames, nbits)*sqrt(1/(2*EbNo));
- rx_indexes = zeros(1,frames);
-
- for f=1:frames
- tx_bits = tx_codewords(f,:) > 0;
- rx_bits = rx_codewords(f,:) > 0;
- rx_indexes(f) = sum(rx_bits .* 2.^(nbits-1:-1:0));
- errors = sum(xor(tx_bits, rx_bits));
- nerrors += errors;
- if errors nper++;, end
- tbits += nbits;
- nframes++;
- end
-
- EbNodB = 10*log10(EbNo);
- target_ = vq(rx_indexes+1,:);
- diff = target - target_;
- mse = mean(diff(:).^2);
- printf("Eb/No: %3.2f dB nframes: %3d nerrors: %4d BER: %4.3f PER: %3.2f mse: %3.2f %3.2f\n",
- EbNodB, nframes, nerrors, nerrors/tbits, nper/nframes, mse_noerrors, mse);
- results.ber = nerrors/tbits;
- results.per = nper/nframes;
- results.mse_noerrors = mse_noerrors;
- results.mse = mse;
- results.tx_indexes = tx_indexes;
- results.rx_indexes = rx_indexes;
-endfunction
-
-% VQ a target sequence of frames then run a test using a LDPC code
-function results = run_test_ldpc(target, vq, EbNo, verbose)
- [frames tmp] = size(target);
- [vq_length tmp] = size(vq);
- nbits = log2(vq_length);
- nerrors = 0;
- tbits = 0;
- nframes = 0;
- nper = 0;
-
- % init LDPC code
- mod_order = 4; bps = 2;
- modulation = 'QPSK';
- mapping = 'gray';
- max_iterations = 100; demod_type = 0; decoder_type = 0;
- ldpc; init_cml();
- tempStruct = load("HRA_56_56.txt");
- b = fieldnames(tempStruct);
- ldpcArrayName = b{1,1};
- % extract the array from the struct
- HRA = tempStruct.(ldpcArrayName);
- [code_param framesize rate] = ldpc_init_user(HRA, modulation, mod_order, mapping);
-
- % set up noise
- EbNodB = 10*log10(EbNo);
- EsNodB = EbNodB + 10*log10(rate) + 10*log10(bps);
- EsNo = 10^(EsNodB/10);
- variance = 1/EsNo;
-
- % Vector Quantise target vectors sequence
- [tx_indexes target_ ] = vector_quantiser_fast(vq, target, verbose);
- % use convention of indexes starting from 0
- tx_indexes -= 1;
- % mean SD of VQ with no errors
- diff = target - target_;
- mse_noerrors = mean(diff(:).^2);
-
- % construct tx frames x nbit matrix using VQ indexes
- tx_bits = zeros(frames, nbits);
- for f=1:frames
- tx_bits(f,:) = dec2sd(tx_indexes(f), nbits) > 0;
- end
-
- % find a superframe size, that has an integer number of nbits and data_bits_per_frame frames
- bits_per_superframe = nbits;
- while mod(bits_per_superframe,nbits) || mod(bits_per_superframe,code_param.data_bits_per_frame)
- bits_per_superframe += nbits;
- end
-
- Nsuperframes = floor(frames*nbits/bits_per_superframe);
- Nldpc_codewords = Nsuperframes*bits_per_superframe/code_param.data_bits_per_frame;
- frames = Nsuperframes*bits_per_superframe/nbits;
- %printf("bits_per_superframe: %d Nldpc_codewords: %d frames: %d\n", bits_per_superframe, Nldpc_codewords, frames);
-
- % reshape tx_bits matrix into Nldpc_codewords x data_bits_per_frame
- tx_bits = tx_bits(1:frames,:);
- tx_bits_ldpc = reshape(tx_bits',code_param.data_bits_per_frame, Nldpc_codewords)';
-
- % modulate tx symbols
- tx_symbols = [];
- for nn=1:Nldpc_codewords
- [tx_codeword atx_symbols] = ldpc_enc(tx_bits_ldpc(nn,:), code_param);
- tx_symbols = [tx_symbols atx_symbols];
- end
-
- noise = sqrt(variance*0.5)*(randn(1,length(tx_symbols)) + j*randn(1,length(tx_symbols)));
- rx_symbols = tx_symbols+noise;
-
- % LDPC decode
- for nn = 1:Nldpc_codewords
- st = (nn-1)*code_param.coded_syms_per_frame + 1;
- en = (nn)*code_param.coded_syms_per_frame;
-
- arx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_symbols(st:en), EsNo, ones(1,code_param.coded_syms_per_frame));
- rx_bits_ldpc(nn,:) = arx_codeword(1:code_param.data_bits_per_frame);
- end
-
- % reshape rx_bits_ldpc matrix into frames x nbits
- rx_bits = reshape(rx_bits_ldpc',nbits,frames)';
-
- rx_indexes = tx_indexes;
- for f=1:frames
- rx_indexes(f) = sum(rx_bits(f,:) .* 2.^(nbits-1:-1:0));
- errors = sum(xor(tx_bits(f,:), rx_bits(f,:)));
- nerrors += errors;
- if errors nper++;, end
- tbits += nbits;
- nframes++;
- end
-
- EbNodB = 10*log10(EbNo);
- target_ = vq(rx_indexes+1,:);
- diff = target - target_;
- mse = mean(diff(:).^2);
- printf("Eb/No: %3.2f dB nframes: %4d nerrors: %4d BER: %4.3f PER: %3.2f mse: %3.2f %3.2f\n",
- EbNodB, nframes, nerrors, nerrors/tbits, nper/nframes, mse_noerrors, mse);
- results.ber = nerrors/tbits;
- results.per = nper/nframes;
- results.mse = mse;
- results.tx_indexes = tx_indexes;
- results.rx_indexes = rx_indexes;
-endfunction
-
-% Simulations ---------------------------------------------------------------------
-
-% top level function to set up and run a test with a specific vq
-function [results target_] = run_test_vq(vq_fn, target_fn, nframes=100, dec=1, EbNodB=3, ldpc_en=0, verbose=0)
- K = 20; K_st=2+1; K_en=16+1;
-
- % load VQ
- vq = load_f32(vq_fn, K);
- [vq_size tmp] = size(vq);
- vqsub = vq(:,K_st:K_en);
-
- % load sequence of target vectors we wish to VQ
- target = load_f32(target_fn, K);
-
- % limit test to the first nframes vectors
- if nframes != -1
- last = nframes;
- else
- last = length(target);
- end
- target = target(1:dec:last, K_st:K_en);
-
- % run a test
- EbNo=10^(EbNodB/10);
- if ldpc_en
- results = run_test_ldpc(target, vqsub, EbNo, verbose);
- else
- results = run_test(target, vqsub, EbNo, verbose);
- end
- if verbose
- for f=2:nframes-1
- printf("f: %03d tx_index: %04d rx_index: %04d\n", f, results.tx_indexes(f), results.rx_indexes(f));
- end
- end
-
- % return full band vq-ed vectors
- target_ = zeros(last,K);
- target_(1:dec:last,:) = vq(results.rx_indexes+1,:);
-
- % use linear interpolation to restore original frame rate
- for f=1:dec:last-dec
- prev = f; next = f + dec;
- for g=prev+1:next-1
- cnext = (g-prev)/dec; cprev = 1 - cnext;
- target_(g,:) = cprev*target_(prev,:) + cnext*target_(next,:);
- %printf("f: %d g: %d cprev: %f cnext: %f\n", f, g, cprev, cnext);
- end
- end
-endfunction
-
-% generate sets of curves
-function run_curves(frames=100, dec=1)
- target_fn = "../build_linux/all_speech_8k_lim.f32";
- EbNodB = 0:5;
-
- results1_ldpc_log = [];
- for i=1:length(EbNodB)
- results = run_test_vq("../build_linux/vq_stage1.f32", target_fn, frames, dec, EbNodB(i), ldpc_en=1, verbose=0);
- results1_ldpc_log = [results1_ldpc_log results];
- end
- results4_ldpc_log = [];
- for i=1:length(EbNodB)
- results = run_test_vq("../build_linux/vq_stage1_bs004.f32", target_fn, frames, dec, EbNodB(i), ldpc_en=1, verbose=0);
- results4_ldpc_log = [results4_ldpc_log results];
- end
-
- results1_log = [];
- for i=1:length(EbNodB)
- results = run_test_vq("../build_linux/vq_stage1.f32", target_fn, frames, dec, EbNodB(i), ldpc_en=0, verbose=0);
- results1_log = [results1_log results];
- end
- results4_log = [];
- for i=1:length(EbNodB)
- results = run_test_vq("../build_linux/vq_stage1_bs004.f32", target_fn, frames, dec, EbNodB(i), ldpc_en=0, verbose=0);
- results4_log = [results4_log results];
- end
- for i=1:length(results1_log)
- ber(i) = results1_log(i).ber;
- per(i) = results1_log(i).per;
- mse_noerrors(i) = sqrt(results1_log(i).mse_noerrors);
- mse_vq1(i) = sqrt(results1_log(i).mse);
- mse_vq4(i) = sqrt(results4_log(i).mse);
- mse_vq1_ldpc(i) = sqrt(results1_ldpc_log(i).mse);
- mse_vq4_ldpc(i) = sqrt(results4_ldpc_log(i).mse);
- end
-
- figure(1); clf;
- semilogy(EbNodB, ber, 'g+-;ber;','linewidth', 2); hold on;
- semilogy(EbNodB, per, 'b+-;per;','linewidth', 2);
- grid('minor'); xlabel('Eb/No(dB)');
- hold off;
-
- figure(2); clf;
- plot(EbNodB, mse_noerrors, "b+-;no errors;"); hold on;
- plot(EbNodB, mse_vq1, "g+-;vanilla AWGN;");
- plot(EbNodB, mse_vq4, "b+-;binary switch;");
- plot(EbNodB, mse_vq1_ldpc, "r+-;ldpc (112,56);");
- plot(EbNodB, mse_vq4_ldpc, "k+-;binary switch ldpc (112,56);");
- load trellis_dec3_nstage3.txt
- plot(EbNodB, rms_sd, "c+-;binary switch trellis dec3;");
- hold off; grid; title("RMS SD (dB)"); xlabel('Eb/No(dB)');
-endfunction
-
-
-function vq_file(vq_fn, dec, EbNodB, in_fn, out_fn)
- [results target_] = run_test_vq(vq_fn, in_fn, nframes=-1, dec, EbNodB, verbose=0);
- save_f32(out_fn, target_);
-endfunction
-
-