freedv api much improved by Jim Ahlstrom, thanks Jim
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 2 Aug 2015 22:41:06 +0000 (22:41 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 2 Aug 2015 22:41:06 +0000 (22:41 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2248 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 4850247e2a83bf9e349ae1c0a6422c8d07c38016..b6bc2d289ff6455d3bdb364c40ba44a0fadcb1e2 100644 (file)
 #include "golay23.h"
 #include "varicode.h"
 #include "freedv_api.h"
+#include "freedv_api_internal.h"
 #include "comp_prim.h"
 
+#define VERSION     10 /* The API version number.  The first version is 10.  Increment if the API changes
+                           in a way that would require changes by the API user. */
+/*
+ * Version 10   Initial version August 2, 2015.
+ * Version 11   September
+ *              Changes go here.
+ *
+ */
+
 #define NORM_PWR  1.74   /* experimentally derived fudge factor so 1600 and 
                             700 mode have the same tx power */
 
@@ -771,3 +781,102 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
     return nout;
 }
 
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: freedv_get_version
+  AUTHOR......: Jim Ahlstrom      
+  DATE CREATED: 28 July 2015
+
+  Return the version of the FreeDV API.  This is meant to help API users determine when
+  incompatible changes have occurred.
+
+\*---------------------------------------------------------------------------*/
+
+int freedv_get_version(void)
+{
+    return VERSION;
+}
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: freedv_set_callback_txt
+  AUTHOR......: Jim Ahlstrom
+  DATE CREATED: 28 July 2015
+
+  Set the callback functions and the callback state pointer that will be used
+  for the aux txt channel.  The freedv_callback_rx is a function pointer that
+  will be called to return received characters.  The freedv_callback_tx is a
+  function pointer that will be called to send transmitted characters.  The callback
+  state is a user-defined void pointer that will be passed to the callback functions.
+  Any or all can be NULL, and the default is all NULL.
+  The function signatures are:
+    void receive_char(void *callback_state, char c);
+    char transmit_char(void *callback_state);
+
+\*---------------------------------------------------------------------------*/
+
+void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_callback_tx tx, void *state)
+{
+    f->freedv_put_next_rx_char = rx;
+    f->freedv_get_next_tx_char = tx;
+    f->callback_state = state;
+}
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: freedv_get_modem_stats
+  AUTHOR......: Jim Ahlstrom
+  DATE CREATED: 28 July 2015
+
+  Return data from the modem.  The arguments are pointers to the data items.  The
+  pointers can be NULL if the data item is not wanted.
+
+\*---------------------------------------------------------------------------*/
+
+void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est)
+{
+    if (f->mode == FREEDV_MODE_1600)
+        fdmdv_get_demod_stats(f->fdmdv, &f->stats);
+    if (f->mode == FREEDV_MODE_700)
+        cohpsk_get_demod_stats(f->cohpsk, &f->stats);
+    if (sync) *sync = f->stats.sync;
+    if (snr_est) *snr_est = f->stats.snr_est;
+}
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTIONS...: freedv_set_*
+  AUTHOR......: Jim Ahlstrom
+  DATE CREATED: 28 July 2015
+
+  Set some parameters used by FreeDV.  It is possible to write a macro using ## for
+  this, but I wasn't sure it would be 100% portable.
+
+\*---------------------------------------------------------------------------*/
+
+// Set integers
+void freedv_set_test_frames                            (struct freedv *f, int val) {f->smooth_symbols = val;}
+void freedv_set_squelch_en                             (struct freedv *f, int val) {f->squelch_en = val;}
+// Set floats
+void freedv_set_snr_squelch_thresh             (struct freedv *f, float val) {f->snr_squelch_thresh = val;}
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTIONS...: freedv_get_*
+  AUTHOR......: Jim Ahlstrom
+  DATE CREATED: 28 July 2015
+
+  Get some parameters from FreeDV.  It is possible to write a macro using ## for
+  this, but I wasn't sure it would be 100% portable.
+
+\*---------------------------------------------------------------------------*/
+
+// Get integers
+int freedv_get_test_frames                             (struct freedv *f) {return f->test_frames;}
+int freedv_get_n_speech_samples                        (struct freedv *f) {return f->n_speech_samples;}
+int freedv_get_n_max_modem_samples             (struct freedv *f) {return f->n_max_modem_samples;}
+int freedv_get_n_nom_modem_samples             (struct freedv *f) {return f->n_nom_modem_samples;}
+int freedv_get_total_bits                              (struct freedv *f) {return f->total_bits;}
+int freedv_get_total_bit_errors                        (struct freedv *f) {return f->total_bit_errors;}
+// Get floats
+
index c6921ed2e80ae979b9c3f9deafa7108d8173b584..a6684f131a9178a3892236fc42c6192e074c0ed5 100644 (file)
 
 #ifndef __FREEDV__
 
+// This declares a single-precision (float) complex number
+#include "comp.h"
+
 #define FREEDV_MODE_1600        0
 #define FREEDV_MODE_700         1
 
