From 2899ad95cf0147ff04a4459588dddb1a8060ede4 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 10 Jul 2014 06:17:17 +0000 Subject: [PATCH] added basic AWGN channel simulation feature git-svn-id: https://svn.code.sf.net/p/freetel/code@1750 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/src/codec2_fdmdv.h | 1 + codec2-dev/src/fdmdv.c | 50 ++++++++++++++++++++++++++++++++- codec2-dev/src/fdmdv_internal.h | 6 +++- codec2-dev/src/fdmdv_mod.c | 5 +++- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/codec2-dev/src/codec2_fdmdv.h b/codec2-dev/src/codec2_fdmdv.h index 0b5d8bab..02a888ed 100644 --- a/codec2-dev/src/codec2_fdmdv.h +++ b/codec2-dev/src/codec2_fdmdv.h @@ -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 } diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index aba53114..e475d4be 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -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; isig_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; isig_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); +} diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index ca04f224..d542e5e6 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -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; }; /*---------------------------------------------------------------------------*\ diff --git a/codec2-dev/src/fdmdv_mod.c b/codec2-dev/src/fdmdv_mod.c index de2d578d..0bda4ebb 100644 --- a/codec2-dev/src/fdmdv_mod.c +++ b/codec2-dev/src/fdmdv_mod.c @@ -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 */ -- 2.25.1