modified 1600 to freewheel through unreliable sync bits so we can hear entire signal...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 30 Jun 2015 01:34:10 +0000 (01:34 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 30 Jun 2015 01:34:10 +0000 (01:34 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2227 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/trellis.m [new file with mode: 0644]
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h

diff --git a/codec2-dev/octave/trellis.m b/codec2-dev/octave/trellis.m
new file mode 100644 (file)
index 0000000..89f4d55
--- /dev/null
@@ -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
index 4be815c5cdbe5a4fed8592e2ab12688419ea6909..9e846cfc7e55f002062eb28376926f90100cf57f 100644 (file)
@@ -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; i<f->n_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; i<nin_prev; i++)
                     speech_out[i] = FDMDV_SCALE*demod_in[i].real;
             }
@@ -724,6 +742,7 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
 
     }
      
+    //fprintf(stderr,"f->stats.sync: %d reliable_sync_bit: %d evenframe: %d nout: %d\n", f->stats.sync, reliable_sync_bit, f->evenframe, nout);
     return nout;
 }
 
index 275c1fb2013971fd4bbfd1616eebb0003fde1b63..eac86c77313c053cdf1c42db9f9359fa01dc4c60 100644 (file)
@@ -75,6 +75,7 @@ struct freedv {
     int                  total_bit_errors;
 
     int                  sync;
+    int                  evenframe;
     float                snr_est;
     float                snr_squelch_thresh;
     float                squelch_en;