-#include "varicode.h"
-#include "codec2_fdmdv.h"
-#include "codec2_cohpsk.h"
-
-struct freedv {
-    int                  mode;
-
-    struct CODEC2       *codec2;
-    struct FDMDV        *fdmdv;
-    struct MODEM_STATS   stats;
-    struct COHPSK       *cohpsk;
-
-    int                  n_speech_samples;
-    int                  n_nom_modem_samples;    // size of tx and most rx modem sample buffers
-    int                  n_max_modem_samples;    // make your rx modem sample buffers this big
-
-    int                  modem_sample_rate;      // ATM caller is responsible for meeting this (TBC)
-    int                  clip;                   // non-zero for cohpsk modem output clipping for low PAPR
-
-    unsigned char       *packed_codec_bits;
-    int                 *codec_bits;
-    int                 *tx_bits;
-    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;
-
-    int                  test_frames;            // set this baby for 1 to tx/rx test frames to look at bit error stats
-    int                  test_frame_sync_state;
-    int                  test_frame_count;
-    int                  total_bits;
-    int                  total_bit_errors;
-    int                  sz_error_pattern;
-
-    /* optional user defined function to pass error pattern when a test frame is received */
+struct freedv;
 
-    void                *error_pattern_callback_state;
-    void (*freedv_put_error_pattern)(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
-
-    int                  sync;
-    int                  evenframe;
-    float                snr_est;
-    float                snr_squelch_thresh;
-    float                squelch_en;
-    int                  nin;
-
-    struct VARICODE_DEC  varicode_dec_states;
-    short                tx_varicode_bits[VARICODE_MAX_BITS];
-    int                  nvaricode_bits;
-    int                  varicode_bit_index;
-    
-    /* user defined function ptrs to produce and consume ASCII
-      characters using aux txt channel */
-
-    char (*freedv_get_next_tx_char)(void *callback_state);
-    void (*freedv_put_next_rx_char)(void *callback_state, char c);
-
-    void                *callback_state;
-
-};
+typedef void (*freedv_callback_rx)(void *, char);
+typedef char (*freedv_callback_tx)(void *);
 
+// FreeDV API functions:
+// open, close
 struct freedv *freedv_open(int mode);
 void freedv_close(struct freedv *freedv);
-
-void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]);
-void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]);
-
-int freedv_nin(struct freedv *f);
-int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]);
-int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]);
-int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]);
-
+// Transmit
+void freedv_tx(struct freedv *freedv, short mod_out[], short speech_in[]);
+void freedv_comptx(struct freedv *freedv, COMP mod_out[], short speech_in[]);
+// Receive
+int freedv_nin(struct freedv *freedv);
+int freedv_rx(struct freedv *freedv, short speech_out[], short demod_in[]);
+int freedv_floatrx(struct freedv *freedv, short speech_out[], float demod_in[]);
+int freedv_comprx(struct freedv *freedv, short speech_out[], COMP demod_in[]);
+// Set parameters
+void freedv_set_callback_txt(struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
+void freedv_set_test_frames                    (struct freedv *freedv, int test_frames);
+void freedv_set_smooth_symbols         (struct freedv *freedv, int smooth_symbols);
+void freedv_set_squelch_en                     (struct freedv *freedv, int squelch_en);
+void freedv_set_snr_squelch_thresh     (struct freedv *freedv, float snr_squelch_thresh);
+// Get parameters
+int freedv_get_version(void);
+void freedv_get_modem_stats(struct freedv *freedv, int *sync, float *snr_est);
+int freedv_get_test_frames                     (struct freedv *freedv);
+int freedv_get_n_speech_samples                (struct freedv *freedv);
+int freedv_get_n_max_modem_samples     (struct freedv *freedv);
+int freedv_get_n_nom_modem_samples     (struct freedv *freedv);
+int freedv_get_total_bits                      (struct freedv *freedv);
+int freedv_get_total_bit_errors                (struct freedv *freedv);
 #endif
 
 #ifdef __cplusplus
index c24d34c8ca0fcd171fbe8ac7a2fa2bd731b9ddd6..28a920ee37a2111b594250b6580173c03c2322ea 100644 (file)
@@ -60,6 +60,12 @@ int main(int argc, char *argv[]) {
     int                        nin, nout, frame = 0;
     struct my_callback_state   my_cb_state;
     int                        mode;
+    int                        sync;
+    int                        total_bits;
+    int                        total_bit_errors;
+    float                      snr_est;
+    int                        n_speech_samples;
+    int                        n_max_modem_samples;
 
     if (argc < 4) {
        printf("usage: %s 1600|700 InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
@@ -92,21 +98,22 @@ int main(int argc, char *argv[]) {
     assert(freedv != NULL);
 
     if ( (argc > 4) && (strcmp(argv[4], "--testframes") == 0) ) {
-        freedv->test_frames = 1;
+               freedv_set_test_frames(freedv, 1);
     }
+    freedv_set_snr_squelch_thresh(freedv, -100.0);
+    freedv_set_squelch_en(freedv, 1);
     
-    speech_out = (short*)malloc(sizeof(short)*freedv->n_speech_samples);
+    n_speech_samples = freedv_get_n_speech_samples(freedv);
+    n_max_modem_samples = freedv_get_n_max_modem_samples(freedv);
+    speech_out = (short*)malloc(sizeof(short)*n_speech_samples);
     assert(speech_out != NULL);
-    demod_in = (short*)malloc(sizeof(short)*freedv->n_max_modem_samples);
+    demod_in = (short*)malloc(sizeof(short)*n_max_modem_samples);
     assert(demod_in != NULL);
 
     ftxt = fopen("freedv_rx_log.txt","wt");
     assert(ftxt != NULL);
     my_cb_state.ftxt = ftxt;
-    freedv->callback_state = (void*)&my_cb_state;
-    freedv->freedv_put_next_rx_char = &my_put_next_rx_char;
-
-    freedv->snr_squelch_thresh = -100.0;
+    freedv_set_callback_txt(freedv, &my_put_next_rx_char, NULL, &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
@@ -121,12 +128,14 @@ int main(int argc, char *argv[]) {
         nin = freedv_nin(freedv);
 
         fwrite(speech_out, sizeof(short), nout, fout);
+        freedv_get_modem_stats(freedv, &sync, &snr_est);
+        total_bit_errors = freedv_get_total_bit_errors(freedv);
         
         /* log some side info to the txt file */
                
         if (ftxt != NULL) {
             fprintf(ftxt, "frame: %d  demod sync: %d  demod snr: %3.2f dB  bit errors: %d\n", frame, 
-                    freedv->sync, freedv->snr_est, freedv->total_bit_errors);
+                    sync, snr_est, total_bit_errors);
         }
 
        /* if this is in a pipeline, we probably don't want the usual
@@ -136,8 +145,10 @@ int main(int argc, char *argv[]) {
         if (fin == stdin) fflush(stdin);         
     }
 
-    if (freedv->test_frames) {
-        fprintf(stderr, "bits: %d errors: %d BER: %3.2f\n", freedv->total_bits, freedv->total_bit_errors, (float)freedv->total_bit_errors/freedv->total_bits);
+    if (freedv_get_test_frames(freedv)) {
+        total_bits = freedv_get_total_bits(freedv);
+        total_bit_errors = freedv_get_total_bit_errors(freedv);
+        fprintf(stderr, "bits: %d errors: %d BER: %3.2f\n", total_bits, total_bit_errors, (float)total_bit_errors/total_bits);
     }
 
     free(speech_out);
index 80e4c4798d2f5de5a0e653ff89c9cd9c4aed24b7..a327922989f197f9f92afca63c5cd4cd46d9a0f1 100644 (file)
@@ -56,6 +56,8 @@ int main(int argc, char *argv[]) {
     struct freedv            *freedv;
     struct my_callback_state  my_cb_state;
     int                       mode;
+    int                       n_speech_samples;
+    int                       n_nom_modem_samples;
 
     if (argc < 4) {
        printf("usage: %s 1600|700 InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
@@ -88,26 +90,29 @@ int main(int argc, char *argv[]) {
     assert(freedv != NULL);
 
     if ((argc > 4) && (strcmp(argv[4], "--testframes") == 0)) {
-        freedv->test_frames = 1;
+               freedv_set_test_frames(freedv, 1);
     }
+    freedv_set_snr_squelch_thresh(freedv, -100.0);
+    freedv_set_squelch_en(freedv, 1);
 
-    speech_in = (short*)malloc(sizeof(short)*freedv->n_speech_samples);
+    n_speech_samples = freedv_get_n_speech_samples(freedv);
+    n_nom_modem_samples = freedv_get_n_nom_modem_samples(freedv);
+    speech_in = (short*)malloc(sizeof(short)*n_speech_samples);
     assert(speech_in != NULL);
-    mod_out = (short*)malloc(sizeof(short)*freedv->n_nom_modem_samples);
+    mod_out = (short*)malloc(sizeof(short)*n_nom_modem_samples);
     assert(mod_out != NULL);
 
     /* set up callback for txt msg chars */
 
     sprintf(my_cb_state.tx_str, "cq cq cq hello world\n");
     my_cb_state.ptx_str = my_cb_state.tx_str;
-    freedv->callback_state = (void*)&my_cb_state;
-    freedv->freedv_get_next_tx_char = &my_get_next_tx_char;
+    freedv_set_callback_txt(freedv, NULL, &my_get_next_tx_char, &my_cb_state);
 
     /* OK main loop */
 
-    while(fread(speech_in, sizeof(short), freedv->n_speech_samples, fin) == freedv->n_speech_samples) {
+    while(fread(speech_in, sizeof(short), n_speech_samples, fin) == n_speech_samples) {
         freedv_tx(freedv, mod_out, speech_in);
-        fwrite(mod_out, sizeof(short), freedv->n_nom_modem_samples, fout);
+        fwrite(mod_out, sizeof(short), n_nom_modem_samples, fout);
 
        /* if this is in a pipeline, we probably don't want the usual
            buffering to occur */