a little more work on squelch
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 28 Jun 2015 04:28:51 +0000 (04:28 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 28 Jun 2015 04:28:51 +0000 (04:28 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2221 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/cohpsk.c
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h
codec2-dev/src/freedv_rx.c

index 69755127fd4f6bdb37f7b6db2edfbe37d80a1178..0304c8bdbea8190dce4d9e5d4bda25b988d6d5b7 100644 (file)
@@ -1113,13 +1113,16 @@ void cohpsk_get_demod_stats(struct COHPSK *coh, struct MODEM_STATS *stats)
 {
     int   c,r;
     COMP  pi_4;
+    float new_snr_est;
 
     pi_4.real = cosf(M_PI/4.0);
     pi_4.imag = sinf(M_PI/4.0);
 
     stats->Nc = COHPSK_NC*ND;
     assert(stats->Nc <= MODEM_STATS_NC_MAX);
-    stats->snr_est = 20*log10((coh->sig_rms+1E-6)/(coh->noise_rms+1E-6)) - 10*log10(3000.0/700.0);
+    new_snr_est = 20*log10((coh->sig_rms+1E-6)/(coh->noise_rms+1E-6)) - 10*log10(3000.0/700.0);
+    stats->snr_est = 0.9*stats->snr_est + 0.1*new_snr_est;
+
     //fprintf(stderr, "sig_rms: %f noise_rms: %f snr_est: %f\n", coh->sig_rms, coh->noise_rms, stats->snr_est);
     stats->sync = coh->sync;
     stats->foff = coh->f_est - FDMDV_FCENTRE;
index cf919c0c9a6580b42be1bade58517912ac60e1aa..64aeb79e44f5ddde0126ddd339a7d9915ab7c27d 100644 (file)
@@ -71,8 +71,9 @@ struct freedv *freedv_open(int mode) {
         return NULL;
     
     f->mode = mode;
-    f->test_frames = 0;
+    f->test_frames = f->smooth_symbols = 0;
     f->snr_squelch_thresh = 2.0;
+    f->squelch_en = 1;
    
     if (mode == FREEDV_MODE_1600) {
         Nc = 16;
@@ -122,6 +123,9 @@ struct freedv *freedv_open(int mode) {
         f->n_speech_samples = codec2_samples_per_frame(f->codec2);
     if (mode == FREEDV_MODE_700)
         f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2);
+    f->prev_rx_bits = (float*)malloc(sizeof(float)*2*codec2_bits_per_frame(f->codec2));
+    if (f->prev_rx_bits == NULL)
+        return NULL;
 
     nbit = codec2_bits_per_frame(f->codec2);
     nbyte = (nbit + 7) / 8;
@@ -158,6 +162,7 @@ struct freedv *freedv_open(int mode) {
 void freedv_close(struct freedv *freedv) {
     assert(freedv != NULL);
 
+    free(freedv->prev_rx_bits);
     free(freedv->packed_codec_bits);
     free(freedv->codec_bits);
     free(freedv->tx_bits);
@@ -582,9 +587,10 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
 
                 /* squelch if beneath SNR threshold or test frames enabled */
 
-                if ((f->stats.snr_est < f->snr_squelch_thresh) || f->test_frames) {
+                if ((f->squelch_en && (f->stats.snr_est < f->snr_squelch_thresh)) || f->test_frames) {
                     for(i=0; i<f->n_speech_samples; i++)
                         speech_out[i] = 0;
+                    fprintf(stderr, "sq! ");
                 }
 
                 nout = f->n_speech_samples;
@@ -594,8 +600,14 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
             /* if not in sync pass through analog samples */
             /* this lets us "hear" whats going on, e.g. during tuning */
             
-            for(i=0; i<nin_prev; i++)
-                speech_out[i] = FDMDV_SCALE*demod_in[i].real;
+            if (f->squelch_en == 0) {
+                for(i=0; i<nin_prev; i++)
+                    speech_out[i] = FDMDV_SCALE*demod_in[i].real;
+            }
+            else {
+                for(i=0; i<nin_prev; i++)
+                    speech_out[i] = 0;
+             }
             //fprintf(stderr, "%d %d %d\n", nin_prev, speech_out[0], speech_out[nin_prev-1]);
             nout = nin_prev;
         }
@@ -617,6 +629,17 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
             if (f->test_frames == 0) {
                 data_flag_index = codec2_get_spare_bit_index(f->codec2);
 
+                /* optional smoothing of codec symbols */
+
+                if (f->smooth_symbols) {
+                    float tmp;
+
+                    for(i=0; i<bits_per_codec_frame; i++) {
+                        rx_bits[i] += rx_bits[i+bits_per_codec_frame];
+                        rx_bits[i+bits_per_codec_frame] = rx_bits[i];
+                    }
+                }
+
                 for (j=0; j<COHPSK_BITS_PER_FRAME; j+=bits_per_codec_frame) {
                 
                     /* extract txt msg data bits */
@@ -645,9 +668,10 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
 
                     codec2_decode(f->codec2, speech_out, f->packed_codec_bits);
 
-                    if (f->stats.snr_est < f->snr_squelch_thresh) {
+                    if (f->squelch_en && (f->stats.snr_est < f->snr_squelch_thresh)) {
                         for(i=0; i<f->n_speech_samples; i++)
                             speech_out[i] = 0; 
+                        fprintf(stderr, "sq! ");
                     }
                     speech_out += codec2_samples_per_frame(f->codec2);
                 }
@@ -675,23 +699,31 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
         }
 
         if (sync == 0) {
-            float t,a,b,s;
-            int   t1,t2;
-
-            /* if not in sync pass through analog samples */
-            /* this lets us "hear" whats going on, e.g. during tuning */
-            /* need to linearly interp as Fs in and out slightly different */
-
-            for(i=0, t=0.0; i<f->n_speech_samples; i++, t+=(float)f->modem_sample_rate/FS) {
-                t1 = floor(t); t2 = ceil(t);
-                a = t - t1;
-                b = t2 - t1;
-                s = b*demod_in[t1].real + a*demod_in[t2].real;
-                speech_out[i] = FDMDV_SCALE*s;
+            if (f->squelch_en) {
+                for(i=0; i<f->n_speech_samples; i++)
+                    speech_out[i] = 0; 
+                nout = f->n_speech_samples;                 
+            }
+            else {
+                float t,a,b,s;
+                int   t1,t2;
+
+                /* if not in sync pass through analog samples */
+                /* this lets us "hear" whats going on, e.g. during tuning */
+                /* need to linearly interp as Fs in and out slightly different */
+
+                for(i=0, t=0.0; i<f->n_speech_samples; i++, t+=(float)f->modem_sample_rate/FS) {
+                    t1 = floor(t); t2 = ceil(t);
+                    a = t - t1;
+                    b = t2 - t1;
+                    s = b*demod_in[t1].real + a*demod_in[t2].real;               
+                    speech_out[i] = FDMDV_SCALE*s;
+                }
+                nout = f->n_speech_samples;
+                //fprintf(stderr, "%d %d %d\n", f->n_speech_samples, speech_out[0], speech_out[nin_prev-1]);
             }
-            nout = f->n_speech_samples;
-            //fprintf(stderr, "%d %d %d\n", f->n_speech_samples, speech_out[0], speech_out[nin_prev-1]);
         }
+            
 
     }
      
index c8c3b819f3e1bb5e9ca2aa0e98203696ea9a57a6..275c1fb2013971fd4bbfd1616eebb0003fde1b63 100644 (file)
@@ -62,6 +62,8 @@ struct freedv {
     int                 *fdmdv_bits;
     int                 *rx_bits;
     int                  tx_sync_bit;
+    int                  smooth_symbols;
+    float               *prev_rx_bits;
 
     int                 *ptest_bits_coh;
     int                 *ptest_bits_coh_end;
@@ -75,6 +77,7 @@ struct freedv {
     int                  sync;
     float                snr_est;
     float                snr_squelch_thresh;
+    float                squelch_en;
     int                  nin;
 
     struct VARICODE_DEC  varicode_dec_states;
index d949669666405b1c628ff099c1fbcc46c1d4d237..b39dd575c09692d5cb4e9c2fa9dd7872c56387b4 100644 (file)
@@ -90,6 +90,9 @@ int main(int argc, char *argv[]) {
     if ( (argc > 4) && (strcmp(argv[4], "--testframes") == 0) ) {
         freedv->test_frames = 1;
     }
+    if ( (argc > 4) && (strcmp(argv[4], "--smooth") == 0) ) {
+        freedv->smooth_symbols = 1;
+    }
     
     speech_out = (short*)malloc(sizeof(short)*freedv->n_speech_samples);
     assert(speech_out != NULL);