From 13273437267e3ed6ca8792a4c41947780c56a780 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 2 Jun 2015 05:08:36 +0000 Subject: [PATCH] modifying cohpsk demod and support code for soft dec git-svn-id: https://svn.code.sf.net/p/freetel/code@2170 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/cohpsk_demod_plot.m | 94 ++++++++++++++++++++++++--- codec2-dev/octave/tcohpsk.m | 2 + codec2-dev/src/c2dec.c | 31 ++++----- codec2-dev/src/codec2.c | 10 +++ codec2-dev/src/codec2_cohpsk.h | 2 +- codec2-dev/src/codec2_internal.h | 3 +- codec2-dev/src/cohpsk.c | 8 +-- codec2-dev/src/cohpsk_ch.c | 34 +++++++--- codec2-dev/src/cohpsk_demod.c | 4 +- codec2-dev/src/cohpsk_internal.h | 2 +- codec2-dev/src/cohpsk_put_test_bits.c | 7 +- codec2-dev/src/dump.c | 21 ++++++ codec2-dev/src/dump.h | 1 + codec2-dev/unittest/tcohpsk.c | 6 +- codec2-dev/unittest/test_cohpsk_ch.c | 6 +- 15 files changed, 182 insertions(+), 49 deletions(-) diff --git a/codec2-dev/octave/cohpsk_demod_plot.m b/codec2-dev/octave/cohpsk_demod_plot.m index cbe5ca55..2d4ab30d 100644 --- a/codec2-dev/octave/cohpsk_demod_plot.m +++ b/codec2-dev/octave/cohpsk_demod_plot.m @@ -1,13 +1,31 @@ -% 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; @@ -24,11 +42,13 @@ axis([-2 2 -2 2]) 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) @@ -40,8 +60,9 @@ title('Sync ratio'); figure(4); clf; -plot(nerr_log_c); +plot(nerr_log_c(1:Ncf)); title('Bit Errors'); +xlabel('Codec Frame') figure(5); clf; @@ -49,8 +70,61 @@ plot(error_positions_hist_c); 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)'); diff --git a/codec2-dev/octave/tcohpsk.m b/codec2-dev/octave/tcohpsk.m index 8ffeb866..93eadb94 100644 --- a/codec2-dev/octave/tcohpsk.m +++ b/codec2-dev/octave/tcohpsk.m @@ -51,6 +51,8 @@ % + 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; diff --git a/codec2-dev/src/c2dec.c b/codec2-dev/src/c2dec.c index 2330c910..cb20bd9d 100644 --- a/codec2-dev/src/c2dec.c +++ b/codec2-dev/src/c2dec.c @@ -50,14 +50,14 @@ int main(int argc, char *argv[]) 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[] = { @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { "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 @@ -124,8 +124,7 @@ int main(int argc, char *argv[]) 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; @@ -175,8 +174,8 @@ int main(int argc, char *argv[]) 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); @@ -186,7 +185,7 @@ int main(int argc, char *argv[]) // 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; ibpf_buf != NULL); for(i=0; ibpf_buf[i] = 0.0; + + c2->softdec = NULL; return c2; } @@ -1487,6 +1489,14 @@ void codec2_decode_700(struct CODEC2 *c2, short speech[], const unsigned char * 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]; diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index 387e75a6..9dce5806 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -42,6 +42,6 @@ struct COHPSK *cohpsk_create(void); 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 diff --git a/codec2-dev/src/codec2_internal.h b/codec2-dev/src/codec2_internal.h index bb1f207b..44ff177f 100644 --- a/codec2-dev/src/codec2_internal.h +++ b/codec2-dev/src/codec2_internal.h @@ -35,7 +35,7 @@ struct CODEC2 { 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 */ @@ -59,6 +59,7 @@ struct CODEC2 { float xq_dec[2]; int smoothing; /* enable smoothing for channels with errors */ + float *softdec; /* optional soft decn bits from demod */ }; #endif diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index 0802de0d..fbbc91f8 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -266,7 +266,7 @@ void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits \*---------------------------------------------------------------------------*/ -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; @@ -350,8 +350,8 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][ } 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; } } } @@ -905,7 +905,7 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM \*---------------------------------------------------------------------------*/ -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; diff --git a/codec2-dev/src/cohpsk_ch.c b/codec2-dev/src/cohpsk_ch.c index 539de498..6258c285 100644 --- a/codec2-dev/src/cohpsk_ch.c +++ b/codec2-dev/src/cohpsk_ch.c @@ -50,9 +50,10 @@ #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.: @@ -61,7 +62,8 @@ 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[]) { @@ -107,7 +109,7 @@ 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); @@ -128,12 +130,24 @@ int main(int argc, char *argv[]) /* 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 0.0; + ch_fdm_frame_log_index += tmp; /* --------------------------------------------------------*\ diff --git a/codec2-dev/unittest/test_cohpsk_ch.c b/codec2-dev/unittest/test_cohpsk_ch.c index 82530265..32f40f82 100644 --- a/codec2-dev/unittest/test_cohpsk_ch.c +++ b/codec2-dev/unittest/test_cohpsk_ch.c @@ -68,6 +68,7 @@ int main(int argc, char *argv[]) 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; @@ -248,7 +249,10 @@ int main(int argc, char *argv[]) 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 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); -- 2.25.1