-% cohpsk_demod.m
+% cohpsk_demod_plot.m
% David Rowe May 2015
%
-% Plot Octave outputs from cohpsk_demod_plot
+% Plot Octave outputs from cohpsk_demod, c2dec, to visualise whats going on
+% when errors hit the system
-Nc=7; Nd=2;
+% $ ./c2enc 700 ../../raw/ve9qrp_10s.raw - | ./cohpsk_mod - - | ./cohpsk_ch - - -60 50 1 1 | ./cohpsk_demod - - | ./c2dec 700 - - --dump ve9qrp | play -t raw -r 8000 -s -2 - -q
+
+% ./c2enc 700 ../../raw/ve9qrp_10s.raw - | ./cohpsk_mod - - | ./cohpsk_ch - - -30 50 1 1 | ./cohpsk_demod - - | ./c2dec 700 - - --dump ve9qrp_snr3 | play -t raw -r 8000 -s -2 - -q
+
+graphics_toolkit ("gnuplot");
+
+Nc=7; Nd=2; Ns=6;
load ../build_linux/src/cohpsk_demod.txt
load ../build_linux/src/cohpsk_put_test_bits.txt
-
+load ../build_linux/src/ve9qrp_lsp_.txt
+load ../build_linux/src/ve9qrp_snr3_lsp_.txt
+load ../build_linux/src/ve9qrp_ak_.txt
+load ../build_linux/src/ve9qrp_snr3_ak_.txt
+load ../build_linux/src/ve9qrp_model.txt
+load ../build_linux/src/ve9qrp_snr3_model.txt
+load ../build_linux/src/ve9qrp_snr3_softdec.txt
+
+Ncf = 50; % number of codec frames to plot
+Nmf = Ncf/2; % number of modem frames to plot
+Nms = Nmf*Ns; % number of modem symbols to plot
+
figure(1)
clf;
figure(2)
clf;
subplot(211)
-plot(rx_phi_log_c)
+plot(rx_phi_log_c(1:Nms,:))
title('phase')
+axis([1 Nms -pi pi])
subplot(212)
-plot(rx_amp_log_c)
-title('amplitide')
+plot(rx_amp_log_c(1:Nms,:))
+title('amplitude')
+axis([1 Nms 0 1])
figure(3)
subplot(211)
figure(4);
clf;
-plot(nerr_log_c);
+plot(nerr_log_c(1:Ncf));
title('Bit Errors');
+xlabel('Codec Frame')
figure(5);
clf;
title('Error Position Histogram');
figure(6)
-y = 1:length(rx_amp_log_c);
+y = 1:Nms;
x = 1:Nc*Nd;
-mesh(x,y,20*log10(rx_amp_log_c));
+z = 20*log10(rx_amp_log_c(1:Nms,:));
+mesh(x,y,z);
grid
title('Channel Amplitude dB');
+a = min(min(z));
+b = max(max(z));
+axis([1 Nc*Nd 1 Nms a b])
+
+% work out alignment, as they sync at different times
+
+min_e = 1E6;
+for i=1:10
+ l1 = length(ve9qrp_lsp_);
+ l2 = length(ve9qrp_snr3_lsp_);
+ st = i; en = min(l1+i-1,l2);
+ d = ve9qrp_lsp_(st:en, 1:6) - ve9qrp_snr3_lsp_(1:en-st+1, 1:6);
+ e = sum(sum(abs(d)));
+ if e < min_e
+ min_e = e;
+ min_i = i;
+ end
+end
+printf("time offset between clean and 3dB is %d codec frames\n", min_i);
+
+% LSP trajectories
+
+figure(7)
+clf
+st = min_i; en = 50;
+plot(ve9qrp_snr3_lsp_(1:en-st+1, 1:6),'r--')
+hold on
+plot(ve9qrp_lsp_(st:en, 1:6),'g')
+hold off
+
+% Spectral distortion of LPCs
+
+figure(8)
+clf;
+f1=fft(ve9qrp_ak_(st:en,:)',128);
+f2=fft(ve9qrp_snr3_ak_(1:en-st+1,:)',128);
+d = (20*log10(abs(f1)) - 20*log10(abs(f2)));
+sdsq = mean(d.^2);
+plot(sdsq)
+title('spectral distortion clean and channel SNR=3dB')
+
+figure(9)
+clf;
+y = 1:en-st+1;
+x = 1:40;
+%mesh(y,x,-20*log10(abs(f2(1:40,:))));
+mesh(y,x,d(1:40,:));
+grid
+title('Synthesis filter difference between clean and channel SNR=3dB');
+xlabel('Time (codec frames)')
+ylabel('Frequency 0 to 2500Hz');
+zlabel('Difference (dB)');
% + ssb filter
% + compression
% + make sure it's flat with many errors
+% [ ] linear tracking of ampl ests
+% + seem to only change every
graphics_toolkit ("gnuplot");
more off;
FILE *fout;
FILE *fber = NULL;
short *buf;
- unsigned char *bits, *prev_bits;
- int *unpacked_bits;
+ unsigned char *bits;
+ float *softdec_bits;
int nsam, nbit, nbyte, i, byte, frames, bits_proc, bit_errors, error_mode;
int nstart_bit, nend_bit, bit_rate;
int state, next_state;
float ber, r, burst_length, burst_period, burst_timer, ber_est;
unsigned char mask;
- int natural, dump, unpacked, bit, ret;
+ int natural, dump, softdec, bit, ret;
char* opt_string = "h:";
struct option long_options[] = {
{ "endbit", required_argument, NULL, 0 },
{ "berfile", required_argument, NULL, 0 },
{ "natural", no_argument, &natural, 1 },
- { "unpacked", no_argument, &unpacked, 1 },
+ { "softdec", no_argument, &softdec, 1 },
#ifdef DUMP
{ "dump", required_argument, &dump, 1 },
#endif
buf = (short*)malloc(nsam*sizeof(short));
nbyte = (nbit + 7) / 8;
bits = (unsigned char*)malloc(nbyte*sizeof(char));
- unpacked_bits = (int*)malloc(nbit*sizeof(int));
- prev_bits = (unsigned char*)malloc(nbyte*sizeof(char));
+ softdec_bits = (int*)malloc(nbit*sizeof(float));
frames = bit_errors = bits_proc = 0;
nstart_bit = 0;
nend_bit = nbit-1;
codec2_set_natural_or_gray(codec2, !natural);
//printf("%d %d\n", nstart_bit, nend_bit);
- if (unpacked)
- ret = (fread(unpacked_bits, sizeof(int), nbit, fin) == (size_t)nbit);
+ if (softdec)
+ ret = (fread(softdec_bits, sizeof(float), nbit, fin) == (size_t)nbit);
else
ret = (fread(bits, sizeof(char), nbyte, fin) == (size_t)nbyte);
// apply bit errors, MSB of byte 0 is bit 0 in frame, only works in packed mode
if ((error_mode == UNIFORM) || (error_mode == UNIFORM_RANGE)) {
- assert(unpacked == 0);
+ assert(softdec == 0);
for(i=nstart_bit; i<nend_bit+1; i++) {
r = (float)rand()/RAND_MAX;
if (r < ber) {
}
if (error_mode == TWO_STATE) {
- assert(unpacked == 0);
+ assert(softdec == 0);
burst_timer += (float)nbit/bit_rate;
fprintf(stderr, "burst_timer: %f state: %d\n", burst_timer, state);
else
ber_est = 0.0;
- if (unpacked) {
+ if (softdec) {
/* pack bits, MSB received first */
bit = 7; byte = 0;
memset(bits, 0, nbyte);
for(i=0; i<nbit; i++) {
- bits[byte] |= (unpacked_bits[i] << bit);
+ bits[byte] |= ((softdec_bits[i] < 0.0) << bit);
bit--;
if (bit < 0) {
bit = 7;
if (fout == stdout) fflush(stdout);
if (fin == stdin) fflush(stdin);
- memcpy(prev_bits, bits, nbyte);
-
- if (unpacked)
- ret = (fread(unpacked_bits, sizeof(int), nbit, fin) == (size_t)nbit);
+ if (softdec)
+ ret = (fread(softdec_bits, sizeof(float), nbit, fin) == (size_t)nbit);
else
ret = (fread(bits, sizeof(char), nbyte, fin) == (size_t)nbyte);
}
free(buf);
free(bits);
- free(unpacked_bits);
+ free(softdec_bits);
fclose(fin);
fclose(fout);
assert(c2->bpf_buf != NULL);
for(i=0; i<BPF_N+4*N; i++)
c2->bpf_buf[i] = 0.0;
+
+ c2->softdec = NULL;
return c2;
}
synthesise_one_frame(c2, &speech[N*i], &model[i], Aw);
}
+ #ifdef DUMP
+ dump_lsp_(&lsps[3][0]);
+ dump_ak_(&ak[3][0], LPC_ORD_LOW);
+ dump_model(&model[3]);
+ if (c2->softdec)
+ dump_softdec(c2->softdec, nbit);
+ #endif
+
/* update memories for next frame ----------------------------*/
c2->prev_model_dec = model[3];
void cohpsk_destroy(struct COHPSK *coh);
void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[]);
void cohpsk_clip(COMP tx_fdm[]);
-void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame);
+void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame);
#endif
float w[M]; /* time domain hamming window */
COMP W[FFT_ENC]; /* DFT of w[] */
float Pn[2*N]; /* trapezoidal synthesis window */
- float *bpf_buf; /* buffer for band pass filter */
+ float *bpf_buf; /* buffer for band pass filter */
float Sn[M]; /* input speech */
float hpf_states[2]; /* high pass filter states */
void *nlp; /* pitch predictor states */
float xq_dec[2];
int smoothing; /* enable smoothing for channels with errors */
+ float *softdec; /* optional soft decn bits from demod */
};
#endif
\*---------------------------------------------------------------------------*/
-void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC*ND])
+void qpsk_symbols_to_bits(struct COHPSK *coh, float rx_bits[], COMP ct_symb_buf[][COHPSK_NC*ND])
{
int p, r, c, i, pc, d;
float x[NPILOTSFRAME+2], x1;
}
rot = cmult(div_symb, pi_on_4);
i = c*NSYMROW + r;
- rx_bits[2*i+1] = rot.real < 0;
- rx_bits[2*i] = rot.imag < 0;
+ rx_bits[2*i+1] = rot.real;
+ rx_bits[2*i] = rot.imag;
}
}
}
\*---------------------------------------------------------------------------*/
-void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame)
+void cohpsk_demod(struct COHPSK *coh, float rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame)
{
COMP ch_symb[NSW*NSYMROWPILOT][COHPSK_NC*ND];
int i, j, sync, anext_sync, next_sync, nin, r, c;
#include "ssbfilt_coeff.h"
#include "codec2_fdmdv.h"
-#define BUF_N 160
-#define HF_DELAY_MS 2.0
-#define PAPR_TARGET 7.0
+#define BUF_N 160
+#define FAST_FADING_DELAY_MS 2.0
+#define SLOW_FADING_DELAY_MS 0.5
+#define PAPR_TARGET 7.0
/* This file gets generated using the function write_noise_file in tcohpsk.m. You have to run
tcohpsk first (any variant) to load the function into Octave, e.g.:
octave:18> write_noise_file("../raw/fading_samples.float", 7500, 7500*60)
*/
-#define FADING_FILE_NAME "../../raw/fading_samples.float"
+#define FAST_FADING_FILE_NAME "../../raw/fast_fading_samples.float"
+#define SLOW_FADING_FILE_NAME "../../raw/slow_fading_samples.float"
int main(int argc, char *argv[])
{
inclip = atof(argv[6]);
}
else {
- fprintf(stderr, "usage: %s InputRealModemRawFileFs7500Hz OutputRealModemRawFileFs7500Hz No(dB/Hz) FoffHz FadingEn InputClip0to1\n", argv[0]);
+ fprintf(stderr, "usage: %s InputRealModemRawFileFs7500Hz OutputRealModemRawFileFs7500Hz No(dB/Hz) FoffHz Fading[0-none 1-fast 2-slow] InputClip0to1\n", argv[0]);
exit(1);
}
fprintf(stderr, "NodB: %4.2f foff: %4.2f Hz fading: %d inclip: %4.2f\n", NodB, foff_hz, fading_en, inclip);
/* init HF fading model */
if (fading_en) {
- ffading = fopen(FADING_FILE_NAME, "rb");
- if (ffading == NULL) {
- printf("Can't find fading file: %s\n", FADING_FILE_NAME);
- exit(1);
+ if (fading_en == 1) {
+ ffading = fopen(FAST_FADING_FILE_NAME, "rb");
+ if (ffading == NULL) {
+ printf("Can't find fast fading file: %s\n", FAST_FADING_FILE_NAME);
+ exit(1);
+ }
+ nhfdelay = floor(FAST_FADING_DELAY_MS*COHPSK_FS/1000);
+ }
+
+ if (fading_en == 2) {
+ ffading = fopen(SLOW_FADING_FILE_NAME, "rb");
+ if (ffading == NULL) {
+ printf("Can't find slow fading file: %s\n", SLOW_FADING_FILE_NAME);
+ exit(1);
+ }
+ nhfdelay = floor(SLOW_FADING_DELAY_MS*COHPSK_FS/1000);
}
- nhfdelay = floor(HF_DELAY_MS*COHPSK_FS/1000);
+
ch_fdm_delay = (COMP*)malloc((nhfdelay+COHPSK_SAMPLES_PER_FRAME)*sizeof(COMP));
assert(ch_fdm_delay != NULL);
for(i=0; i<nhfdelay+COHPSK_SAMPLES_PER_FRAME; i++) {
{
FILE *fin, *fout, *foct;
struct COHPSK *cohpsk;
- int rx_bits[COHPSK_BITS_PER_FRAME];
+ float rx_bits[COHPSK_BITS_PER_FRAME];
COMP rx_fdm[COHPSK_SAMPLES_PER_FRAME];
short rx_fdm_scaled[COHPSK_SAMPLES_PER_FRAME];
int frames, reliable_sync_bit, nin_frame;
cohpsk_demod(cohpsk, rx_bits, &reliable_sync_bit, rx_fdm, &nin_frame);
if (reliable_sync_bit) {
- fwrite(rx_bits, sizeof(int), COHPSK_BITS_PER_FRAME, fout);
+ fwrite(rx_bits, sizeof(float), COHPSK_BITS_PER_FRAME, fout);
if (oct) {
for(r=0; r<NSYMROW; r++, log_data_r++) {
};
void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits);
-void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC*COHPSK_ND]);
+void qpsk_symbols_to_bits(struct COHPSK *coh, float rx_bits[], COMP ct_symb_buf[][COHPSK_NC*COHPSK_ND]);
void tx_filter_and_upconvert_coh(COMP tx_fdm[], int Nc, COMP tx_symbols[],
COMP tx_filter_memory[COHPSK_NC][COHPSK_NSYM],
COMP phase_tx[], COMP freq[],
int main(int argc, char *argv[])
{
FILE *fin, *foct;
+ float rx_bits_sd[COHPSK_BITS_PER_FRAME];
int rx_bits[COHPSK_BITS_PER_FRAME];
int *ptest_bits_coh, *ptest_bits_coh_end;
int state, next_state, i, nbits, errors, nerrors;
ptest_bits_coh_end = (int*)test_bits_coh + sizeof(test_bits_coh)/sizeof(int);
state = 0; nbits = 0; nerrors = 0;
- while (fread(rx_bits, sizeof(int), COHPSK_BITS_PER_FRAME, fin) == COHPSK_BITS_PER_FRAME) {
+ while (fread(rx_bits_sd, sizeof(float), COHPSK_BITS_PER_FRAME, fin) == COHPSK_BITS_PER_FRAME) {
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++) {
+ rx_bits[i] = rx_bits_sd[i] < 0.0;
+ //fprintf(stderr,"%f %d\n", rx_bits_sd[i], rx_bits[i]);
+ }
errors = 0;
for(i=0; i<COHPSK_BITS_PER_FRAME; i++) {
static FILE *fsw = NULL;
static FILE *few = NULL;
static FILE *fsw_ = NULL;
+static FILE *fsoftdec = NULL;
static FILE *fmodel = NULL;
static FILE *fqmodel = NULL;
static FILE *fpwb = NULL;
fclose(few);
if (fmodel != NULL)
fclose(fmodel);
+ if (fsoftdec != NULL)
+ fclose(fsoftdec);
if (fqmodel != NULL)
fclose(fqmodel);
if (fpwb != NULL)
fprintf(few,"\n");
}
+void dump_softdec(float *softdec, int n)
+{
+ int i;
+ char s[MAX_STR];
+
+ if (!dumpon) return;
+
+ if (fsoftdec == NULL) {
+ sprintf(s,"%s_softdec.txt", prefix);
+ fsoftdec = fopen(s, "wt");
+ assert(fsoftdec != NULL);
+ }
+
+ for(i=0; i<n; i++)
+ fprintf(fsoftdec,"%f\t", softdec[i]);
+ fprintf(fsoftdec,"\n");
+}
+
void dump_model(MODEL *model) {
int l;
char s[MAX_STR];
void dump_Sw(COMP Sw[]);
void dump_Sw_(COMP Sw_[]);
void dump_Ew(COMP Ew[]);
+void dump_softdec(float *softdec, int n);
/* amplitude modelling */
COMP ch_fdm_frame[COHPSK_M*NSYMROWPILOT];
//COMP rx_fdm_frame_bb[M*NSYMROWPILOT];
//COMP ch_symb[NSYMROWPILOT][COHPSK_NC*ND];
+ float rx_bits_sd[COHPSK_BITS_PER_FRAME];
int rx_bits[COHPSK_BITS_PER_FRAME];
int tx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES];
assert(ch_fdm_frame_log_index < COHPSK_M*NSYMROWPILOT*FRAMES);
tmp = nin_frame;
- cohpsk_demod(coh, rx_bits, &reliable_sync_bit, &ch_fdm_frame_log_out[ch_fdm_frame_log_index], &nin_frame);
+ cohpsk_demod(coh, rx_bits_sd, &reliable_sync_bit, &ch_fdm_frame_log_out[ch_fdm_frame_log_index], &nin_frame);
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+ rx_bits[i] = rx_bits_sd[i] > 0.0;
+
ch_fdm_frame_log_index += tmp;
/* --------------------------------------------------------*\
COMP ch_fdm[COHPSK_SAMPLES_PER_FRAME];
COMP ch_buf[CH_BUF_SZ];
int rx_bits[COHPSK_BITS_PER_FRAME];
+ float rx_bits_sd[COHPSK_BITS_PER_FRAME];
float *rx_amp_log;
float *rx_phi_log;
COMP *rx_symb_log;
coh->frame = f;
tmp = nin_frame;
- cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_buf, &tmp);
+ cohpsk_demod(coh, rx_bits_sd, &reliable_sync_bit, ch_buf, &tmp);
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+ rx_bits[i] = rx_bits_sd[i] > 0.0;
+
ch_buf_n -= nin_frame;
//printf("nin_frame: %d tmp: %d ch_buf_n: %d\n", nin_frame, tmp, ch_buf_n);
assert(ch_buf_n >= 0);