From 953693521d9f064cbc29df88d05fcd3f51b60d51 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 30 Jun 2015 01:34:10 +0000 Subject: [PATCH] modified 1600 to freewheel through unreliable sync bits so we can hear entire signal when squelch is open git-svn-id: https://svn.code.sf.net/p/freetel/code@2227 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/trellis.m | 151 ++++++++++++++++++++++++++++++++++++ codec2-dev/src/freedv_api.c | 25 +++++- codec2-dev/src/freedv_api.h | 1 + 3 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 codec2-dev/octave/trellis.m diff --git a/codec2-dev/octave/trellis.m b/codec2-dev/octave/trellis.m new file mode 100644 index 00000000..89f4d55e --- /dev/null +++ b/codec2-dev/octave/trellis.m @@ -0,0 +1,151 @@ +% trellis.m +% David Rowe June 2015 +% +% Testing ideas for trellis decoding of codec parameters. Uses +% soft decision information, probablility of state transitions, +% and left over redundancy to correct errors on codec parameter +% reception. +% +% [ ] Add probability of transition +% [ ] Will this mess up a perfectly received signal, i.e. all +% codewords perfectly received. This should dominate prob +% calc (with small No) + +graphics_toolkit ("gnuplot"); +more off; + +function [tp codewords] = build_tp(bitstream_filename) + bits_per_frame = 28; + bit_fields = [1 5 3 3 2 4 3 3 2 2]; + nfields = length(bit_fields); + + % load encoded speech file (one float per bit) + + fbitstream = fopen(bitstream_filename, "rb"); + bitstream = fread(fbitstream, "float32"); + fclose(fbitstream); + nframes = floor(length(bitstream)/bits_per_frame); + bitstream = bitstream < 0; + + % extract LSPs codewords + + codewords = zeros(nframes,nfields); + for f=1:nframes + aframe = bitstream((f-1)*bits_per_frame+1:f*bits_per_frame); + field = 1; + st = bit_fields(field); + for l=1:nfields + nbits = bit_fields(field); + %printf("st: %d %d\n", st, st+nbits-1); + codeword = aframe(st:st+nbits-1)'; + %printf("codeword: %d\n", codeword); + codewords(f,l) = sum(codeword .* 2.^(nbits-1:-1:0)); + %printf("nbits: %d lsp(%d, %d) = %d\n", nbits, f, l, codewords(f,l)); + st += nbits; + field++; + end + end + + % determine transition probablilities of each codeword + % state at time n, state a time n+1 + % prob must add to 1 + % so for every state, of every codeword, compute histogram of + % transition probabilities + + tp = zeros(32,32,nfields); + for f=1:nframes-1 + for l=1:nfields + acodeword = codewords(f,l); + bcodeword = codewords(f+1,l); + %printf("%d %d %d %d\n", f, l, acodeword, bcodeword); + tp(acodeword+1,bcodeword+1,l)++; + end + end +endfunction + + +% y is vector of +/- 1 soft decision values for 0,1 transmitted bits + +function lnp = ln_prob_of_tx_codeword_c_given_rx_codeword_y(y) + nbits = length(y); + np = 2.^nbits; + + % work through all possible received codeworks and determine probability + % given a number of bits + + lnp = zeros(1,np); + for i=0:np-1 + + % convert to binary + + c = zeros(1,nbits); + for j=0:nbits-1 + mask = 2.^j; + if bitand(i,mask) + c(j+1) = 1; + end + end + + % map to +/- 1 + + c = 1 - 2*c; + + % probability calculation for this i + + lnp(i+1) = sum(y .* c); + end + +endfunction + + +% y is the received soft decision codedwords, each row is one codeword in time +% tp is the transition probabilities, each row is the start state +% returns the most likely transitted codeword c + +function c = find_most_likely_codeword(y, tp) + [nstates nbits] = size(y); + tp + y_n = y(1,:); % codeword received at time n + y_n_1 = y(2,:); % codeword received at time n+1 + + lnp_n = ln_prob_of_tx_codeword_c_given_rx_codeword_y(y_n); + lnp_n_1 = ln_prob_of_tx_codeword_c_given_rx_codeword_y(y_n_1); + + % determine probability of a path + % (prob of start state)(prob of transition)(prob of next state) + % cycle through all possibilities of states + % state variable for possible state + % step through them exhaustively + + max_prob = 0; + for n=1:nstates + for n_1=1:nstates + prob = lnp_n(n); + prob += tp(n, n_1); + prob += lnp_n_1(n_1); + printf("state: %d %d %f\n", n, n_1, prob); + if (prob > max_prob) + max_prob = prob; + max_n = n; max_n_1 = n; + end + end + end + +endfunction + +% for a given parameter +% weight for No +% given received symbols y(n) and y(n+1) +% calculate all possible paths +% select most likely + + +printf("loading training database and generating tp .... "); +[tp codewords] = build_tp("hts.bit"); +printf("done\n"); + +y = [-1 -1; -1 -1]; +find_most_likely_codeword(y,tp(1:4,1:4,5)) + +% TODO: normalise tp (is this rqd? Just a const?), ln(tp), add No to calculation +% then test! Try to insert in channel and correct errors diff --git a/codec2-dev/src/freedv_api.c b/codec2-dev/src/freedv_api.c index 4be815c5..9e846cfc 100644 --- a/codec2-dev/src/freedv_api.c +++ b/codec2-dev/src/freedv_api.c @@ -96,6 +96,7 @@ struct freedv *freedv_open(int mode) { f->rx_bits = (int*)malloc(nbit*sizeof(int)); if ((f->tx_bits == NULL) || (f->rx_bits == NULL)) return NULL; + f->evenframe = 0; } if (mode == FREEDV_MODE_700) { @@ -466,6 +467,7 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { int recd_codeword, codeword1, data_flag_index, n_ascii; short abit[1]; char ascii_out; + int reliable_sync_bit; assert(f->nin <= f->n_max_modem_samples); @@ -477,7 +479,6 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { nout = f->n_speech_samples; if (f->mode == FREEDV_MODE_1600) { - int reliable_sync_bit; bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv); @@ -487,8 +488,12 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { f->sync = f->fdmdv->sync; f->snr_est = f->stats.snr_est; + if (reliable_sync_bit == 1) { + f->evenframe = 1; + } + if (f->stats.sync) { - if (reliable_sync_bit == 0) { + if (f->evenframe == 0) { memcpy(f->rx_bits, f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int)); nout = 0; } @@ -588,18 +593,31 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { /* squelch if beneath SNR threshold or test frames enabled */ if ((f->squelch_en && (f->stats.snr_est < f->snr_squelch_thresh)) || f->test_frames) { + //fprintf(stderr,"squelch %f %f !\n", f->stats.snr_est, f->snr_squelch_thresh); for(i=0; in_speech_samples; i++) speech_out[i] = 0; } nout = f->n_speech_samples; + } + + /* note this freewheels if reliable sync dissapears on bad channels */ + + if (f->evenframe) + f->evenframe = 0; + else + f->evenframe = 1; + //fprintf(stderr,"%d\n", f->evenframe); + } /* if (sync) .... */ else { /* if not in sync pass through analog samples */ /* this lets us "hear" whats going on, e.g. during tuning */ - if (f->squelch_en == 0) { + //fprintf(stderr, "out of sync\n"); + + if (f->squelch_en == 0) { for(i=0; istats.sync: %d reliable_sync_bit: %d evenframe: %d nout: %d\n", f->stats.sync, reliable_sync_bit, f->evenframe, nout); return nout; } diff --git a/codec2-dev/src/freedv_api.h b/codec2-dev/src/freedv_api.h index 275c1fb2..eac86c77 100644 --- a/codec2-dev/src/freedv_api.h +++ b/codec2-dev/src/freedv_api.h @@ -75,6 +75,7 @@ struct freedv { int total_bit_errors; int sync; + int evenframe; float snr_est; float snr_squelch_thresh; float squelch_en; -- 2.25.1