Applied Jeroen's patch to add datachannel support to freedv test utils
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 14 Apr 2016 23:30:24 +0000 (23:30 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 14 Apr 2016 23:30:24 +0000 (23:30 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2790 01035d8c-6547-0410-b346-abe4f91aad63

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

index 268eef46e9958c649eedfc9aaf6e8fda7f129500..60de1e583dd47cf9006cfb80d211d8e876e1be44 100644 (file)
@@ -888,14 +888,13 @@ int freedv_floatrx_fsk(struct freedv *f, float demod_in[], int *valid) {
             (*f->freedv_put_next_proto)(f->proto_callback_state,(char*)proto_bits);
         }
         *valid = 1;
-        f->sync = 1;
-        f->stats.sync = 1;
     } else {
         /* Fill with silence */
         *valid = 0;
-        f->sync = 0;
-        f->stats.sync = 0;
     }
+    f->sync = f->deframer->state;
+    f->stats.sync = f->deframer->state;
+
     return f->n_speech_samples;
 }
 #endif
index 5158517e1bb6c556c4b50cd18e01d6a2f524ba16..4d6f1551926db03052f5e10956a917bfb50c7e5d 100644 (file)
@@ -98,6 +98,7 @@ void freedv_set_varicode_code_num       (struct freedv *freedv, int val);
 void freedv_set_data_header             (struct freedv *freedv, unsigned char *header);\r
 \r
 // Get parameters\r
+struct MODEM_STATS;
 int freedv_get_version(void);\r
 int freedv_get_mode                 (struct freedv *freedv);
 void freedv_get_modem_stats         (struct freedv *freedv, int *sync, float *snr_est);
index df7207c0ff3ae0593228b6818b3b3fa2dc0c8917..f351452c78c16a75393268ab3894b1bc72db6e8b 100644 (file)
@@ -42,6 +42,8 @@
 #include "freedv_api.h"
 #include "modem_stats.h"
 
+#include "codec2.h"
+
 struct my_callback_state {
     FILE *ftxt;
 };
@@ -60,6 +62,27 @@ void my_put_next_rx_proto(void *callback_state,char *proto_bits){
     }
 }
 
