diff options
Diffstat (limited to 'src/freedv_api.c')
| -rw-r--r-- | src/freedv_api.c | 1968 |
1 files changed, 1025 insertions, 943 deletions
diff --git a/src/freedv_api.c b/src/freedv_api.c index 516d604..5cedcf1 100644 --- a/src/freedv_api.c +++ b/src/freedv_api.c @@ -31,72 +31,55 @@ along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "freedv_api.h" + #include <assert.h> -#include <stdlib.h> +#include <math.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <math.h> -#include "fsk.h" -#include "fmfsk.h" #include "codec2.h" #include "codec2_fdmdv.h" +#include "codec2_ofdm.h" +#include "comp_prim.h" +#include "debug_alloc.h" #include "fdmdv_internal.h" -#include "varicode.h" -#include "freedv_api.h" +#include "fmfsk.h" #include "freedv_api_internal.h" #include "freedv_vhf_framing.h" -#include "comp_prim.h" - -#include "codec2_ofdm.h" -#include "ofdm_internal.h" -#include "mpdecode_core.h" +#include "fsk.h" #include "gp_interleaver.h" #include "interldpc.h" +#include "mpdecode_core.h" +#include "ofdm_internal.h" +#include "varicode.h" -#include "debug_alloc.h" - -#define VERSION 15 /* 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. */ +#define VERSION \ + 15 /* 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 2015 * Added: freedv_zero_total_bit_errors(), freedv_get_sync() - * Changed all input and output sample rates to 8000 sps. Rates for FREEDV_MODE_700 and 700B were 7500. - * Version 12 August 2018 - * Added OFDM configuration switch structure - * Version 13 November 2019 - * Removed 700 and 700B modes - * Version 14 May 2020 - * Number of returned speech samples can vary, use freedv_get_n_max_speech_samples() to allocate - * buffers. - * Version 15 December 2022 - * Removing rarely used DPSK support which is not needed given fast fading modes + * Changed all input and output sample rates to 8000 sps. Rates + * for FREEDV_MODE_700 and 700B were 7500. Version 12 August 2018 Added OFDM + * configuration switch structure Version 13 November 2019 Removed 700 and + * 700B modes Version 14 May 2020 Number of returned speech samples can vary, + * use freedv_get_n_max_speech_samples() to allocate buffers. Version 15 + * December 2022 Removing rarely used DPSK support which is not needed given + * fast fading modes */ -char *ofdm_statemode[] = {"search","trial","synced"}; - -char *rx_sync_flags_to_text[] = { - "----", - "---T", - "--S-", - "--ST", - "-B--", - "-B-T", - "-BS-", - "-BST", - "E---", - "E--T", - "E-S-", - "E-ST", - "EB--", - "EB-T", - "EBS-", - "EBST"}; +char *ofdm_statemode[] = {"search", "trial", "synced"}; + +char *rx_sync_flags_to_text[] = {"----", "---T", "--S-", "--ST", "-B--", "-B-T", + "-BS-", "-BST", "E---", "E--T", "E-S-", "E-ST", + "EB--", "EB-T", "EBS-", "EBST"}; /*---------------------------------------------------------------------------* \ @@ -111,63 +94,66 @@ char *rx_sync_flags_to_text[] = { \*---------------------------------------------------------------------------*/ struct freedv *freedv_open(int mode) { - // defaults for those modes that support the use of adv - struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"}; - return freedv_open_advanced(mode, &adv); + // defaults for those modes that support the use of adv + struct freedv_advanced adv = {0, 2, 100, 8000, 1000, 200, "H_256_512_4"}; + return freedv_open_advanced(mode, &adv); } struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { - struct freedv *f; - - assert(FREEDV_PEAK == OFDM_PEAK); - assert(FREEDV_VARICODE_MAX_BITS == VARICODE_MAX_BITS); - - if ((FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) == false) return NULL; - - /* set everything to zero just in case */ - f = (struct freedv*)CALLOC(1, sizeof(struct freedv)); - if (f == NULL) return NULL; - - f->mode = mode; - - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode)) freedv_1600_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode)) freedv_700c_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode)) freedv_ofdm_voice_open(f, "700D"); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode)) freedv_ofdm_voice_open(f, "700E"); + struct freedv *f; + + assert(FREEDV_PEAK == OFDM_PEAK); + assert(FREEDV_VARICODE_MAX_BITS == VARICODE_MAX_BITS); + + if ((FDV_MODE_ACTIVE(FREEDV_MODE_1600, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700C, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700D, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400A, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) == false) + return NULL; + + /* set everything to zero just in case */ + f = (struct freedv *)CALLOC(1, sizeof(struct freedv)); + if (f == NULL) return NULL; + + f->mode = mode; + + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, mode)) freedv_1600_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, mode)) freedv_700c_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, mode)) + freedv_ofdm_voice_open(f, "700D"); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700E, mode)) + freedv_ofdm_voice_open(f, "700E"); #ifdef __LPCNET__ - if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, mode)) - freedv_2020x_open(f); -#endif - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode)) freedv_2400a_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode)) freedv_2400b_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode)) freedv_800xa_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv); - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f); - - varicode_decode_init(&f->varicode_dec_states, 1); - - return f; + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, mode)) + freedv_2020x_open(f); +#endif + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, mode)) freedv_2400a_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, mode)) freedv_2400b_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, mode)) freedv_800xa_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f); + + varicode_decode_init(&f->varicode_dec_states, 1); + + return f; } /*---------------------------------------------------------------------------*\ @@ -181,113 +167,114 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { \*---------------------------------------------------------------------------*/ void freedv_close(struct freedv *freedv) { - assert(freedv != NULL); + assert(freedv != NULL); - FREE(freedv->tx_payload_bits); - FREE(freedv->rx_payload_bits); - if (freedv->codec2) codec2_destroy(freedv->codec2); + FREE(freedv->tx_payload_bits); + FREE(freedv->rx_payload_bits); + if (freedv->codec2) codec2_destroy(freedv->codec2); - if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, freedv->mode)) { - FREE(freedv->fdmdv_bits); - FREE(freedv->fdmdv_tx_bits); - FREE(freedv->fdmdv_rx_bits); - fdmdv_destroy(freedv->fdmdv); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, freedv->mode)) { + FREE(freedv->fdmdv_bits); + FREE(freedv->fdmdv_tx_bits); + FREE(freedv->fdmdv_rx_bits); + fdmdv_destroy(freedv->fdmdv); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, freedv->mode)) { - cohpsk_destroy(freedv->cohpsk); - quisk_filt_destroy(freedv->ptFilter8000to7500); - FREE(freedv->ptFilter8000to7500); - quisk_filt_destroy(freedv->ptFilter7500to8000); - FREE(freedv->ptFilter7500to8000); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, freedv->mode)) { + cohpsk_destroy(freedv->cohpsk); + quisk_filt_destroy(freedv->ptFilter8000to7500); + FREE(freedv->ptFilter8000to7500); + quisk_filt_destroy(freedv->ptFilter7500to8000); + FREE(freedv->ptFilter7500to8000); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700E, freedv->mode)) { - FREE(freedv->rx_syms); - FREE(freedv->rx_amps); - FREE(freedv->ldpc); - ofdm_destroy(freedv->ofdm); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, freedv->mode)) { + FREE(freedv->rx_syms); + FREE(freedv->rx_amps); + FREE(freedv->ldpc); + ofdm_destroy(freedv->ofdm); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, freedv->mode)) { - FREE(freedv->codeword_symbols); - FREE(freedv->codeword_amps); - FREE(freedv->ldpc); - FREE(freedv->passthrough_2020); - ofdm_destroy(freedv->ofdm); + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, freedv->mode)) { + FREE(freedv->codeword_symbols); + FREE(freedv->codeword_amps); + FREE(freedv->ldpc); + FREE(freedv->passthrough_2020); + ofdm_destroy(freedv->ofdm); #ifdef __LPCNET__ - lpcnet_freedv_destroy(freedv->lpcnet); + lpcnet_freedv_destroy(freedv->lpcnet); #endif - } + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, freedv->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, freedv->mode)){ - fsk_destroy(freedv->fsk); - fvhff_destroy_deframer(freedv->deframer); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, freedv->mode)) { + fsk_destroy(freedv->fsk); + fvhff_destroy_deframer(freedv->deframer); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, freedv->mode)) { - fmfsk_destroy(freedv->fmfsk); - fvhff_destroy_deframer(freedv->deframer); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, freedv->mode)) { + fmfsk_destroy(freedv->fmfsk); + fvhff_destroy_deframer(freedv->deframer); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, freedv->mode)) { - fsk_destroy(freedv->fsk); - FREE(freedv->ldpc); - FREE(freedv->frame_llr); - FREE(freedv->twoframes_llr); - FREE(freedv->twoframes_hard); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, freedv->mode)) { + fsk_destroy(freedv->fsk); + FREE(freedv->ldpc); + FREE(freedv->frame_llr); + FREE(freedv->twoframes_llr); + FREE(freedv->twoframes_hard); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, freedv->mode)) - { - FREE(freedv->rx_syms); - FREE(freedv->rx_amps); - FREE(freedv->ldpc); - ofdm_destroy(freedv->ofdm); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, freedv->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, freedv->mode)) { + FREE(freedv->rx_syms); + FREE(freedv->rx_amps); + FREE(freedv->ldpc); + ofdm_destroy(freedv->ofdm); + } - FREE(freedv); + FREE(freedv); } +/* helper function, unpacked bits are much easier to work with inside the modem + */ -/* helper function, unpacked bits are much easier to work with inside the modem */ - -static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[], short speech_in[]) { - int n_packed = (f->bits_per_codec_frame + 7) / 8; - uint8_t packed_codec_bits[n_packed]; +static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[], + short speech_in[]) { + int n_packed = (f->bits_per_codec_frame + 7) / 8; + uint8_t packed_codec_bits[n_packed]; - codec2_encode(f->codec2, packed_codec_bits, speech_in); - freedv_unpack(unpacked_bits, packed_codec_bits, f->bits_per_codec_frame); + codec2_encode(f->codec2, packed_codec_bits, speech_in); + freedv_unpack(unpacked_bits, packed_codec_bits, f->bits_per_codec_frame); } static int is_ofdm_mode(struct freedv *f) { - return FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode); -} - + return FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode); +} + static int is_ofdm_data_mode(struct freedv *f) { - return FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode); + return FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode); } - + /*---------------------------------------------------------------------------*\ FUNCTION....: freedv_tx @@ -317,362 +304,385 @@ static int is_ofdm_data_mode(struct freedv *f) { /* real-valued short output */ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) { - assert(f != NULL); - COMP tx_fdm[f->n_nom_modem_samples]; - int i; - - /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just - * stick them in the real sample tx/rx functions than to add a comp->real converter - * to comptx */ - - if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){ - /* 800XA has two codec frames per modem frame */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - codec2_encode(f->codec2, &f->tx_payload_bits[0], &speech_in[ 0]); - codec2_encode(f->codec2, &f->tx_payload_bits[4], &speech_in[320]); - }else{ - codec2_encode(f->codec2, f->tx_payload_bits, speech_in); - } - freedv_tx_fsk_voice(f, mod_out); + assert(f != NULL); + COMP tx_fdm[f->n_nom_modem_samples]; + int i; + + /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just + * stick them in the real sample tx/rx functions than to add a comp->real + * converter to comptx */ + + if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode))) { + /* 800XA has two codec frames per modem frame */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + codec2_encode(f->codec2, &f->tx_payload_bits[0], &speech_in[0]); + codec2_encode(f->codec2, &f->tx_payload_bits[4], &speech_in[320]); } else { - freedv_comptx(f, tx_fdm, speech_in); - for(i=0; i<f->n_nom_modem_samples; i++) - mod_out[i] = tx_fdm[i].real; + codec2_encode(f->codec2, f->tx_payload_bits, speech_in); } + freedv_tx_fsk_voice(f, mod_out); + } else { + freedv_comptx(f, tx_fdm, speech_in); + for (i = 0; i < f->n_nom_modem_samples; i++) mod_out[i] = tx_fdm[i].real; + } } - /* complex float output version of freedv_tx() */ void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) { - assert(f != NULL); + assert(f != NULL); + + assert(FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)); + + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) { + codec2_encode_upacked(f, f->tx_payload_bits, speech_in); + freedv_comptx_fdmdv_1600(f, mod_out); + } - assert( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)); + /* all these modes need to pack a bunch of codec frames into one modem frame + * ... */ - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) { - codec2_encode_upacked(f, f->tx_payload_bits, speech_in); - freedv_comptx_fdmdv_1600(f, mod_out); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + for (int j = 0; j < f->n_codec_frames; j++) { + codec2_encode_upacked(f, f->tx_payload_bits + j * f->bits_per_codec_frame, + speech_in); + speech_in += codec2_samples_per_frame(f->codec2); } + freedv_comptx_700c(f, mod_out); + } - /* all these modes need to pack a bunch of codec frames into one modem frame ... */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) { + /* buffer up bits until we get enough encoded bits for interleaver */ - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) { - for (int j=0; j<f->n_codec_frames; j++) { - codec2_encode_upacked(f, f->tx_payload_bits+j*f->bits_per_codec_frame, speech_in); - speech_in += codec2_samples_per_frame(f->codec2); - } - freedv_comptx_700c(f, mod_out); + for (int j = 0; j < f->n_codec_frames; j++) { + int offset = j * f->bits_per_codec_frame; + codec2_encode_upacked(f, f->tx_payload_bits + offset, speech_in); + speech_in += codec2_samples_per_frame(f->codec2); } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) { - - /* buffer up bits until we get enough encoded bits for interleaver */ - - for (int j=0; j<f->n_codec_frames; j++) { - int offset = j*f->bits_per_codec_frame; - codec2_encode_upacked(f, f->tx_payload_bits + offset, speech_in); - speech_in += codec2_samples_per_frame(f->codec2); - } - - freedv_comptx_ofdm(f, mod_out); - } + freedv_comptx_ofdm(f, mod_out); + } #ifdef __LPCNET__ - if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) { - - /* buffer up bits until we get enough encoded bits for interleaver */ - - for (int j=0; j<f->n_codec_frames; j++) { - int offset = j*f->bits_per_codec_frame; - lpcnet_enc(f->lpcnet, speech_in, (char*)f->tx_payload_bits + offset); - speech_in += lpcnet_samples_per_frame(f->lpcnet); - } - - freedv_comptx_2020(f, mod_out); + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) { + /* buffer up bits until we get enough encoded bits for interleaver */ + + for (int j = 0; j < f->n_codec_frames; j++) { + int offset = j * f->bits_per_codec_frame; + lpcnet_enc(f->lpcnet, speech_in, (char *)f->tx_payload_bits + offset); + speech_in += lpcnet_samples_per_frame(f->lpcnet); } + + freedv_comptx_2020(f, mod_out); + } #endif - /* 2400 A and B are handled by the real-mode TX */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - codec2_encode(f->codec2, f->tx_payload_bits, speech_in); - freedv_comptx_fsk_voice(f, mod_out); - } + /* 2400 A and B are handled by the real-mode TX */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + codec2_encode(f->codec2, f->tx_payload_bits, speech_in); + freedv_comptx_fsk_voice(f, mod_out); + } } - /* pack bits */ void freedv_pack(uint8_t *bytes, uint8_t *bits, int nbits) { - memset(bytes, 0, (nbits+7)/8); - int bit = 7, byte = 0; - for(int i=0; i<nbits; i++) { - bytes[byte] |= bits[i] << bit; - bit--; - if (bit < 0) { - bit = 7; - byte++; - } + memset(bytes, 0, (nbits + 7) / 8); + int bit = 7, byte = 0; + for (int i = 0; i < nbits; i++) { + bytes[byte] |= bits[i] << bit; + bit--; + if (bit < 0) { + bit = 7; + byte++; } + } } /* unpack bits, MSB first */ void freedv_unpack(uint8_t *bits, uint8_t *bytes, int nbits) { - int bit = 7, byte = 0; - for(int i=0; i<nbits; i++) { - bits[i] = (bytes[byte] >> bit) & 0x1; - bit--; - if (bit < 0) { - bit = 7; - byte++; - } + int bit = 7, byte = 0; + for (int i = 0; i < nbits; i++) { + bits[i] = (bytes[byte] >> bit) & 0x1; + bit--; + if (bit < 0) { + bit = 7; + byte++; } + } } /* compute the CRC16 of a frame of unpacked bits */ unsigned short freedv_crc16_unpacked(unsigned char unpacked_bits[], int nbits) { - assert((nbits % 8) == 0); - int nbytes = nbits/8; - uint8_t packed_bytes[nbytes]; - freedv_pack(packed_bytes, unpacked_bits, nbits); - return freedv_gen_crc16(packed_bytes, nbytes); + assert((nbits % 8) == 0); + int nbytes = nbits / 8; + uint8_t packed_bytes[nbytes]; + freedv_pack(packed_bytes, unpacked_bits, nbits); + return freedv_gen_crc16(packed_bytes, nbytes); } /* Return non-zero if CRC16 of a frame of unpacked bits is correct */ int freedv_check_crc16_unpacked(unsigned char unpacked_bits[], int nbits) { - assert((nbits % 8) == 0); - int nbytes = nbits/8; - uint8_t packed_bytes[nbytes]; - freedv_pack(packed_bytes, unpacked_bits, nbits); - uint16_t tx_crc16 = (packed_bytes[nbytes-2] << 8) | packed_bytes[nbytes-1]; - uint16_t rx_crc16 = freedv_crc16_unpacked(unpacked_bits, nbits - 16); - return tx_crc16 == rx_crc16; -} - -/* send raw frames of bytes, or speech data that was compressed externally, complex float output */ -void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[], unsigned char *packed_payload_bits) { - assert(f != NULL); - - freedv_unpack(f->tx_payload_bits, packed_payload_bits, f->bits_per_modem_frame); - - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) freedv_comptx_fdmdv_1600(f, mod_out); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) freedv_comptx_700c(f, mod_out); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) freedv_comptx_ofdm(f, mod_out); - - if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) { - freedv_tx_fsk_ldpc_data(f, mod_out); - } + assert((nbits % 8) == 0); + int nbytes = nbits / 8; + uint8_t packed_bytes[nbytes]; + freedv_pack(packed_bytes, unpacked_bits, nbits); + uint16_t tx_crc16 = + (packed_bytes[nbytes - 2] << 8) | packed_bytes[nbytes - 1]; + uint16_t rx_crc16 = freedv_crc16_unpacked(unpacked_bits, nbits - 16); + return tx_crc16 == rx_crc16; } +/* send raw frames of bytes, or speech data that was compressed externally, + * complex float output */ +void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[], + unsigned char *packed_payload_bits) { + assert(f != NULL); + + freedv_unpack(f->tx_payload_bits, packed_payload_bits, + f->bits_per_modem_frame); + + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) + freedv_comptx_fdmdv_1600(f, mod_out); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) + freedv_comptx_700c(f, mod_out); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode)) + freedv_comptx_ofdm(f, mod_out); + + if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, f->mode)) { + freedv_tx_fsk_ldpc_data(f, mod_out); + } +} -/* send raw frames of bytes, or speech data that was compressed externally, real short output */ -void freedv_rawdatatx(struct freedv *f, short mod_out[], unsigned char *packed_payload_bits) { - assert(f != NULL); - COMP mod_out_comp[f->n_nat_modem_samples]; - - /* Some FSK modes used packed bits, and coincidentally support real samples natively */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) ) { - freedv_codec_frames_from_rawdata(f, f->tx_payload_bits, packed_payload_bits); - freedv_tx_fsk_voice(f, mod_out); - return; /* output is already real */ - } +/* send raw frames of bytes, or speech data that was compressed externally, real + * short output */ +void freedv_rawdatatx(struct freedv *f, short mod_out[], + unsigned char *packed_payload_bits) { + assert(f != NULL); + COMP mod_out_comp[f->n_nat_modem_samples]; + + /* Some FSK modes used packed bits, and coincidentally support real samples + * natively */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + freedv_codec_frames_from_rawdata(f, f->tx_payload_bits, + packed_payload_bits); + freedv_tx_fsk_voice(f, mod_out); + return; /* output is already real */ + } - freedv_rawdatacomptx(f, mod_out_comp, packed_payload_bits); + freedv_rawdatacomptx(f, mod_out_comp, packed_payload_bits); - /* convert complex to real */ - for(int i=0; i<f->n_nat_modem_samples; i++) - mod_out[i] = mod_out_comp[i].real; + /* convert complex to real */ + for (int i = 0; i < f->n_nat_modem_samples; i++) + mod_out[i] = mod_out_comp[i].real; } int freedv_rawdatapreamblecomptx(struct freedv *f, COMP mod_out[]) { - assert(f != NULL); - int npreamble_samples = 0; - - if (f->mode == FREEDV_MODE_FSK_LDPC) { - struct FSK *fsk = f->fsk; - - int npreamble_symbols = 50*(fsk->mode>>1); - int npreamble_bits = npreamble_symbols*(fsk->mode>>1); - npreamble_samples = fsk->Ts*npreamble_symbols; - //fprintf(stderr, "npreamble_symbols: %d npreamble_bits: %d npreamble_samples: %d Nbits: %d N: %d\n", - //npreamble_symbols, npreamble_bits, npreamble_samples, fsk->Nbits, fsk->N); - - assert(npreamble_samples < f->n_nom_modem_samples); /* caller probably using an array of this size */ - freedv_tx_fsk_ldpc_data_preamble(f, mod_out, npreamble_bits, npreamble_samples); - } else if (is_ofdm_data_mode(f)) { - struct OFDM *ofdm = f->ofdm; - complex float *tx_preamble = (complex float*)mod_out; - memcpy(tx_preamble, ofdm->tx_preamble, sizeof(COMP)*ofdm->samplesperframe); - ofdm_hilbert_clipper(ofdm, tx_preamble, ofdm->samplesperframe); - npreamble_samples = ofdm->samplesperframe; - } + assert(f != NULL); + int npreamble_samples = 0; + + if (f->mode == FREEDV_MODE_FSK_LDPC) { + struct FSK *fsk = f->fsk; + + int npreamble_symbols = 50 * (fsk->mode >> 1); + int npreamble_bits = npreamble_symbols * (fsk->mode >> 1); + npreamble_samples = fsk->Ts * npreamble_symbols; + // fprintf(stderr, "npreamble_symbols: %d npreamble_bits: %d + // npreamble_samples: %d Nbits: %d N: %d\n", npreamble_symbols, + // npreamble_bits, npreamble_samples, fsk->Nbits, fsk->N); + + assert(npreamble_samples < + f->n_nom_modem_samples); /* caller probably using an array of this + size */ + freedv_tx_fsk_ldpc_data_preamble(f, mod_out, npreamble_bits, + npreamble_samples); + } else if (is_ofdm_data_mode(f)) { + struct OFDM *ofdm = f->ofdm; + complex float *tx_preamble = (complex float *)mod_out; + memcpy(tx_preamble, ofdm->tx_preamble, + sizeof(COMP) * ofdm->samplesperframe); + ofdm_hilbert_clipper(ofdm, tx_preamble, ofdm->samplesperframe); + npreamble_samples = ofdm->samplesperframe; + } - return npreamble_samples; + return npreamble_samples; } int freedv_rawdatapreambletx(struct freedv *f, short mod_out[]) { - assert(f != NULL); - COMP mod_out_comp[f->n_nat_modem_samples]; + assert(f != NULL); + COMP mod_out_comp[f->n_nat_modem_samples]; - int npreamble_samples = freedv_rawdatapreamblecomptx(f, mod_out_comp); - assert(npreamble_samples <= f->n_nat_modem_samples); + int npreamble_samples = freedv_rawdatapreamblecomptx(f, mod_out_comp); + assert(npreamble_samples <= f->n_nat_modem_samples); - /* convert complex to real */ - for(int i=0; i<npreamble_samples; i++) - mod_out[i] = mod_out_comp[i].real; + /* convert complex to real */ + for (int i = 0; i < npreamble_samples; i++) mod_out[i] = mod_out_comp[i].real; - return npreamble_samples; + return npreamble_samples; } int freedv_rawdatapostamblecomptx(struct freedv *f, COMP mod_out[]) { - assert(f != NULL); - int npostamble_samples = 0; - - if (is_ofdm_data_mode(f)) { - struct OFDM *ofdm = f->ofdm; - complex float *tx_postamble = (complex float*)mod_out; - memcpy(tx_postamble, ofdm->tx_postamble, sizeof(COMP)*ofdm->samplesperframe); - ofdm_hilbert_clipper(ofdm, tx_postamble, ofdm->samplesperframe); - npostamble_samples = ofdm->samplesperframe; - } + assert(f != NULL); + int npostamble_samples = 0; + + if (is_ofdm_data_mode(f)) { + struct OFDM *ofdm = f->ofdm; + complex float *tx_postamble = (complex float *)mod_out; + memcpy(tx_postamble, ofdm->tx_postamble, + sizeof(COMP) * ofdm->samplesperframe); + ofdm_hilbert_clipper(ofdm, tx_postamble, ofdm->samplesperframe); + npostamble_samples = ofdm->samplesperframe; + } - return npostamble_samples; + return npostamble_samples; } int freedv_rawdatapostambletx(struct freedv *f, short mod_out[]) { - assert(f != NULL); - COMP mod_out_comp[f->n_nat_modem_samples]; + assert(f != NULL); + COMP mod_out_comp[f->n_nat_modem_samples]; - int npostamble_samples = freedv_rawdatapostamblecomptx(f, mod_out_comp); - assert(npostamble_samples <= f->n_nat_modem_samples); + int npostamble_samples = freedv_rawdatapostamblecomptx(f, mod_out_comp); + assert(npostamble_samples <= f->n_nat_modem_samples); - /* convert complex to real */ - for(int i=0; i<npostamble_samples; i++) - mod_out[i] = mod_out_comp[i].real; + /* convert complex to real */ + for (int i = 0; i < npostamble_samples; i++) + mod_out[i] = mod_out_comp[i].real; - return npostamble_samples; + return npostamble_samples; } /* VHF packet data tx function */ -void freedv_datatx (struct freedv *f, short mod_out[]) { - assert(f != NULL); - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) { - freedv_tx_fsk_data(f, mod_out); - } +void freedv_datatx(struct freedv *f, short mod_out[]) { + assert(f != NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + freedv_tx_fsk_data(f, mod_out); + } } - /* VHF packet data: returns how many tx frames are queued up but not sent yet */ -int freedv_data_ntxframes (struct freedv *f) { - assert(f != NULL); - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) { - if (f->deframer->fdc) - return freedv_data_get_n_tx_frames(f->deframer->fdc, 8); - } else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) { - if (f->deframer->fdc) - return freedv_data_get_n_tx_frames(f->deframer->fdc, 6); - } - return 0; +int freedv_data_ntxframes(struct freedv *f) { + assert(f != NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + if (f->deframer->fdc) + return freedv_data_get_n_tx_frames(f->deframer->fdc, 8); + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + if (f->deframer->fdc) + return freedv_data_get_n_tx_frames(f->deframer->fdc, 6); + } + return 0; } int freedv_nin(struct freedv *f) { - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) - // For mode 700C, the input rate is 8000 sps, but the modem rate is 7500 sps - // For mode 700C, we request a larger number of Rx samples that will be decimated to f->nin samples - return (16 * f->nin + f->ptFilter8000to7500->decim_index) / 15; - else - return f->nin; -} - -int freedv_codec_frames_from_rawdata(struct freedv *f, unsigned char *codec_frames, unsigned char *rawdata) -{ - int cbit = 7; - int cbyte = 0; - int rbit = 7; - int rbyte = 0; - int modem_bits = freedv_get_bits_per_modem_frame(f); - int codec_bits = freedv_get_bits_per_codec_frame(f); - int nr_cbits = 0; - int i; - - codec_frames[0] = 0; - for (i = 0; i < modem_bits; i++) { - codec_frames[cbyte] |= ((rawdata[rbyte] >> rbit) & 1) << cbit; - - rbit--; - if (rbit < 0) { - rbit = 7; - rbyte++; - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) + // For mode 700C, the input rate is 8000 sps, but the modem rate is 7500 sps + // For mode 700C, we request a larger number of Rx samples that will be + // decimated to f->nin samples + return (16 * f->nin + f->ptFilter8000to7500->decim_index) / 15; + else + return f->nin; +} - cbit--; - if (cbit < 0) { - cbit = 7; - cbyte++; - codec_frames[cbyte] = 0; - } - nr_cbits++; - if (nr_cbits == codec_bits) { - if (cbit) { - cbyte++; - codec_frames[cbyte] = 0; - } - cbit = 7; - nr_cbits = 0; - } +int freedv_codec_frames_from_rawdata(struct freedv *f, + unsigned char *codec_frames, + unsigned char *rawdata) { + int cbit = 7; + int cbyte = 0; + int rbit = 7; + int rbyte = 0; + int modem_bits = freedv_get_bits_per_modem_frame(f); + int codec_bits = freedv_get_bits_per_codec_frame(f); + int nr_cbits = 0; + int i; + + codec_frames[0] = 0; + for (i = 0; i < modem_bits; i++) { + codec_frames[cbyte] |= ((rawdata[rbyte] >> rbit) & 1) << cbit; + + rbit--; + if (rbit < 0) { + rbit = 7; + rbyte++; } - return f->n_codec_frames; -} - -int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, unsigned char *codec_frames) -{ - int cbit = 7; - int cbyte = 0; - int rbit = 7; - int rbyte = 0; - int modem_bits = freedv_get_bits_per_modem_frame(f); - int codec_bits = freedv_get_bits_per_codec_frame(f); - int nr_cbits = 0; - int i; - - rawdata[rbyte] = 0; - for (i = 0; i < modem_bits; i++) { - rawdata[rbyte] |= ((codec_frames[cbyte] >> cbit) & 1) << rbit; - - rbit--; - if (rbit < 0) { - rbit = 7; - rbyte++; - rawdata[rbyte] = 0; - } - cbit--; - if (cbit < 0) { - cbit = 7; - cbyte++; - } - - nr_cbits++; - if (nr_cbits == codec_bits) { - if (cbit) - cbyte++; - cbit = 7; - nr_cbits = 0; - } + cbit--; + if (cbit < 0) { + cbit = 7; + cbyte++; + codec_frames[cbyte] = 0; + } + nr_cbits++; + if (nr_cbits == codec_bits) { + if (cbit) { + cbyte++; + codec_frames[cbyte] = 0; + } + cbit = 7; + nr_cbits = 0; } - return f->n_codec_frames; + } + return f->n_codec_frames; } +int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, + unsigned char *codec_frames) { + int cbit = 7; + int cbyte = 0; + int rbit = 7; + int rbyte = 0; + int modem_bits = freedv_get_bits_per_modem_frame(f); + int codec_bits = freedv_get_bits_per_codec_frame(f); + int nr_cbits = 0; + int i; + + rawdata[rbyte] = 0; + for (i = 0; i < modem_bits; i++) { + rawdata[rbyte] |= ((codec_frames[cbyte] >> cbit) & 1) << rbit; + + rbit--; + if (rbit < 0) { + rbit = 7; + rbyte++; + rawdata[rbyte] = 0; + } + + cbit--; + if (cbit < 0) { + cbit = 7; + cbyte++; + } + + nr_cbits++; + if (nr_cbits == codec_bits) { + if (cbit) cbyte++; + cbit = 7; + nr_cbits = 0; + } + } + return f->n_codec_frames; +} /*---------------------------------------------------------------------------*\ @@ -726,119 +736,129 @@ int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, u \*---------------------------------------------------------------------------*/ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) { - assert(f != NULL); - int i; - int nin = freedv_nin(f); - f->nin_prev = nin; - - assert(nin <= f->n_max_modem_samples); - - /* FSK Rx happens in real floats, so convert to those and call their demod here */ - if( FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) ){ - float rx_float[f->n_max_modem_samples]; - for(i=0; i<nin; i++) { - rx_float[i] = ((float)demod_in[i]); - } - return freedv_floatrx(f,speech_out,rx_float); + assert(f != NULL); + int i; + int nin = freedv_nin(f); + f->nin_prev = nin; + + assert(nin <= f->n_max_modem_samples); + + /* FSK Rx happens in real floats, so convert to those and call their demod + * here */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + float rx_float[f->n_max_modem_samples]; + for (i = 0; i < nin; i++) { + rx_float[i] = ((float)demod_in[i]); } + return freedv_floatrx(f, speech_out, rx_float); + } - if ( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) { - - float gain = 1.0f; + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) { + float gain = 1.0f; - assert(nin <= f->n_max_modem_samples); - COMP rx_fdm[f->n_max_modem_samples]; + assert(nin <= f->n_max_modem_samples); + COMP rx_fdm[f->n_max_modem_samples]; - for(i=0; i<nin; i++) { - rx_fdm[i].real = gain*(float)demod_in[i]; - rx_fdm[i].imag = 0.0f; - } - return freedv_comprx(f, speech_out, rx_fdm); + for (i = 0; i < nin; i++) { + rx_fdm[i].real = gain * (float)demod_in[i]; + rx_fdm[i].imag = 0.0f; } + return freedv_comprx(f, speech_out, rx_fdm); + } - /* special low memory version for 700D, to help with stm32 port */ - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) { - float gain = 2.0f; /* keep levels the same as Octave simulations and C unit tests for real signals */ - return freedv_shortrx(f, speech_out, demod_in, gain); - } + /* special low memory version for 700D, to help with stm32 port */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) { + float gain = 2.0f; /* keep levels the same as Octave simulations and C unit + tests for real signals */ + return freedv_shortrx(f, speech_out, demod_in, gain); + } - assert(1); /* should never get here */ - return 0; + assert(1); /* should never get here */ + return 0; } /* complex sample input version of freedv_rx() */ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { - assert(f != NULL); - assert(f->nin <= f->n_max_modem_samples); - int rx_status = 0; - f->nin_prev = freedv_nin(f); + assert(f != NULL); + assert(f->nin <= f->n_max_modem_samples); + int rx_status = 0; + f->nin_prev = freedv_nin(f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) { - rx_status = freedv_comprx_fdmdv_1600(f, demod_in); - } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) { - rx_status = freedv_comprx_700c(f, demod_in); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) { + rx_status = freedv_comprx_fdmdv_1600(f, demod_in); + } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + rx_status = freedv_comprx_700c(f, demod_in); + } - if( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))) { - rx_status = freedv_comprx_fsk(f, demod_in); - } + if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode))) { + rx_status = freedv_comprx_fsk(f, demod_in); + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) { - rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 2.0f); // was 1.0 ?? - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) { + rx_status = + freedv_comp_short_rx_ofdm(f, (void *)demod_in, 0, 2.0f); // was 1.0 ?? + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) { #ifdef __LPCNET__ - rx_status = freedv_comprx_2020(f, demod_in); + rx_status = freedv_comprx_2020(f, demod_in); #endif - } + } - short demod_in_short[f->nin_prev]; + short demod_in_short[f->nin_prev]; - for(int i=0; i<f->nin_prev; i++) - demod_in_short[i] = demod_in[i].real; + for (int i = 0; i < f->nin_prev; i++) demod_in_short[i] = demod_in[i].real; - return freedv_bits_to_speech(f, speech_out, demod_in_short, rx_status); + return freedv_bits_to_speech(f, speech_out, demod_in_short, rx_status); } /* memory efficient real short version - just for 700D on the SM1000 */ -int freedv_shortrx(struct freedv *f, short speech_out[], short demod_in[], float gain) { - assert(f != NULL); - int rx_status = 0; - f->nin_prev = f->nin; +int freedv_shortrx(struct freedv *f, short speech_out[], short demod_in[], + float gain) { + assert(f != NULL); + int rx_status = 0; + f->nin_prev = f->nin; - // At this stage short interface only supported for 700D, to help - // memory requirements on stm32 - assert((f->mode == FREEDV_MODE_700D) || (f->mode == FREEDV_MODE_700E)); - assert(f->nin <= f->n_max_modem_samples); + // At this stage short interface only supported for 700D, to help + // memory requirements on stm32 + assert((f->mode == FREEDV_MODE_700D) || (f->mode == FREEDV_MODE_700E)); + assert(f->nin <= f->n_max_modem_samples); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) { - rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 1, gain); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) { + rx_status = freedv_comp_short_rx_ofdm(f, (void *)demod_in, 1, gain); + } - return freedv_bits_to_speech(f, speech_out, demod_in, rx_status); + return freedv_bits_to_speech(f, speech_out, demod_in, rx_status); } +/* helper function, unpacked bits are much easier to work with inside the modem + */ -/* helper function, unpacked bits are much easier to work with inside the modem */ - -static void codec2_decode_upacked(struct freedv *f, short speech_out[], uint8_t unpacked_bits[]) { - int n_packed = (f->bits_per_codec_frame + 7) / 8; - uint8_t packed_codec_bits[n_packed]; +static void codec2_decode_upacked(struct freedv *f, short speech_out[], + uint8_t unpacked_bits[]) { + int n_packed = (f->bits_per_codec_frame + 7) / 8; + uint8_t packed_codec_bits[n_packed]; - freedv_pack(packed_codec_bits, unpacked_bits, f->bits_per_codec_frame); - codec2_decode(f->codec2, speech_out, packed_codec_bits); + freedv_pack(packed_codec_bits, unpacked_bits, f->bits_per_codec_frame); + codec2_decode(f->codec2, speech_out, packed_codec_bits); } - /*---------------------------------------------------------------------------* \ FUNCTION....: freedv_rx_bits_to_speech @@ -856,197 +876,211 @@ static void codec2_decode_upacked(struct freedv *f, short speech_out[], uint8_t We may not have demod sync, so various pass through options may happen with the input samples. We may squelch based on SNR. - Need to handle various codecs, and varying number of codec frames per modem frame - Squelch audio if test frames are being sent - Determine how many speech samples to return, which will vary if in sync/out of sync - Work with real and complex inputs (complex wrapper) - Attenuate audio on pass through - Deal with 700D first frame burble, and different sync states from OFDM modes like 700D - Output no samples if squelched, we assume it's OK for the audio sink to run dry - A FIFO required on output to smooth sample flow to audio sink - Don't decode when we are sending test frames + Need to handle various codecs, and varying number of codec frames per modem +frame Squelch audio if test frames are being sent Determine how many speech +samples to return, which will vary if in sync/out of sync Work with real and +complex inputs (complex wrapper) Attenuate audio on pass through Deal with 700D +first frame burble, and different sync states from OFDM modes like 700D Output +no samples if squelched, we assume it's OK for the audio sink to run dry A FIFO +required on output to smooth sample flow to audio sink Don't decode when we are +sending test frames \*---------------------------------------------------------------------------*/ -int freedv_bits_to_speech(struct freedv *f, short speech_out[], short demod_in[], int rx_status) { - int nout = 0; - int decode_speech = 0; - if ((rx_status & FREEDV_RX_SYNC) == 0) { - - if (!f->squelch_en) { - - /* pass through received samples so we can hear what's going on, e.g. during tuning */ - - if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020B) || - (f->mode == FREEDV_MODE_2020C)) { - /* 8kHz modem sample rate but 16 kHz speech sample - rate, so we need to resample */ - nout = 2*f->nin_prev; - assert(nout <= freedv_get_n_max_speech_samples(f)); - float tmp[nout]; - for(int i=0; i<nout/2; i++) - f->passthrough_2020[FDMDV_OS_TAPS_16K+i] = demod_in[i]; - fdmdv_8_to_16(tmp, &f->passthrough_2020[FDMDV_OS_TAPS_16K], nout/2); - for(int i=0; i<nout; i++) - speech_out[i] = f->passthrough_gain*tmp[i]; - } else { - /* Speech and modem rates might be different */ - int rate_factor = f->modem_sample_rate / f-> speech_sample_rate; - nout = f->nin_prev / rate_factor; - for(int i=0; i<nout; i++) - speech_out[i] = f->passthrough_gain*demod_in[i * rate_factor]; - } - } +int freedv_bits_to_speech(struct freedv *f, short speech_out[], + short demod_in[], int rx_status) { + int nout = 0; + int decode_speech = 0; + if ((rx_status & FREEDV_RX_SYNC) == 0) { + if (!f->squelch_en) { + /* pass through received samples so we can hear what's going on, e.g. + * during tuning */ + + if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020B) || + (f->mode == FREEDV_MODE_2020C)) { + /* 8kHz modem sample rate but 16 kHz speech sample + rate, so we need to resample */ + nout = 2 * f->nin_prev; + assert(nout <= freedv_get_n_max_speech_samples(f)); + float tmp[nout]; + for (int i = 0; i < nout / 2; i++) + f->passthrough_2020[FDMDV_OS_TAPS_16K + i] = demod_in[i]; + fdmdv_8_to_16(tmp, &f->passthrough_2020[FDMDV_OS_TAPS_16K], nout / 2); + for (int i = 0; i < nout; i++) + speech_out[i] = f->passthrough_gain * tmp[i]; + } else { + /* Speech and modem rates might be different */ + int rate_factor = f->modem_sample_rate / f->speech_sample_rate; + nout = f->nin_prev / rate_factor; + for (int i = 0; i < nout; i++) + speech_out[i] = f->passthrough_gain * demod_in[i * rate_factor]; + } } + } - if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS) && !f->test_frames) { - /* following logic is tricky so spell it out clearly, see table - in: https://github.com/drowe67/codec2/pull/111 */ - - if (!f->squelch_en) { - decode_speech = 1; - } else { - /* squelch is enabled */ - - /* anti-burble case - don't decode on trial sync unless the - frame has no bit errors. This prevents short lived trial - sync cases generating random bursts of audio */ - if (rx_status & FREEDV_RX_TRIAL_SYNC) { - if ((rx_status & FREEDV_RX_BIT_ERRORS) == 0) - decode_speech = 1; - } - else { - /* sync is solid - decode even through fades as there is still some speech info there */ - if (f->snr_est > f->snr_squelch_thresh) - decode_speech = 1; - } - } - + if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS) && + !f->test_frames) { + /* following logic is tricky so spell it out clearly, see table + in: https://github.com/drowe67/codec2/pull/111 */ + + if (!f->squelch_en) { + decode_speech = 1; + } else { + /* squelch is enabled */ + + /* anti-burble case - don't decode on trial sync unless the + frame has no bit errors. This prevents short lived trial + sync cases generating random bursts of audio */ + if (rx_status & FREEDV_RX_TRIAL_SYNC) { + if ((rx_status & FREEDV_RX_BIT_ERRORS) == 0) decode_speech = 1; + } else { + /* sync is solid - decode even through fades as there is still some + * speech info there */ + if (f->snr_est > f->snr_squelch_thresh) decode_speech = 1; + } } + } - if (decode_speech) { - if(FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)|| - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) { + if (decode_speech) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) { #ifdef __LPCNET__ - /* LPCNet decoder */ - - int bits_per_codec_frame = lpcnet_bits_per_frame(f->lpcnet); - int data_bits_per_frame = f->ldpc->data_bits_per_frame; - int frames = data_bits_per_frame/bits_per_codec_frame; - - nout = f->n_speech_samples; - for (int i = 0; i < frames; i++) { - lpcnet_dec(f->lpcnet, (char*) f->rx_payload_bits + i*bits_per_codec_frame, speech_out); - /* ear protection: on frames with errors and clipping, reduce level by 12dB */ - if (rx_status & FREEDV_RX_BIT_ERRORS) { - int max = 0.0; - for (int j=0; j<lpcnet_samples_per_frame(f->lpcnet); j++) - if (abs(speech_out[j]) > max) max = abs(speech_out[j]); - if (max == 32767) - for (int j=0; j<lpcnet_samples_per_frame(f->lpcnet); j++) speech_out[j] *= 0.25; - } - - speech_out += lpcnet_samples_per_frame(f->lpcnet); - } + /* LPCNet decoder */ + + int bits_per_codec_frame = lpcnet_bits_per_frame(f->lpcnet); + int data_bits_per_frame = f->ldpc->data_bits_per_frame; + int frames = data_bits_per_frame / bits_per_codec_frame; + + nout = f->n_speech_samples; + for (int i = 0; i < frames; i++) { + lpcnet_dec(f->lpcnet, + (char *)f->rx_payload_bits + i * bits_per_codec_frame, + speech_out); + /* ear protection: on frames with errors and clipping, reduce level by + * 12dB */ + if (rx_status & FREEDV_RX_BIT_ERRORS) { + int max = 0.0; + for (int j = 0; j < lpcnet_samples_per_frame(f->lpcnet); j++) + if (abs(speech_out[j]) > max) max = abs(speech_out[j]); + if (max == 32767) + for (int j = 0; j < lpcnet_samples_per_frame(f->lpcnet); j++) + speech_out[j] *= 0.25; + } + + speech_out += lpcnet_samples_per_frame(f->lpcnet); + } #endif + } else { + /* codec 2 decoder */ + + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) { + nout = f->n_speech_samples; + for (int i = 0; i < f->n_codec_frames; i++) { + codec2_decode_upacked( + f, speech_out, f->rx_payload_bits + i * f->bits_per_codec_frame); + speech_out += codec2_samples_per_frame(f->codec2); + } + } else { + /* non-interleaved Codec 2 modes */ + + nout = f->n_speech_samples; + if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode))) + codec2_decode(f->codec2, speech_out, f->rx_payload_bits); + else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + codec2_decode(f->codec2, &speech_out[0], &f->rx_payload_bits[0]); + codec2_decode(f->codec2, &speech_out[320], &f->rx_payload_bits[4]); } else { - /* codec 2 decoder */ - - if(FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) { - nout = f->n_speech_samples; - for (int i = 0; i < f->n_codec_frames; i++) { - codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame); - speech_out += codec2_samples_per_frame(f->codec2); - } - } else { - /* non-interleaved Codec 2 modes */ - - nout = f->n_speech_samples; - if ( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode))) - codec2_decode(f->codec2, speech_out, f->rx_payload_bits); - else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) { - codec2_decode(f->codec2, &speech_out[ 0], &f->rx_payload_bits[0]); - codec2_decode(f->codec2, &speech_out[320], &f->rx_payload_bits[4]); - } else { - for (int i = 0; i <f->n_codec_frames; i++) { - codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame); - speech_out += codec2_samples_per_frame(f->codec2); - } - } - } + for (int i = 0; i < f->n_codec_frames; i++) { + codec2_decode_upacked( + f, speech_out, + f->rx_payload_bits + i * f->bits_per_codec_frame); + speech_out += codec2_samples_per_frame(f->codec2); + } } + } } + } - if (f->verbose == 3) { - fprintf(stderr, " sqen: %d nout: %d decsp: %d\n", f->squelch_en, nout, decode_speech); - } + if (f->verbose == 3) { + fprintf(stderr, " sqen: %d nout: %d decsp: %d\n", f->squelch_en, nout, + decode_speech); + } - f->rx_status= rx_status; - assert(nout <= freedv_get_n_max_speech_samples(f)); - return nout; + f->rx_status = rx_status; + assert(nout <= freedv_get_n_max_speech_samples(f)); + return nout; } +/* a way to receive raw frames of bytes, or speech data that will be + * decompressed externally */ +int freedv_rawdatarx(struct freedv *f, unsigned char *packed_payload_bits, + short demod_in[]) { + assert(f != NULL); + int nin = freedv_nin(f); + assert(nin <= f->n_max_modem_samples); + COMP demod_in_comp[f->n_max_modem_samples]; + + for (int i = 0; i < nin; i++) { + demod_in_comp[i].real = (float)demod_in[i]; + demod_in_comp[i].imag = 0.0; + } -/* a way to receive raw frames of bytes, or speech data that will be decompressed externally */ -int freedv_rawdatarx(struct freedv *f, unsigned char *packed_payload_bits, short demod_in[]) -{ - assert(f != NULL); - int nin = freedv_nin(f); - assert(nin <= f->n_max_modem_samples); - COMP demod_in_comp[f->n_max_modem_samples]; - - for(int i=0; i<nin; i++) { - demod_in_comp[i].real = (float)demod_in[i]; - demod_in_comp[i].imag = 0.0; - } - - return freedv_rawdatacomprx(f, packed_payload_bits, demod_in_comp); + return freedv_rawdatacomprx(f, packed_payload_bits, demod_in_comp); } -/* a way to receive raw frames of bytes, or speech data that will be decompressed externally */ -int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, COMP demod_in[]) -{ - assert(f != NULL); - int ret = 0; - int rx_status = 0; - - /* FSK modes used packed bits internally */ - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - rx_status = freedv_comprx_fsk(f, demod_in); - f->rx_status = rx_status; - if (rx_status & FREEDV_RX_BITS) { - ret = (freedv_get_bits_per_modem_frame(f) + 7) / 8; - freedv_rawdata_from_codec_frames(f, packed_payload_bits, f->rx_payload_bits); - } - return ret; +/* a way to receive raw frames of bytes, or speech data that will be + * decompressed externally */ +int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, + COMP demod_in[]) { + assert(f != NULL); + int ret = 0; + int rx_status = 0; + + /* FSK modes used packed bits internally */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + rx_status = freedv_comprx_fsk(f, demod_in); + f->rx_status = rx_status; + if (rx_status & FREEDV_RX_BITS) { + ret = (freedv_get_bits_per_modem_frame(f) + 7) / 8; + freedv_rawdata_from_codec_frames(f, packed_payload_bits, + f->rx_payload_bits); } + return ret; + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) rx_status = freedv_comprx_fdmdv_1600(f, demod_in); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) rx_status = freedv_comprx_700c(f, demod_in); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 1.0f); - if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) { - rx_status = freedv_rx_fsk_ldpc_data(f, demod_in); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) + rx_status = freedv_comprx_fdmdv_1600(f, demod_in); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) + rx_status = freedv_comprx_700c(f, demod_in); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode)) + rx_status = freedv_comp_short_rx_ofdm(f, (void *)demod_in, 0, 1.0f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, f->mode)) { + rx_status = freedv_rx_fsk_ldpc_data(f, demod_in); + } - if (rx_status & FREEDV_RX_BITS) { - ret = (f->bits_per_modem_frame+7)/8; - freedv_pack(packed_payload_bits, f->rx_payload_bits, f->bits_per_modem_frame); - } + if (rx_status & FREEDV_RX_BITS) { + ret = (f->bits_per_modem_frame + 7) / 8; + freedv_pack(packed_payload_bits, f->rx_payload_bits, + f->bits_per_modem_frame); + } - /* might want to check this for errors, e.g. if reliable data is important */ - f->rx_status= rx_status; + /* might want to check this for errors, e.g. if reliable data is important */ + f->rx_status = rx_status; - return ret; + return ret; } - /*---------------------------------------------------------------------------* \ FUNCTION....: freedv_get_version @@ -1058,10 +1092,7 @@ int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, C \*---------------------------------------------------------------------------*/ -int freedv_get_version(void) -{ - return VERSION; -} +int freedv_get_version(void) { return VERSION; } /*---------------------------------------------------------------------------* \ @@ -1074,10 +1105,7 @@ int freedv_get_version(void) \*---------------------------------------------------------------------------*/ static char git_hash[] = GIT_HASH; -char *freedv_get_hash(void) -{ - return git_hash; -} +char *freedv_get_hash(void) { return git_hash; } /*---------------------------------------------------------------------------*\ @@ -1099,13 +1127,13 @@ char *freedv_get_hash(void) \*---------------------------------------------------------------------------*/ -void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_callback_tx tx, void *state) -{ - if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) { - f->freedv_put_next_rx_char = rx; - f->freedv_get_next_tx_char = tx; - f->callback_state = state; - } +void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, + freedv_callback_tx tx, void *state) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode) == false) { + f->freedv_put_next_rx_char = rx; + f->freedv_get_next_tx_char = tx; + f->callback_state = state; + } } /*---------------------------------------------------------------------------*\ @@ -1115,8 +1143,8 @@ void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_cal DATE CREATED: 19 August 2021 Set the callback functions and the callback state pointer that will - be used to provide the raw symbols for the aux txt channel. The - freedv_callback_rx_sym is a function pointer that will be called to + be used to provide the raw symbols for the aux txt channel. The + freedv_callback_rx_sym is a function pointer that will be called to return received symbols. The callback state is a user-defined void pointer that will be passed to the callback function. Any or all can be NULL, and the default is all NULL. @@ -1127,16 +1155,16 @@ void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_cal Note: Active for OFDM modes only (700D/E, 2020). \*---------------------------------------------------------------------------*/ -void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, void *state) -{ - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode ) || - FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode ) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode ) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) { - f->freedv_put_next_rx_symbol = rx; - f->callback_state_sym = state; - } +void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, + void *state) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) { + f->freedv_put_next_rx_symbol = rx; + f->callback_state_sym = state; + } } /*---------------------------------------------------------------------------*\ @@ -1159,12 +1187,14 @@ void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, vo \*---------------------------------------------------------------------------*/ -void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state){ - if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) { - f->freedv_put_next_proto = rx; - f->freedv_get_next_proto = tx; - f->proto_callback_state = callback_state; - } +void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, + freedv_callback_prototx tx, + void *callback_state) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode) == false) { + f->freedv_put_next_proto = rx; + f->freedv_get_next_proto = tx; + f->proto_callback_state = callback_state; + } } /*---------------------------------------------------------------------------*\ @@ -1184,16 +1214,18 @@ void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, \*---------------------------------------------------------------------------*/ -void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state) { - if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){ - if (!f->deframer->fdc) - f->deframer->fdc = freedv_data_channel_create(); - if (!f->deframer->fdc) - return; - - freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state); - freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state); - } +void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, + freedv_callback_datatx datatx, + void *callback_state) { + if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode))) { + if (!f->deframer->fdc) f->deframer->fdc = freedv_data_channel_create(); + if (!f->deframer->fdc) return; + + freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state); + freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state); + } } /*---------------------------------------------------------------------------*\ @@ -1211,16 +1243,15 @@ void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, f \*---------------------------------------------------------------------------*/ -void freedv_set_data_header(struct freedv *f, unsigned char *header) -{ - if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){ - if (!f->deframer->fdc) - f->deframer->fdc = freedv_data_channel_create(); - if (!f->deframer->fdc) - return; +void freedv_set_data_header(struct freedv *f, unsigned char *header) { + if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) || + (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode))) { + if (!f->deframer->fdc) f->deframer->fdc = freedv_data_channel_create(); + if (!f->deframer->fdc) return; - freedv_data_set_header(f->deframer->fdc, header); - } + freedv_data_set_header(f->deframer->fdc, header); + } } /*---------------------------------------------------------------------------*\ @@ -1234,14 +1265,13 @@ void freedv_set_data_header(struct freedv *f, unsigned char *header) \*---------------------------------------------------------------------------*/ -void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est) -{ - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) - fdmdv_get_demod_stats(f->fdmdv, &f->stats); - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) - cohpsk_get_demod_stats(f->cohpsk, &f->stats); - if (sync) *sync = f->sync; - if (snr_est) *snr_est = f->snr_est; +void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) + fdmdv_get_demod_stats(f->fdmdv, &f->stats); + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) + cohpsk_get_demod_stats(f->cohpsk, &f->stats); + if (sync) *sync = f->sync; + if (snr_est) *snr_est = f->snr_est; } /*---------------------------------------------------------------------------*\ @@ -1255,75 +1285,93 @@ void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est) \*---------------------------------------------------------------------------*/ -void freedv_set_test_frames (struct freedv *f, int val) {f->test_frames = val;} -void freedv_set_test_frames_diversity (struct freedv *f, int val) {f->test_frames_diversity = val;} -void freedv_set_squelch_en (struct freedv *f, bool val) {f->squelch_en = val;} -void freedv_set_total_bit_errors (struct freedv *f, int val) {f->total_bit_errors = val;} -void freedv_set_total_bits (struct freedv *f, int val) {f->total_bits = val;} -void freedv_set_total_bit_errors_coded (struct freedv *f, int val) {f->total_bit_errors_coded = val;} -void freedv_set_total_bits_coded (struct freedv *f, int val) {f->total_bits_coded = val;} -void freedv_set_total_packet_errors (struct freedv *f, int val) {f->total_packet_errors = val;} -void freedv_set_total_packets (struct freedv *f, int val) {f->total_packets = val;} -void freedv_set_varicode_code_num (struct freedv *f, int val) {varicode_set_code_num(&f->varicode_dec_states, val);} -void freedv_set_ext_vco (struct freedv *f, int val) {f->ext_vco = val;} -void freedv_set_snr_squelch_thresh (struct freedv *f, float val) {f->snr_squelch_thresh = val;} -void freedv_set_tx_amp (struct freedv *f, float amp) {f->tx_amp = amp;} -void freedv_passthrough_gain (struct freedv *f, float g) {f->passthrough_gain = g;} +void freedv_set_test_frames(struct freedv *f, int val) { f->test_frames = val; } +void freedv_set_test_frames_diversity(struct freedv *f, int val) { + f->test_frames_diversity = val; +} +void freedv_set_squelch_en(struct freedv *f, bool val) { f->squelch_en = val; } +void freedv_set_total_bit_errors(struct freedv *f, int val) { + f->total_bit_errors = val; +} +void freedv_set_total_bits(struct freedv *f, int val) { f->total_bits = val; } +void freedv_set_total_bit_errors_coded(struct freedv *f, int val) { + f->total_bit_errors_coded = val; +} +void freedv_set_total_bits_coded(struct freedv *f, int val) { + f->total_bits_coded = val; +} +void freedv_set_total_packet_errors(struct freedv *f, int val) { + f->total_packet_errors = val; +} +void freedv_set_total_packets(struct freedv *f, int val) { + f->total_packets = val; +} +void freedv_set_varicode_code_num(struct freedv *f, int val) { + varicode_set_code_num(&f->varicode_dec_states, val); +} +void freedv_set_ext_vco(struct freedv *f, int val) { f->ext_vco = val; } +void freedv_set_snr_squelch_thresh(struct freedv *f, float val) { + f->snr_squelch_thresh = val; +} +void freedv_set_tx_amp(struct freedv *f, float amp) { f->tx_amp = amp; } +void freedv_passthrough_gain(struct freedv *f, float g) { + f->passthrough_gain = g; +} /* supported by 700C, 700D, 700E */ void freedv_set_clip(struct freedv *f, bool val) { - f->clip_en = val; - if (is_ofdm_mode(f)) { - f->ofdm->clip_en = val; - /* really should have BPF if we clip */ - if (val) - ofdm_set_tx_bpf(f->ofdm, true); - } + f->clip_en = val; + if (is_ofdm_mode(f)) { + f->ofdm->clip_en = val; + /* really should have BPF if we clip */ + if (val) ofdm_set_tx_bpf(f->ofdm, true); + } } /* Band Pass Filter to cleanup OFDM tx waveform, only supported by some modes */ void freedv_set_tx_bpf(struct freedv *f, int val) { - if (is_ofdm_mode(f)) { - ofdm_set_tx_bpf(f->ofdm, val); - } + if (is_ofdm_mode(f)) { + ofdm_set_tx_bpf(f->ofdm, val); + } } void freedv_set_phase_est_bandwidth_mode(struct freedv *f, int val) { - if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) { - ofdm_set_phase_est_bandwidth_mode(f->ofdm, val); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode)) { + ofdm_set_phase_est_bandwidth_mode(f->ofdm, val); + } } // For those FreeDV modes using the codec 2 700C vocoder 700C/D/E/800XA void freedv_set_eq(struct freedv *f, bool val) { - if (f->codec2 != NULL) { - codec2_700c_eq(f->codec2, val); - } + if (f->codec2 != NULL) { + codec2_700c_eq(f->codec2, val); + } } void freedv_set_verbose(struct freedv *f, int verbosity) { - f->verbose = verbosity; - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) { - cohpsk_set_verbose(f->cohpsk, f->verbose); - } - if (is_ofdm_mode(f)) { - ofdm_set_verbose(f->ofdm, f->verbose-1); - } + f->verbose = verbosity; + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + cohpsk_set_verbose(f->cohpsk, f->verbose); + } + if (is_ofdm_mode(f)) { + ofdm_set_verbose(f->ofdm, f->verbose - 1); + } } -void freedv_set_callback_error_pattern(struct freedv *f, freedv_calback_error_pattern cb, void *state) -{ - f->freedv_put_error_pattern = cb; - f->error_pattern_callback_state = state; +void freedv_set_callback_error_pattern(struct freedv *f, + freedv_calback_error_pattern cb, + void *state) { + f->freedv_put_error_pattern = cb; + f->error_pattern_callback_state = state; } void freedv_set_carrier_ampl(struct freedv *f, int c, float ampl) { - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) - { - cohpsk_set_carrier_ampl(f->cohpsk, c, ampl); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + cohpsk_set_carrier_ampl(f->cohpsk, c, ampl); + } } /*---------------------------------------------------------------------------* \ @@ -1333,31 +1381,31 @@ void freedv_set_carrier_ampl(struct freedv *f, int c, float ampl) { DATE CREATED: May 2018 Extended control of sync state machines for OFDM modes. - + Ensure this is called in the same thread as freedv_rx(). \*---------------------------------------------------------------------------*/ void freedv_set_sync(struct freedv *freedv, int sync_cmd) { - assert (freedv != NULL); + assert(freedv != NULL); - if (freedv->ofdm != NULL) { - ofdm_set_sync(freedv->ofdm, sync_cmd); - } + if (freedv->ofdm != NULL) { + ofdm_set_sync(freedv->ofdm, sync_cmd); + } } // this also selects burst mode void freedv_set_frames_per_burst(struct freedv *freedv, int framesperburst) { - assert (freedv != NULL); - if (freedv->ofdm != NULL) { - // change of nomenclature as we cross into the OFDM modem layer. In the - // OFDM modem we have packets that contain multiple "modem frames" - ofdm_set_packets_per_burst(freedv->ofdm, framesperburst); - } + assert(freedv != NULL); + if (freedv->ofdm != NULL) { + // change of nomenclature as we cross into the OFDM modem layer. In the + // OFDM modem we have packets that contain multiple "modem frames" + ofdm_set_packets_per_burst(freedv->ofdm, framesperburst); + } } -struct FSK * freedv_get_fsk(struct freedv *f){ - return f->fsk; +struct FSK *freedv_get_fsk(struct freedv *f) { + return f->fsk; } /*---------------------------------------------------------------------------*\ @@ -1370,29 +1418,59 @@ struct FSK * freedv_get_fsk(struct freedv *f){ \*---------------------------------------------------------------------------*/ -int freedv_get_protocol_bits (struct freedv *f) {return f->n_protocol_bits;} -int freedv_get_mode (struct freedv *f) {return f->mode;} -int freedv_get_test_frames (struct freedv *f) {return f->test_frames;} -int freedv_get_speech_sample_rate (struct freedv *f) {return f-> speech_sample_rate;} -int freedv_get_n_speech_samples (struct freedv *f) {return f->n_speech_samples;} -int freedv_get_modem_sample_rate (struct freedv *f) {return f->modem_sample_rate;} -int freedv_get_modem_symbol_rate (struct freedv *f) {return f->modem_symbol_rate;} -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_n_tx_modem_samples (struct freedv *f) {return f->n_nat_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;} -int freedv_get_total_bits_coded (struct freedv *f) {return f->total_bits_coded;} -int freedv_get_total_bit_errors_coded (struct freedv *f) {return f->total_bit_errors_coded;} -int freedv_get_total_packets (struct freedv *f) {return f->total_packets;} -int freedv_get_total_packet_errors (struct freedv *f) {return f->total_packet_errors;} -int freedv_get_sync (struct freedv *f) {return f->sync;} -struct CODEC2 *freedv_get_codec2 (struct freedv *f) {return f->codec2;} -int freedv_get_bits_per_codec_frame (struct freedv *f) {return f->bits_per_codec_frame;} -int freedv_get_bits_per_modem_frame (struct freedv *f) {return f->bits_per_modem_frame;} -int freedv_get_rx_status (struct freedv *f) {return f->rx_status;} -void freedv_get_fsk_S_and_N (struct freedv *f, float *S, float *N) { *S = f->fsk_S[0]; *N = f->fsk_N[0]; } - +int freedv_get_protocol_bits(struct freedv *f) { return f->n_protocol_bits; } +int freedv_get_mode(struct freedv *f) { return f->mode; } +int freedv_get_test_frames(struct freedv *f) { return f->test_frames; } +int freedv_get_speech_sample_rate(struct freedv *f) { + return f->speech_sample_rate; +} +int freedv_get_n_speech_samples(struct freedv *f) { + return f->n_speech_samples; +} +int freedv_get_modem_sample_rate(struct freedv *f) { + return f->modem_sample_rate; +} +int freedv_get_modem_symbol_rate(struct freedv *f) { + return f->modem_symbol_rate; +} +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_n_tx_modem_samples(struct freedv *f) { + return f->n_nat_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; +} +int freedv_get_total_bits_coded(struct freedv *f) { + return f->total_bits_coded; +} +int freedv_get_total_bit_errors_coded(struct freedv *f) { + return f->total_bit_errors_coded; +} +int freedv_get_total_packets(struct freedv *f) { return f->total_packets; } +int freedv_get_total_packet_errors(struct freedv *f) { + return f->total_packet_errors; +} +int freedv_get_sync(struct freedv *f) { return f->sync; } +struct CODEC2 *freedv_get_codec2(struct freedv *f) { + return f->codec2; +} +int freedv_get_bits_per_codec_frame(struct freedv *f) { + return f->bits_per_codec_frame; +} +int freedv_get_bits_per_modem_frame(struct freedv *f) { + return f->bits_per_modem_frame; +} +int freedv_get_rx_status(struct freedv *f) { return f->rx_status; } +void freedv_get_fsk_S_and_N(struct freedv *f, float *S, float *N) { + *S = f->fsk_S[0]; + *N = f->fsk_N[0]; +} /*---------------------------------------------------------------------------*\ @@ -1401,127 +1479,131 @@ void freedv_get_fsk_S_and_N (struct freedv *f, float *S, float *N) DATE CREATED: 18 feb 2022 DEFAULT.....: fmin: -50.0Hz fmax: 50.0Hz DESCRIPTION.: - + |<---fmin - | rx centre frequency | + fmax--->| - - Useful for handling frequency offsets, - e.g. caused by an imprecise VFO, the trade off is more CPU power is required. - -\*---------------------------------------------------------------------------*/ -int freedv_set_tuning_range(struct freedv *freedv, float val_fmin, float val_fmax) { - if (is_ofdm_data_mode(freedv) && (strcmp(freedv->ofdm->data_mode, "burst") == 0)) { - freedv->ofdm->fmin = val_fmin; - freedv->ofdm->fmax = val_fmax; - return 1; - } else { - return 0; - } -} + Useful for handling frequency offsets, + e.g. caused by an imprecise VFO, the trade off is more CPU power is required. +\*---------------------------------------------------------------------------*/ +int freedv_set_tuning_range(struct freedv *freedv, float val_fmin, + float val_fmax) { + if (is_ofdm_data_mode(freedv) && + (strcmp(freedv->ofdm->data_mode, "burst") == 0)) { + freedv->ofdm->fmin = val_fmin; + freedv->ofdm->fmax = val_fmax; + return 1; + } else { + return 0; + } +} int freedv_get_n_max_speech_samples(struct freedv *f) { - /* When "passing through" demod samples to the speech output - (e.g. no sync and squelch off) f->nin bounces around with - timing variations. So we may return - freedv_get_n_max_modem_samples() via the speech_output[] - array */ - int max_output_passthrough_samples; - if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || - FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || - FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) - // In 2020 we oversample the input modem samples from 8->16 kHz - max_output_passthrough_samples = 2*freedv_get_n_max_modem_samples(f); - else - max_output_passthrough_samples = freedv_get_n_max_modem_samples(f); - - if (max_output_passthrough_samples > f->n_speech_samples) - return max_output_passthrough_samples; - else - return f->n_speech_samples; + /* When "passing through" demod samples to the speech output + (e.g. no sync and squelch off) f->nin bounces around with + timing variations. So we may return + freedv_get_n_max_modem_samples() via the speech_output[] + array */ + int max_output_passthrough_samples; + if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode)) + // In 2020 we oversample the input modem samples from 8->16 kHz + max_output_passthrough_samples = 2 * freedv_get_n_max_modem_samples(f); + else + max_output_passthrough_samples = freedv_get_n_max_modem_samples(f); + + if (max_output_passthrough_samples > f->n_speech_samples) + return max_output_passthrough_samples; + else + return f->n_speech_samples; } // Now dummy obsolete call -int freedv_get_sync_interleaver(struct freedv *f) { - return 1; -} - -int freedv_get_sz_error_pattern(struct freedv *f) -{ - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) { - /* if diversity disabled callback sends error pattern for upper and lower carriers */ - return f->sz_error_pattern * (2 - f->test_frames_diversity); - } else { - return f->sz_error_pattern; - } +int freedv_get_sync_interleaver(struct freedv *f) { return 1; } + +int freedv_get_sz_error_pattern(struct freedv *f) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + /* if diversity disabled callback sends error pattern for upper and lower + * carriers */ + return f->sz_error_pattern * (2 - f->test_frames_diversity); + } else { + return f->sz_error_pattern; + } } // Get modem status, scatter/eye diagram for plotting, other goodies -void freedv_get_modem_extended_stats(struct freedv *f, struct MODEM_STATS *stats) -{ - if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) - fdmdv_get_demod_stats(f->fdmdv, stats); - - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) { - fsk_get_demod_stats(f->fsk, stats); /* eye diagram samples, clock offset etc */ - stats->snr_est = f->snr_est; /* estimated when fsk_demod() called in freedv_fsk.c */ - stats->sync = f->sync; /* sync indicator comes from framing layer */ - } +void freedv_get_modem_extended_stats(struct freedv *f, + struct MODEM_STATS *stats) { + if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) + fdmdv_get_demod_stats(f->fdmdv, stats); + + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fsk_get_demod_stats(f->fsk, + stats); /* eye diagram samples, clock offset etc */ + stats->snr_est = + f->snr_est; /* estimated when fsk_demod() called in freedv_fsk.c */ + stats->sync = f->sync; /* sync indicator comes from framing layer */ + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) { - fmfsk_get_demod_stats(f->fmfsk, stats); - stats->snr_est = f->snr_est; - stats->sync = f->sync; - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + fmfsk_get_demod_stats(f->fmfsk, stats); + stats->snr_est = f->snr_est; + stats->sync = f->sync; + } - if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) { - cohpsk_get_demod_stats(f->cohpsk, stats); - } + if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) { + cohpsk_get_demod_stats(f->cohpsk, stats); + } - if (is_ofdm_mode(f)) { - // OFDM modem stats updated when demod runs, so copy last update - // We need to avoid over writing the FFT states which are updated by a different function - // TODO we need a better design here: Issue #182 + if (is_ofdm_mode(f)) { + // OFDM modem stats updated when demod runs, so copy last update + // We need to avoid over writing the FFT states which are updated by a + // different function + // TODO we need a better design here: Issue #182 #ifndef __EMBEDDED__ - size_t ncopy = (void*)stats->rx_eye - (void*)stats; - memcpy(stats, &f->stats, ncopy); + size_t ncopy = (void *)stats->rx_eye - (void *)stats; + memcpy(stats, &f->stats, ncopy); #endif - stats->snr_est = f->snr_est; - stats->sync = f->sync; + stats->snr_est = f->snr_est; + stats->sync = f->sync; } } int freedv_get_n_tx_preamble_modem_samples(struct freedv *f) { - if (f->mode == FREEDV_MODE_FSK_LDPC) { - struct FSK *fsk = f->fsk; - int npreamble_symbols = 50*(fsk->mode>>1); - return fsk->Ts*npreamble_symbols; - } else if (is_ofdm_data_mode(f)) { - return f->ofdm->samplesperframe; - } - - return 0; + if (f->mode == FREEDV_MODE_FSK_LDPC) { + struct FSK *fsk = f->fsk; + int npreamble_symbols = 50 * (fsk->mode >> 1); + return fsk->Ts * npreamble_symbols; + } else if (is_ofdm_data_mode(f)) { + return f->ofdm->samplesperframe; + } + + return 0; } int freedv_get_n_tx_postamble_modem_samples(struct freedv *f) { - if (is_ofdm_data_mode(f)) { - return f->ofdm->samplesperframe; - } - - return 0; + if (is_ofdm_data_mode(f)) { + return f->ofdm->samplesperframe; + } + + return 0; } -// from http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum +// from +// http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum -unsigned short freedv_gen_crc16(unsigned char* data_p, int length) { - unsigned char x; - unsigned short crc = 0xFFFF; +unsigned short freedv_gen_crc16(unsigned char *data_p, int length) { + unsigned char x; + unsigned short crc = 0xFFFF; - while (length--) { - x = crc >> 8 ^ *data_p++; - x ^= x>>4; - crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x); - } + while (length--) { + x = crc >> 8 ^ *data_p++; + x ^= x >> 4; + crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ + ((unsigned short)(x << 5)) ^ ((unsigned short)x); + } - return crc; + return crc; } |
