added basic AWGN channel simulation feature
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 10 Jul 2014 06:17:17 +0000 (06:17 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 10 Jul 2014 06:17:17 +0000 (06:17 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1750 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/codec2_fdmdv.h
codec2-dev/src/fdmdv.c
codec2-dev/src/fdmdv_internal.h
codec2-dev/src/fdmdv_mod.c

index 0b5d8babb7de8407feda70cb0bbb413953d6651d..02a888ede707b4454d20156a58590077fb5147dd 100644 (file)
@@ -115,6 +115,7 @@ void           fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff,
 /* debug/development function(s) */
 
 void fdmdv_dump_osc_mags(struct FDMDV *f);
+void fdmdv_simulate_channel(struct FDMDV *f, COMP samples[], int nin, float target_snr);
  
 #ifdef __cplusplus
 }
index aba531140a51a01bef21e4056c1e22dbf8c9e056..e475d4be0c2ecd2ac0315eacaaa1c792a3ae8cdd 100644 (file)
@@ -226,7 +226,8 @@ struct FDMDV * fdmdv_create(int Nc)
        f->fft_buf[i] = 0.0;
     f->fft_cfg = kiss_fft_alloc (2*FDMDV_NSPEC, 0, NULL, NULL);
     assert(f->fft_cfg != NULL);
-
+    
+    f->sig_pwr_av = 0.0;
 
     return f;
 }
@@ -1647,3 +1648,50 @@ void fdmdv_dump_osc_mags(struct FDMDV *f)
        fprintf(stderr,"  %1.3f", cabsolute(f->phase_rx[i]));
     fprintf(stderr, "\n\n");
 }
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: fdmdv_simulate_channel()            
+  AUTHOR......: David Rowe                           
+  DATE CREATED: 10 July 2014
+
+  Simple channel simulation function to aid in testing.  Target SNR
+  uses noise measured in a 3 kHz bandwidth.  
+
+  TODO: Measured SNR is coming out a few dB higher than target_snr, this
+  needs to be fixed.
+
+\*---------------------------------------------------------------------------*/
+
+void fdmdv_simulate_channel(struct FDMDV *f, COMP samples[], int nin, float target_snr) 
+{
+    float sig_pwr, target_snr_linear, noise_pwr, noise_pwr_4k, var_uniform, noise_gain;
+    int   i;
+
+    /* estimate signal power */
+
+    sig_pwr = 0.0;
+    for(i=0; i<nin; i++)
+        sig_pwr += samples[i].real*samples[i].real + samples[i].imag*samples[i].imag;
+    
+    f->sig_pwr_av = 0.9*f->sig_pwr_av + 0.1*(sig_pwr/nin);
+
+    /* det noise to meet target SNR */
+
+    target_snr_linear = powf(10.0, target_snr/10.0);
+    noise_pwr = f->sig_pwr_av/target_snr_linear;
+    noise_pwr_4k = 0.75*noise_pwr;                     /* this is the equivalent power scaled to a 4000 Hz BW */
+
+    /* for convenience we are using a uniform random number generator */
+
+    var_uniform = 1.0/12.0;
+    noise_gain = sqrtf(0.5*noise_pwr_4k/var_uniform);
+
+    for(i=0; i<nin; i++) {
+        samples[i].real += noise_gain*(((float)rand()/RAND_MAX) - 0.5);
+        samples[i].imag += noise_gain*(((float)rand()/RAND_MAX) - 0.5);
+    }
+
+    //printf("f->sig_pwr_av: %f target_snr_linear: %f noise_pwr_4k: %f noise_gain: %f\n", 
+    //       f->sig_pwr_av, target_snr_linear, noise_pwr_4k, noise_gain);
+}
index ca04f224cd4883c0ce1499020e26a9206d4cc2f4..d542e5e671b9bb0e81a62120cdd7c57ce2b4cc2d 100644 (file)
@@ -140,7 +140,11 @@ struct FDMDV {
     /* Buf for FFT/waterfall */
 
     float fft_buf[2*FDMDV_NSPEC];
-    kiss_fft_cfg fft_cfg;             
+    kiss_fft_cfg fft_cfg;  
+
+    /* channel simulation */
+
+    float sig_pwr_av;
 };
 
 /*---------------------------------------------------------------------------*\
index de2d578dadb1be83d530eec0db3bd2ff572ab9ec..0bda4ebb7aeab319f948bf69f1b0c2153d3ad34a 100644 (file)
@@ -131,9 +131,12 @@ int main(int argc, char *argv[])
        fdmdv_mod(fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &tx_bits[bits_per_fdmdv_frame], &sync_bit);
        assert(sync_bit == 0);
 
-        /* optional frequency offset */
+        #ifdef CHANNEL_SIM
+        /* optional freq shift and channel simulation */
 
         fdmdv_freq_shift(tx_fdm, tx_fdm, foff, &foff_phase_rect, 2*FDMDV_NOM_SAMPLES_PER_FRAME);
+        fdmdv_simulate_channel(fdmdv, tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME, 10.0);
+        #endif
 
        /* scale and save to disk as shorts */