+/* Called when a packet has been received */
+void my_datarx(void *callback_state, unsigned char *packet, size_t size) {
+    struct my_callback_state* pstate = (struct my_callback_state*)callback_state;
+    if (pstate->ftxt != NULL) {
+        size_t i;
+       
+       fprintf(pstate->ftxt, "data (%zd bytes): ", size);
+       for (i = 0; i < size; i++) {
+           fprintf(pstate->ftxt, "0x%02x ", packet[i]);
+       }
+       fprintf(pstate->ftxt, "\n");
+    }
+}
+
+/* Called when a new packet can be send */
+void my_datatx(void *callback_state, unsigned char *packet, size_t *size) {
+    /* This should not happen while receiving.. */
+    fprintf(stderr, "datarx callback called, this should not happen!\n");    
+    *size = 0;
+}
+
 int main(int argc, char *argv[]) {
     FILE                      *fin, *fout, *ftxt;
     short                     *speech_out;
@@ -76,9 +99,13 @@ int main(int argc, char *argv[]) {
     int                        n_speech_samples;
     int                        n_max_modem_samples;
     float                      clock_offset;
+    int                        use_codecrx;
+    struct CODEC2             *c2 = NULL;
+    int                        i;
+
 
     if (argc < 4) {
-       printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
+       printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputModemSpeechFile OutputSpeechRawFile [--test_frames] [--codecrx]\n", argv[0]);
        printf("e.g    %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]);
        exit(1);
     }
@@ -115,8 +142,29 @@ int main(int argc, char *argv[]) {
     freedv = freedv_open(mode);
     assert(freedv != NULL);
 
-    if ( (argc > 4) && (strcmp(argv[4], "--testframes") == 0) ) {
-      freedv_set_test_frames(freedv, 1);
+    use_codecrx = 0;
+
+    if (argc > 4) {
+        for (i = 4; i < argc; i++) {
+            if (strcmp(argv[i], "--testframes") == 0) {
+                freedv_set_test_frames(freedv, 1);
+            }
+            if (strcmp(argv[i], "--codecrx") == 0) {
+                int c2_mode;
+
+                if (mode == FREEDV_MODE_700)  {
+                   c2_mode = CODEC2_MODE_700;
+               } else if ((mode == FREEDV_MODE_700B)|| (mode == FREEDV_MODE_800XA)) {
+                    c2_mode = CODEC2_MODE_700B;
+                } else {
+                    c2_mode = CODEC2_MODE_1300;
+                }
+                use_codecrx = 1;
+
+                c2 = codec2_create(c2_mode);
+                assert(c2 != NULL);
+            }
+        }
     }
     freedv_set_snr_squelch_thresh(freedv, -100.0);
     freedv_set_squelch_en(freedv, 1);
@@ -133,6 +181,7 @@ int main(int argc, char *argv[]) {
     my_cb_state.ftxt = ftxt;
     freedv_set_callback_txt(freedv, &my_put_next_rx_char, NULL, &my_cb_state);
     freedv_set_callback_protocol(freedv, &my_put_next_rx_proto, NULL, &my_cb_state);
+    freedv_set_callback_data(freedv, my_datarx, my_datatx, &my_cb_state);
 
     /* Note we need to work out how many samples demod needs on each
        call (nin).  This is used to adjust for differences in the tx and rx
@@ -143,7 +192,34 @@ int main(int argc, char *argv[]) {
     while(fread(demod_in, sizeof(short), nin, fin) == nin) {
         frame++;
 
-        nout = freedv_rx(freedv, speech_out, demod_in);
+        if (use_codecrx == 0) {
+            /* Use the freedv_api to do everything: speech decoding, demodulating */
+            nout = freedv_rx(freedv, speech_out, demod_in);
+        } else {
+            int bits_per_codec_frame = codec2_bits_per_frame(c2);
+            int bytes_per_codec_frame = (bits_per_codec_frame + 7) / 8;
+            int codec_frames = freedv_get_n_codec_bits(freedv) / bits_per_codec_frame;
+            int samples_per_frame = codec2_samples_per_frame(c2);
+            unsigned char encoded[bytes_per_codec_frame * codec_frames];
+
+            /* Use the freedv_api to demodulate only */
+            nout = freedv_codecrx(freedv, encoded, demod_in);
+
+            /* deccode the speech ourself (or send it to elsewhere, e.g. network) */
+            if (nout) {
+                unsigned char *enc_frame = encoded;
+               short *speech_frame = speech_out;
+               
+               nout = 0;
+               for (i = 0; i < codec_frames; i++) {
+                   codec2_decode(c2, speech_frame, enc_frame);
+                   enc_frame += bytes_per_codec_frame;
+                   speech_frame += samples_per_frame;
+                   nout += samples_per_frame;
+               }
+           }
+        }
+
         nin = freedv_nin(freedv);
 
         fwrite(speech_out, sizeof(short), nout, fout);
index b96103dac85982f1480b8f1fa77412107773852f..f434f06164e16c1e944e551a21e95be80709e23d 100644 (file)
@@ -32,6 +32,7 @@
 #include <errno.h>
 
 #include "freedv_api.h"
+#include "codec2.h"
 
 struct my_callback_state {
     char  tx_str[80];
@@ -56,6 +57,32 @@ void my_get_next_proto(void *callback_state,char *proto_bits){
     cb_states->calls = cb_states->calls + 1;
 }
 
+/* Called when a packet has been received */
+void my_datarx(void *callback_state, unsigned char *packet, size_t size) {
+    /* This should not happen while sending... */
+    fprintf(stderr, "datarx callback called, this should not happen!\n");    
+}
+
+/* Called when a new packet can be send */
+void my_datatx(void *callback_state, unsigned char *packet, size_t *size) {
+    static int data_toggle;
+    
+    /* Data could come from a network interface, here we just make up some */
+    
+    data_toggle = !data_toggle;
+    if (data_toggle) {
+        /* Send a packet with data */
+        int i;
+       for (i = 0; i < 64; i++)
+           packet[i] = i;
+       *size = i;
+    } else {
+        /* set size to zero, the freedv api will insert a header frame */
+        *size = 0;
+    }
+}
+
+
 int main(int argc, char *argv[]) {
     FILE                     *fin, *fout;
     short                    *speech_in;
@@ -65,9 +92,13 @@ int main(int argc, char *argv[]) {
     int                       mode;
     int                       n_speech_samples;
     int                       n_nom_modem_samples;
+    int                       use_codectx;
+    int                       use_datatx;
+    struct CODEC2             *c2;
+    int                       i;
 
     if (argc < 4) {
-        printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
+        printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputRawSpeechFile OutputModemRawFile [--testframes] [--codectx] [--datatx]\n", argv[0]);
         printf("e.g    %s 1600 hts1a.raw hts1a_fdmdv.raw\n", argv[0]);
         exit(1);
     }
@@ -102,8 +133,35 @@ int main(int argc, char *argv[]) {
     freedv = freedv_open(mode);
     assert(freedv != NULL);
 
-    if ((argc > 4) && (strcmp(argv[4], "--testframes") == 0)) {
-               freedv_set_test_frames(freedv, 1);
+    use_codectx = 0;
+    use_datatx = 0;
+
+    if (argc > 4) {
+        for (i = 4; i < argc; i++) {
+            if (strcmp(argv[i], "--testframes") == 0) {
+                freedv_set_test_frames(freedv, 1);
+            }
+            if (strcmp(argv[i], "--codectx") == 0) {
+                int c2_mode;
+
+                if (mode == FREEDV_MODE_700)  {
+                   c2_mode = CODEC2_MODE_700;
+               } else if ((mode == FREEDV_MODE_700B)|| (mode == FREEDV_MODE_800XA)) {
+                    c2_mode = CODEC2_MODE_700B;
+                } else {
+                    c2_mode = CODEC2_MODE_1300;
+                }
+                use_codectx = 1;
+
+                c2 = codec2_create(c2_mode);
+                assert(c2 != NULL);
+            }
+           if (strcmp(argv[i], "--datatx") == 0) {
+               unsigned char header[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc };
+               freedv_set_data_header(freedv, header);
+               use_datatx = 1;
+           }
+        }
     }
     freedv_set_snr_squelch_thresh(freedv, -100.0);
     freedv_set_squelch_en(freedv, 1);
@@ -125,10 +183,44 @@ int main(int argc, char *argv[]) {
     /* set up callback for protocol bits */
     freedv_set_callback_protocol(freedv, NULL, &my_get_next_proto, &my_cb_state);
 
+    /* set up callback for data packets */
+    freedv_set_callback_data(freedv, my_datarx, my_datatx, &my_cb_state);
+
     /* OK main loop */
 
     while(fread(speech_in, sizeof(short), n_speech_samples, fin) == n_speech_samples) {
-        freedv_tx(freedv, mod_out, speech_in);
+        if (use_codectx == 0) {
+            /* Use the freedv_api to do everything: speech encoding, modulating */
+            freedv_tx(freedv, mod_out, speech_in);
+        } else {
+            int bits_per_codec_frame = codec2_bits_per_frame(c2);
+            int bytes_per_codec_frame = (bits_per_codec_frame + 7) / 8;
+            int codec_frames = freedv_get_n_codec_bits(freedv) / bits_per_codec_frame;
+            int samples_per_frame = codec2_samples_per_frame(c2);
+            unsigned char encoded[bytes_per_codec_frame * codec_frames];
+            unsigned char *enc_frame = encoded;
+            short *speech_frame = speech_in;
+           float energy = 0;
+
+            /* Encode the speech ourself (or get it from elsewhere, e.g. network) */
+            for (i = 0; i < codec_frames; i++) {
+                codec2_encode(c2, enc_frame, speech_frame);
+                energy += codec2_get_energy(c2, enc_frame);
+               enc_frame += bytes_per_codec_frame;
+                speech_frame += samples_per_frame;
+           }
+           energy /= codec_frames;
+           
+           /* Is the audio fragment quiet? */
+           if (use_datatx && energy < 1.0) {
+                /* Insert a frame with data instead of speech */
+               freedv_datatx(freedv, mod_out);
+            } else {
+                /* Use the freedv_api to modulate already encoded frames */
+                freedv_codectx(freedv, mod_out, encoded);
+            }
+       }
+
         fwrite(mod_out, sizeof(short), n_nom_modem_samples, fout);
 
        /* if this is in a pipeline, we probably don't want the usual