simple simulation of multipath burst errors, but probably best to use pathsim on...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 18 Feb 2013 01:30:30 +0000 (01:30 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 18 Feb 2013 01:30:30 +0000 (01:30 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1161 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/Makefile.am
codec2-dev/src/Makefile.in
codec2-dev/src/sim_multipath_errors.c [new file with mode: 0644]

index 853b644b45cf0c7597e72a91c191013bcc2153b9..51064d89a697cfb3721de9b4e349b2071c13e43c 100644 (file)
@@ -146,7 +146,7 @@ libcodec2_la_LDFLAGS = $(LIBS)
 library_includedir = $(prefix)/include
 library_include_HEADERS        = codec2.h codec2_fdmdv.h codec2_fifo.h
 
-bin_PROGRAMS = c2demo c2enc c2dec c2sim fdmdv_get_test_bits fdmdv_mod fdmdv_demod fdmdv_put_test_bits fdmdv_interleave
+bin_PROGRAMS = c2demo c2enc c2dec c2sim fdmdv_get_test_bits fdmdv_mod fdmdv_demod fdmdv_put_test_bits fdmdv_interleave sim_multipath_errors
 
 c2demo_SOURCES = c2demo.c
 c2demo_LDADD = $(lib_LTLIBRARIES) 
@@ -179,3 +179,6 @@ fdmdv_put_test_bits_LDFLAGS = $(LIBS)
 fdmdv_interleave_SOURCES = fdmdv_interleave.c
 fdmdv_interleave_LDFLAGS = $(LIBS)
 
+sim_multipath_errors_SOURCES =  sim_multipath_errors.c
+sim_multipath_errors_LDFLAGS = $(LIBS)
+
index f59392a7b681a25c5936e879919affa306e895d7..85c74a8a62f3b6ffe052be5324a46b71fe33a7d8 100644 (file)
@@ -42,7 +42,7 @@ noinst_PROGRAMS = generate_codebook$(EXEEXT) genlspdtcb$(EXEEXT)
 bin_PROGRAMS = c2demo$(EXEEXT) c2enc$(EXEEXT) c2dec$(EXEEXT) \
        c2sim$(EXEEXT) fdmdv_get_test_bits$(EXEEXT) fdmdv_mod$(EXEEXT) \
        fdmdv_demod$(EXEEXT) fdmdv_put_test_bits$(EXEEXT) \
-       fdmdv_interleave$(EXEEXT)
+       fdmdv_interleave$(EXEEXT) sim_multipath_errors$(EXEEXT)
 subdir = src
 DIST_COMMON = $(library_include_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in
@@ -115,6 +115,9 @@ generate_codebook_LDADD = $(LDADD)
 genlspdtcb_SOURCES = genlspdtcb.c
 genlspdtcb_OBJECTS = genlspdtcb.$(OBJEXT)
 genlspdtcb_LDADD = $(LDADD)
+am_sim_multipath_errors_OBJECTS = sim_multipath_errors.$(OBJEXT)
+sim_multipath_errors_OBJECTS = $(am_sim_multipath_errors_OBJECTS)
+sim_multipath_errors_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I. -I$(srcdir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -130,13 +133,14 @@ SOURCES = $(libcodec2_la_SOURCES) $(c2dec_SOURCES) $(c2demo_SOURCES) \
        $(c2enc_SOURCES) $(c2sim_SOURCES) $(fdmdv_demod_SOURCES) \
        $(fdmdv_get_test_bits_SOURCES) $(fdmdv_interleave_SOURCES) \
        $(fdmdv_mod_SOURCES) $(fdmdv_put_test_bits_SOURCES) \
-       generate_codebook.c genlspdtcb.c
+       generate_codebook.c genlspdtcb.c \
+       $(sim_multipath_errors_SOURCES)
 DIST_SOURCES = $(libcodec2_la_SOURCES) $(c2dec_SOURCES) \
        $(c2demo_SOURCES) $(c2enc_SOURCES) $(c2sim_SOURCES) \
        $(fdmdv_demod_SOURCES) $(fdmdv_get_test_bits_SOURCES) \
        $(fdmdv_interleave_SOURCES) $(fdmdv_mod_SOURCES) \
        $(fdmdv_put_test_bits_SOURCES) generate_codebook.c \
-       genlspdtcb.c
+       genlspdtcb.c $(sim_multipath_errors_SOURCES)
 library_includeHEADERS_INSTALL = $(INSTALL_HEADER)
 HEADERS = $(library_include_HEADERS)
 ETAGS = etags
@@ -348,7 +352,7 @@ codebookge.c
 libcodec2_la_CFLAGS = $(AM_CFLAGS)
 libcodec2_la_LDFLAGS = $(LIBS)
 library_includedir = $(prefix)/include
-library_include_HEADERS = codec2.h
+library_include_HEADERS = codec2.h codec2_fdmdv.h codec2_fifo.h
 c2demo_SOURCES = c2demo.c
 c2demo_LDADD = $(lib_LTLIBRARIES) 
 c2demo_LDFLAGS = $(LIBS)
@@ -371,6 +375,8 @@ fdmdv_put_test_bits_SOURCES = fdmdv_put_test_bits.c fdmdv.c kiss_fft.c
 fdmdv_put_test_bits_LDFLAGS = $(LIBS)
 fdmdv_interleave_SOURCES = fdmdv_interleave.c
 fdmdv_interleave_LDFLAGS = $(LIBS)
+sim_multipath_errors_SOURCES = sim_multipath_errors.c
+sim_multipath_errors_LDFLAGS = $(LIBS)
 all: all-am
 
 .SUFFIXES:
@@ -501,6 +507,9 @@ generate_codebook$(EXEEXT): $(generate_codebook_OBJECTS) $(generate_codebook_DEP
 genlspdtcb$(EXEEXT): $(genlspdtcb_OBJECTS) $(genlspdtcb_DEPENDENCIES) 
        @rm -f genlspdtcb$(EXEEXT)
        $(LINK) $(genlspdtcb_LDFLAGS) $(genlspdtcb_OBJECTS) $(genlspdtcb_LDADD) $(LIBS)
+sim_multipath_errors$(EXEEXT): $(sim_multipath_errors_OBJECTS) $(sim_multipath_errors_DEPENDENCIES) 
+       @rm -f sim_multipath_errors$(EXEEXT)
+       $(LINK) $(sim_multipath_errors_LDFLAGS) $(sim_multipath_errors_OBJECTS) $(sim_multipath_errors_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -546,6 +555,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcodec2_la-sine.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/octave.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phaseexp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim_multipath_errors.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff --git a/codec2-dev/src/sim_multipath_errors.c b/codec2-dev/src/sim_multipath_errors.c
new file mode 100644 (file)
index 0000000..bac6b36
--- /dev/null
@@ -0,0 +1,218 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: sim_multipath_errors.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 13/2/2013
+
+  Simulates error bursts on each FDMDV carrier from HF multipath.  Useful for
+  testing error protection schemes.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2010 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "codec2.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define SYMBOL_PERIOD 0.02
+   
+int iterate_state(int    state,
+                  int    carrier,
+                  float  t, 
+                  float  burst_length, 
+                  float  burst_offset)
+{
+    int next_state = state;
+
+    //printf("carrier: %2d state: %d t: %4.3f offset: %f\n", carrier, state, t, burst_offset);
+
+    switch(state) {
+    case 0:
+
+        /* clear channel state - no bit errors */
+
+        /* start of error burst in each carrier is shifted by
+           burst_offset wrt previous carrier */
+
+        if (t > burst_offset*(carrier+1))
+            next_state = 1;
+        break;
+
+    case 1:
+                
+        /* burst error state - 50% bit error rate */
+
+        if (t > (burst_offset*(carrier+1) + burst_length))
+            next_state = 2;
+        break;
+
+    }
+    return next_state;
+}
+
+
+int main(int argc, char *argv[])
+{
+    FILE          *fin;
+    FILE          *fout;
+    unsigned short bits_in, bit;
+    int            i, nbits_in, nbits_out, n_carriers, bits_per_carrier;
+    unsigned char  byte, bits_out;
+    int           *state, carrier;
+    float          t, burst_length, burst_period, burst_offset, r;
+    int            errors,bits;
+
+    if (argc < 7) {
+       printf("%s InputBitFile OutputBitFile nCarriers BitsPerCarrier "
+               "burstPeriod burstLength nextCarrierOffset\n", argv[0]);
+       exit(1);
+    }
+
+    if (strcmp(argv[1], "-")  == 0) fin = stdin;
+    else if ( (fin = fopen(argv[1],"rb")) == NULL ) {
+       fprintf(stderr, "Error opening input bit file: %s: %s.\n",
+         argv[1], strerror(errno));
+       exit(1);
+    }
+
+    if (strcmp(argv[2], "-") == 0) fout = stdout;
+    else if ( (fout = fopen(argv[2],"wb")) == NULL ) {
+       fprintf(stderr, "Error opening output speech file: %s: %s.\n",
+         argv[2], strerror(errno));
+       exit(1);
+    }
+
+    n_carriers = atoi(argv[3]);
+    bits_per_carrier = atoi(argv[4]);
+    
+    burst_period = atof(argv[5]);
+    burst_length = atof(argv[6]);
+    burst_offset = atof(argv[7]);
+
+    state = (int*)malloc(sizeof(int)*n_carriers);
+    assert(state != NULL);
+    for(i=0; i<n_carriers; i++)
+        state[i] = 0;
+
+    /* We have packed bits for input and output, which must be read as
+       bytes.  We would like to process these packed bits at the modem
+       frame rate.  e.g. for 1400 bit/s, the modem frame rate is 28
+       bit/frame of 3.5 bytes.
+
+       while !feof
+         Read a byte
+         while enough bits left
+           apply burst error
+           
+    */
+
+    t = 0.0;
+    carrier = 0;
+    nbits_in = 0;
+    bits_in = 0;
+    nbits_out = 0;
+    bits_out = 0;
+    errors = bits = 0;
+    while(fread(&byte, sizeof(char), 1, fin) == 1) {
+
+        /* insert latest byte into bits buffer, MSB is first in time order */
+        
+        bits_in <<= 8;
+        bits_in |= (short)byte;
+        nbits_in += 8;
+
+        //printf("byte: 0x%x bits_in: 0x%x nbits_in: %d\n", byte, bits_in, nbits_in);
+
+        while(nbits_in >= bits_per_carrier) {
+
+            /* iterate error state for every carrier to see if this carrier is 
+               knocked out by a simulated fade */
+
+            state[carrier] = iterate_state(state[carrier], 
+                                           carrier,
+                                           t, 
+                                           burst_length, burst_offset);
+
+            /* apply error model to bits in this carrier */
+
+            for(i=0; i<bits_per_carrier; i++) {
+
+                bit = (bits_in >> (nbits_in - 1)) & 0x1;               
+                nbits_in--;
+                //printf("bit: %d\n", bit);
+
+                bits++;
+                if (state[carrier] == 1) {
+                    r = (float)rand()/RAND_MAX;
+                    if (r < 0.5) {
+                        bit ^= 1;
+                        errors++;
+                        fprintf(stderr, "e");
+                    }
+                    else
+                        fprintf(stderr, ".");
+                }
+                else
+                    fprintf(stderr, ".");
+
+                /* pack processed bits and fwrite when we get a byte */
+
+                bits_out |= bit;
+                nbits_out++;
+                if (nbits_out == 8) {
+                    //printf("bits_out: 0x%x\n", bits_out);
+                    fwrite(&bits_out, sizeof(char), 1, fout); 
+                    nbits_out = 0;
+                    bits_out = 0;
+                }
+                else
+                    bits_out <<= 1;
+
+            }
+
+            /* move to next carrier */
+
+            carrier++;
+            fprintf(stderr, " ");
+            if (carrier == n_carriers) {
+                carrier = 0;
+                t += SYMBOL_PERIOD;
+                if (t > burst_period) {
+                    t = 0.0;
+                    for(i=0; i<n_carriers; i++)
+                        state[i] = 0;
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+    }
+
+    fclose(fin);
+    fclose(fout);
+    free(state);
+
+    fprintf(stderr,"ber: %4.3f\n", (float)errors/bits);
+
+    return 0;
+}