From b145f8d910fac30364540d754cc76c89fc2b02b6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 13 Jun 2015 00:18:57 +0000 Subject: [PATCH] integrated freedv 700 mode into the freedv API git-svn-id: https://svn.code.sf.net/p/freetel/code@2182 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/src/codec2.c | 3 + codec2-dev/src/codec2_cohpsk.h | 13 +- codec2-dev/src/cohpsk.c | 11 +- codec2-dev/src/cohpsk_ch.c | 4 +- codec2-dev/src/cohpsk_demod.c | 6 +- codec2-dev/src/cohpsk_mod.c | 8 +- codec2-dev/src/freedv_api.c | 490 ++++++++++++++++++++++----------- codec2-dev/src/freedv_api.h | 13 +- codec2-dev/src/freedv_rx.c | 47 ++-- codec2-dev/src/freedv_tx.c | 43 ++- 10 files changed, 433 insertions(+), 205 deletions(-) diff --git a/codec2-dev/src/codec2.c b/codec2-dev/src/codec2.c index d1208641..debb89eb 100644 --- a/codec2-dev/src/codec2.c +++ b/codec2-dev/src/codec2.c @@ -1690,6 +1690,9 @@ int codec2_get_spare_bit_index(struct CODEC2 *c2) case CODEC2_MODE_1600: return 15; // bit 15 (16th bit) is v2 (third voicing bit) break; + case CODEC2_MODE_700: + return 26; // bits 26 and 27 are spare + break; } return -1; diff --git a/codec2-dev/src/codec2_cohpsk.h b/codec2-dev/src/codec2_cohpsk.h index 9dce5806..273a2c91 100644 --- a/codec2-dev/src/codec2_cohpsk.h +++ b/codec2-dev/src/codec2_cohpsk.h @@ -28,11 +28,14 @@ #ifndef __CODEC2_COHPSK__ #define __CODEC2_COHPSK__ -#define COHPSK_BITS_PER_FRAME 56 /* hard coded for now */ -#define COHPSK_NC 7 /* hard coded for now */ -#define COHPSK_SAMPLES_PER_FRAME 600 -#define COHPSK_RS 75 -#define COHPSK_FS 7500 /* note this is a wierd value to get an integer oversampling rate */ +#define COHPSK_BITS_PER_FRAME 56 /* hard coded for now */ +#define COHPSK_NC 7 /* hard coded for now */ +#define COHPSK_NOM_SAMPLES_PER_FRAME 600 +#define COHPSK_MAX_SAMPLES_PER_FRAME 625 +#define COHPSK_RS 75 +#define COHPSK_FS 7500 /* note this is a wierd + value to get an integer + oversampling rate */ #include "comp.h" diff --git a/codec2-dev/src/cohpsk.c b/codec2-dev/src/cohpsk.c index a87203ea..677d4f72 100644 --- a/codec2-dev/src/cohpsk.c +++ b/codec2-dev/src/cohpsk.c @@ -86,7 +86,8 @@ struct COHPSK *cohpsk_create(void) float freq_hz; assert(COHPSK_NC == PILOTS_NC); - assert(COHPSK_SAMPLES_PER_FRAME == COHPSK_M*NSYMROWPILOT); + assert(COHPSK_NOM_SAMPLES_PER_FRAME == (COHPSK_M*NSYMROWPILOT)); + assert(COHPSK_MAX_SAMPLES_PER_FRAME == (COHPSK_M*NSYMROWPILOT+COHPSK_M/P)); assert(COHPSK_ND == ND); assert(COHPSK_NSYM == NSYM); /* as we want to use the tx sym mem on fdmdv */ assert(COHPSK_NT == NT); @@ -619,7 +620,7 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync) DATE CREATED: 5/4/2015 COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME bits and - generates a frame of COHPSK_SAMPLES_PER_FRAME modulated symbols. + generates a frame of COHPSK_NOM_SAMPLES_PER_FRAME modulated symbols. The output signal is complex to support single sided frequency shifting, for example when testing frequency offsets in channel @@ -662,7 +663,7 @@ void cohpsk_clip(COMP tx_fdm[]) float mag; int i; - for(i=0; i COHPSK_CLIP) { @@ -907,7 +908,7 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM DATE CREATED: 5/4/2015 COHPSK demodulator, takes an array of (nominally) nin_frame = - COHPSK_SAMPLES_PER_FRAME modulated samples, returns an array of + COHPSK_NOM_SAMPLES_PER_FRAME modulated samples, returns an array of COHPSK_BITS_PER_FRAME bits. The input signal is complex to support single sided frequency shifting @@ -921,6 +922,8 @@ void cohpsk_demod(struct COHPSK *coh, float rx_bits[], int *reliable_sync_bit, C int i, j, sync, anext_sync, next_sync, nin, r, c; float max_ratio, f_est; + assert(*nin_frame <= COHPSK_MAX_SAMPLES_PER_FRAME); + next_sync = sync = coh->sync; for (i=0; i #include #include +#include #include "codec2.h" #include "codec2_fdmdv.h" +#include "fdmdv_internal.h" #include "golay23.h" #include "varicode.h" #include "freedv_api.h" +#include "comp_prim.h" /*---------------------------------------------------------------------------*\ @@ -57,44 +60,70 @@ struct freedv *freedv_open(int mode) { struct freedv *f; int Nc, codec2_mode, nbit, nbyte; - if (mode != FREEDV_MODE_1600) + if ((mode != FREEDV_MODE_1600) && (mode != FREEDV_MODE_700)) return NULL; - + f = (struct freedv*)malloc(sizeof(struct freedv)); if (f == NULL) return NULL; - + f->mode = mode; - f->tx_sync_bit = 0; - f->snr_thresh = 2.0; - + if (mode == FREEDV_MODE_1600) { Nc = 16; + f->tx_sync_bit = 0; codec2_mode = CODEC2_MODE_1300; + f->fdmdv = fdmdv_create(Nc); + if (f->fdmdv == NULL) + return NULL; + f->snr_thresh = 2.0; + golay23_init(); + f->nin = FDMDV_NOM_SAMPLES_PER_FRAME; + f->n_nom_modem_samples = 2*FDMDV_NOM_SAMPLES_PER_FRAME; + f->n_max_modem_samples = FDMDV_NOM_SAMPLES_PER_FRAME+FDMDV_MAX_SAMPLES_PER_FRAME; + f->modem_sample_rate = FS; + nbit = fdmdv_bits_per_frame(f->fdmdv); + f->fdmdv_bits = (int*)malloc(nbit*sizeof(int)); + if (f->fdmdv_bits == NULL) + return NULL; + nbit = 2*fdmdv_bits_per_frame(f->fdmdv); + f->tx_bits = (int*)malloc(nbit*sizeof(int)); + f->rx_bits = (int*)malloc(nbit*sizeof(int)); + if ((f->tx_bits == NULL) || (f->rx_bits == NULL)) + return NULL; + } + + if (mode == FREEDV_MODE_700) { + codec2_mode = CODEC2_MODE_700; + f->cohpsk = cohpsk_create(); + f->nin = COHPSK_NOM_SAMPLES_PER_FRAME; + f->n_nom_modem_samples = COHPSK_NOM_SAMPLES_PER_FRAME; + f->n_max_modem_samples = COHPSK_MAX_SAMPLES_PER_FRAME; + f->modem_sample_rate = COHPSK_FS; /* note wierd sample rate */ + f->clip = 1; + nbit = COHPSK_BITS_PER_FRAME; + f->tx_bits = (int*)malloc(nbit*sizeof(int)); + if (f->tx_bits == NULL) + return NULL; } f->codec2 = codec2_create(codec2_mode); if (f->codec2 == NULL) return NULL; - - f->fdmdv = fdmdv_create(Nc); - if (f->fdmdv == NULL) - return NULL; + if (mode == FREEDV_MODE_1600) + f->n_speech_samples = codec2_samples_per_frame(f->codec2); + if (mode == FREEDV_MODE_700) + f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2); nbit = codec2_bits_per_frame(f->codec2); nbyte = (nbit + 7) / 8; f->packed_codec_bits = (unsigned char*)malloc(nbyte*sizeof(char)); - f->codec_bits = (int*)malloc(nbit*sizeof(int)); + if (mode == FREEDV_MODE_1600) + f->codec_bits = (int*)malloc(nbit*sizeof(int)); + if (mode == FREEDV_MODE_700) + f->codec_bits = (int*)malloc(COHPSK_BITS_PER_FRAME*sizeof(int)); - nbit = 2*fdmdv_bits_per_frame(f->fdmdv); - f->tx_bits = (int*)malloc(nbit*sizeof(int)); - f->rx_bits = (int*)malloc(nbit*sizeof(int)); - - nbit = fdmdv_bits_per_frame(f->fdmdv); - f->fdmdv_bits = (int*)malloc(nbit*sizeof(int)); - - if ((f->packed_codec_bits == NULL) || (f->codec_bits == NULL) - || (f->tx_bits == NULL) || (f->rx_bits == NULL) || (f->fdmdv_bits == NULL)) + if ((f->packed_codec_bits == NULL) || (f->codec_bits == NULL)) return NULL; varicode_decode_init(&f->varicode_dec_states, 1); @@ -103,11 +132,8 @@ struct freedv *freedv_open(int mode) { f->freedv_get_next_tx_char = NULL; f->freedv_put_next_rx_char = NULL; - golay23_init(); f->total_bit_errors = 0; - f->nin = FDMDV_NOM_SAMPLES_PER_FRAME; - return f; } @@ -122,10 +148,15 @@ struct freedv *freedv_open(int mode) { \*---------------------------------------------------------------------------*/ void freedv_close(struct freedv *freedv) { + assert(freedv != NULL); + free(freedv->packed_codec_bits); free(freedv->codec_bits); free(freedv->tx_bits); - fdmdv_destroy(freedv->fdmdv); + if (freedv->mode == FREEDV_MODE_1600) + fdmdv_destroy(freedv->fdmdv); + if (freedv->mode == FREEDV_MODE_700) + cohpsk_destroy(freedv->cohpsk); codec2_destroy(freedv->codec2); free(freedv); } @@ -139,66 +170,90 @@ void freedv_close(struct freedv *freedv) { Takes a frame of input speech samples, encodes and modulates them to produce a frame of modem samples that can be sent to the transmitter. - speech_in[] and mod_out[] are sampled at 8 kHz, 16 bit shorts, and - are always FREEDV_NSAMPLES long. The speech_in[] level should be - such that the peak speech level is between +/16384 and +/- 32767. - mod_out[] will be scaled such that the peak level is just less than - +/-32767. + speech_in[] is sampled at 8 kHz, the user must supply + f->n_speech_samples. The speech_in[] level should be such that the + peak speech level is between +/16384 and +/- 32767. - The FDM modem signal mod_out[] has a high crest factor (around - 12dB), however the energy and duration of the peaks is small. - FreeDV is generally operated at a "backoff" of 6-8dB. Adjust the - power amplifier drive so that the average power is 6-8dB less than - the peak power of the PA. For example, on a radio rated at 100W PEP - for SSB, the average FreeDV power is typically 20-25W. + The FDM modem signal mod_out[] is sampled at f->modem_sample_rate + and is f->n_modem_samples long. mod_out[] will be scaled such that + the peak level is just less than +/-32767. + + The FreeDV 1600 modem has a high crest factor (around 12dB), however + the energy and duration of the peaks is small. FreeDV 1600 is + usually operated at a "backoff" of 8dB. Adjust the power + amplifier drive so that the average power is 8dB less than the + peak power of the PA. For example, on a radio rated at 100W PEP for + SSB, the average FreeDV power is typically 20W. + + The FreeDV 900 modem has a crest factor of about 5dB (with f->clip=1, the + default), so if your PA can handle it, it can be driven harder than + FreeDV 1600. Caution - some PAs cannot handle a high continuous + power. A conservative level is 20W average for a 100W PEP rated PA. \*---------------------------------------------------------------------------*/ +/* real-valued short sample output, useful for going straight to DAC */ + void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) { - int bit, byte, i, j; - int bits_per_codec_frame, bits_per_fdmdv_frame; + assert(f != NULL); + COMP tx_fdm[f->n_nom_modem_samples]; + int i; + + freedv_comptx(f, tx_fdm, speech_in); + + for(i=0; in_nom_modem_samples; i++) + mod_out[i] = tx_fdm[i].real; +} + +/* complex valued output, useful for suitable for single sided freq shifting */ + +void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) { + assert(f != NULL); + int bit, byte, i, j, k; + int bits_per_codec_frame, bits_per_modem_frame; int data, codeword1, data_flag_index; - COMP tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME]; + COMP tx_fdm[f->n_nom_modem_samples]; - bits_per_codec_frame = codec2_bits_per_frame(f->codec2); - bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv); + assert((f->mode == FREEDV_MODE_1600) || (f->mode == FREEDV_MODE_700)); + + if (f->mode == FREEDV_MODE_1600) { + bits_per_codec_frame = codec2_bits_per_frame(f->codec2); + bits_per_modem_frame = fdmdv_bits_per_frame(f->fdmdv); - codec2_encode(f->codec2, f->packed_codec_bits, speech_in); + codec2_encode(f->codec2, f->packed_codec_bits, speech_in); - /* unpack bits, MSB first */ + /* unpack bits, MSB first */ - bit = 7; byte = 0; - for(i=0; icodec_bits[i] = (f->packed_codec_bits[byte] >> bit) & 0x1; - bit--; - if (bit < 0) { - bit = 7; - byte++; + bit = 7; byte = 0; + for(i=0; icodec_bits[i] = (f->packed_codec_bits[byte] >> bit) & 0x1; + bit--; + if (bit < 0) { + bit = 7; + byte++; + } } - } - // spare bit in frame that codec defines. Use this 1 - // bit/frame to send txt messages + // spare bit in frame that codec defines. Use this 1 + // bit/frame to send txt messages - data_flag_index = codec2_get_spare_bit_index(f->codec2); + data_flag_index = codec2_get_spare_bit_index(f->codec2); - if (f->nvaricode_bits) { - f->codec_bits[data_flag_index] = f->tx_varicode_bits[f->varicode_bit_index++]; - f->nvaricode_bits--; - } + if (f->nvaricode_bits) { + f->codec_bits[data_flag_index] = f->tx_varicode_bits[f->varicode_bit_index++]; + f->nvaricode_bits--; + } - if (f->nvaricode_bits == 0) { - /* get new char and encode */ - char s[2]; - if (f->freedv_get_next_tx_char != NULL) { - s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); - f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); - f->varicode_bit_index = 0; + if (f->nvaricode_bits == 0) { + /* get new char and encode */ + char s[2]; + if (f->freedv_get_next_tx_char != NULL) { + s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); + f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); + f->varicode_bit_index = 0; + } } - } - if (f->mode == FREEDV_MODE_1600) { - /* Protect first 12 out of first 16 excitation bits with (23,12) Golay Code: 0,1,2,3: v[0]..v[1] @@ -228,23 +283,75 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) { f->tx_bits[i] = (codeword1 >> (10-j)) & 0x1; } f->tx_bits[i] = 0; /* spare bit */ + + /* modulate even and odd frames */ + + fdmdv_mod(f->fdmdv, tx_fdm, f->tx_bits, &f->tx_sync_bit); + assert(f->tx_sync_bit == 1); + + fdmdv_mod(f->fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &f->tx_bits[bits_per_modem_frame], &f->tx_sync_bit); + assert(f->tx_sync_bit == 0); + + assert(2*FDMDV_NOM_SAMPLES_PER_FRAME == f->n_nom_modem_samples); - //for(i=0; itx_bits[i]); + for(i=0; in_nom_modem_samples; i++) + mod_out[i] = fcmult(FDMDV_SCALE, tx_fdm[i]); } - /* modulate even and odd frames */ - fdmdv_mod(f->fdmdv, tx_fdm, f->tx_bits, &f->tx_sync_bit); - assert(f->tx_sync_bit == 1); + if (f->mode == FREEDV_MODE_700) { + bits_per_codec_frame = codec2_bits_per_frame(f->codec2); + bits_per_modem_frame = COHPSK_BITS_PER_FRAME; - fdmdv_mod(f->fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &f->tx_bits[bits_per_fdmdv_frame], &f->tx_sync_bit); - assert(f->tx_sync_bit == 0); + for (j=0; jcodec2, f->packed_codec_bits, speech_in); + speech_in += codec2_samples_per_frame(f->codec2); - for(i=0; i<2*FDMDV_NOM_SAMPLES_PER_FRAME; i++) - mod_out[i] = FDMDV_SCALE * tx_fdm[i].real; + /* unpack bits, MSB first */ + + bit = 7; byte = 0; + for(i=0; icodec_bits[j+i] = (f->packed_codec_bits[byte] >> bit) & 0x1; + bit--; + if (bit < 0) { + bit = 7; + byte++; + } + } + + // spare bits in frame that codec defines. Use these 2 + // bits/frame to send txt messages - assert(2*FDMDV_NOM_SAMPLES_PER_FRAME == FREEDV_NSAMPLES); + data_flag_index = codec2_get_spare_bit_index(f->codec2); + + for(k=0; k<2; k++) { + if (f->nvaricode_bits) { + f->codec_bits[j+data_flag_index+k] = f->tx_varicode_bits[f->varicode_bit_index++]; + //fprintf(stderr, "%d %d\n", j+data_flag_index+k, f->codec_bits[j+data_flag_index+k]); + f->nvaricode_bits--; + } + + if (f->nvaricode_bits == 0) { + /* get new char and encode */ + char s[2]; + if (f->freedv_get_next_tx_char != NULL) { + s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); + f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); + f->varicode_bit_index = 0; + } + } + } + + } + + /* cohpsk modulator */ + + cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits); + if (f->clip) + cohpsk_clip(tx_fdm); + for(i=0; in_nom_modem_samples; i++) + mod_out[i] = fcmult(FDMDV_SCALE, tx_fdm[i]); + } } int freedv_nin(struct freedv *f) { @@ -273,9 +380,12 @@ int freedv_nin(struct freedv *f) { samples. Call freedv_nin() before each call to freedv_rx() to determine how many samples to pass to this function (see example). + The maximum vlaue of freedv_nin is set by f->n_max_modem_samples, + allocate this much storage to your buffers. + Returns the number of output speech samples available in speech_out[]. When in sync this will typically alternate between 0 - and FREEDV_NSAMPLES. When out of sync, this will be f->nin. + and f->n_speech_samples. When out of sync, this will be f->nin. When out of sync, this function echoes the demod_in[] samples to speech_out[]. This allows the user to listen to the channel, which @@ -284,27 +394,34 @@ int freedv_nin(struct freedv *f) { \*---------------------------------------------------------------------------*/ + // short version int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) { - - float rxdata[FDMDV_MAX_SAMPLES_PER_FRAME]; + assert(f != NULL); + COMP rx_fdm[f->n_max_modem_samples]; int i; - for(i=0; inin; i++) - rxdata[i] = (float)demod_in[i]/FDMDV_SCALE; + assert(f->nin <= f->n_max_modem_samples); - return freedv_floatrx(f, speech_out, rxdata); - + for(i=0; inin; i++) { + rx_fdm[i].real = (float)demod_in[i]; + rx_fdm[i].imag = 0.0; + } + + return freedv_comprx(f, speech_out, rx_fdm); } // float input samples version int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) { - COMP rx_fdm[FDMDV_MAX_SAMPLES_PER_FRAME]; + assert(f != NULL); + COMP rx_fdm[f->n_max_modem_samples]; int i; + assert(f->nin <= f->n_max_modem_samples); + for(i=0; inin; i++) { rx_fdm[i].real = demod_in[i]; rx_fdm[i].imag = 0; @@ -316,106 +433,167 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) { // complex input samples version int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) { + assert(f != NULL); int bits_per_codec_frame, bytes_per_codec_frame, bits_per_fdmdv_frame; - int reliable_sync_bit, i, j, bit, byte, nin_prev, nout; + int reliable_sync_bit, i, j, bit, byte, nin_prev, nout, k; int recd_codeword, codeword1, data_flag_index, n_ascii; short abit[1]; char ascii_out; + assert(f->nin <= f->n_max_modem_samples); + + for(i=0; inin; i++) + demod_in[i] = fcmult(1.0/FDMDV_SCALE, demod_in[i]); + bits_per_codec_frame = codec2_bits_per_frame(f->codec2); bytes_per_codec_frame = (bits_per_codec_frame + 7) / 8; - bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv); - nin_prev = f->nin; - fdmdv_demod(f->fdmdv, f->fdmdv_bits, &reliable_sync_bit, demod_in, &f->nin); - fdmdv_get_demod_stats(f->fdmdv, &f->fdmdv_stats); + if (f->mode == FREEDV_MODE_1600) { + bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv); - if (f->fdmdv_stats.sync) { - if (reliable_sync_bit == 0) { - memcpy(f->rx_bits, f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int)); - nout = 0; - } - else { - memcpy(&f->rx_bits[bits_per_fdmdv_frame], f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int)); + nin_prev = f->nin; + fdmdv_demod(f->fdmdv, f->fdmdv_bits, &reliable_sync_bit, demod_in, &f->nin); + fdmdv_get_demod_stats(f->fdmdv, &f->fdmdv_stats); + + if (f->fdmdv_stats.sync) { + if (reliable_sync_bit == 0) { + memcpy(f->rx_bits, f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int)); + nout = 0; + } + else { + memcpy(&f->rx_bits[bits_per_fdmdv_frame], f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int)); - if (f->mode == FREEDV_MODE_1600) { - recd_codeword = 0; - for(i=0; i<8; i++) { - recd_codeword <<= 1; - recd_codeword |= (f->rx_bits[i] & 0x1); - } - for(i=11; i<15; i++) { - recd_codeword <<= 1; - recd_codeword |= (f->rx_bits[i] & 0x1); - } - for(i=bits_per_codec_frame; irx_bits[i] & 0x1); - } - codeword1 = golay23_decode(recd_codeword); - f->total_bit_errors += golay23_count_errors(recd_codeword, codeword1); + if (f->mode == FREEDV_MODE_1600) { + recd_codeword = 0; + for(i=0; i<8; i++) { + recd_codeword <<= 1; + recd_codeword |= (f->rx_bits[i] & 0x1); + } + for(i=11; i<15; i++) { + recd_codeword <<= 1; + recd_codeword |= (f->rx_bits[i] & 0x1); + } + for(i=bits_per_codec_frame; irx_bits[i] & 0x1); + } + codeword1 = golay23_decode(recd_codeword); + f->total_bit_errors += golay23_count_errors(recd_codeword, codeword1); - //codeword1 = recd_codeword; - //fprintf(stderr, "received codeword1: 0x%x decoded codeword1: 0x%x\n", recd_codeword, codeword1); + //codeword1 = recd_codeword; + //fprintf(stderr, "received codeword1: 0x%x decoded codeword1: 0x%x\n", recd_codeword, codeword1); - for(i=0; icodec_bits[i] = f->rx_bits[i]; + for(i=0; icodec_bits[i] = f->rx_bits[i]; - for(i=0; i<8; i++) { - f->codec_bits[i] = (codeword1 >> (22-i)) & 0x1; + for(i=0; i<8; i++) { + f->codec_bits[i] = (codeword1 >> (22-i)) & 0x1; + } + for(i=8,j=11; i<12; i++,j++) { + f->codec_bits[j] = (codeword1 >> (22-i)) & 0x1; + } } - for(i=8,j=11; i<12; i++,j++) { - f->codec_bits[j] = (codeword1 >> (22-i)) & 0x1; + + // extract txt msg data bit ------------------------------------------------------------ + + data_flag_index = codec2_get_spare_bit_index(f->codec2); + abit[0] = f->codec_bits[data_flag_index]; + + n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, abit, 1, 1); + if (n_ascii && (f->freedv_put_next_rx_char != NULL)) { + (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out); } - } - // extract txt msg data bit ------------------------------------------------------------ + // reconstruct missing bit we steal for data bit and decode speech - data_flag_index = codec2_get_spare_bit_index(f->codec2); - abit[0] = f->codec_bits[data_flag_index]; + codec2_rebuild_spare_bit(f->codec2, f->codec_bits); - n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, abit, 1, 1); - if (n_ascii && (f->freedv_put_next_rx_char != NULL)) { - (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out); - } + // pack bits, MSB received first - // reconstruct missing bit we steal for data bit and decode speech + bit = 7; + byte = 0; + memset(f->packed_codec_bits, 0, bytes_per_codec_frame); + for(i=0; ipacked_codec_bits[byte] |= (f->codec_bits[i] << bit); + bit--; + if(bit < 0) { + bit = 7; + byte++; + } + } - codec2_rebuild_spare_bit(f->codec2, f->codec_bits); + codec2_decode(f->codec2, speech_out, f->packed_codec_bits); - // pack bits, MSB received first + /* squelch if beneath SNR threshold */ - bit = 7; - byte = 0; - memset(f->packed_codec_bits, 0, bytes_per_codec_frame); - for(i=0; ipacked_codec_bits[byte] |= (f->codec_bits[i] << bit); - bit--; - if(bit < 0) { - bit = 7; - byte++; + if (f->fdmdv_stats.snr_est < f->snr_thresh) { + for(i=0; in_speech_samples; i++) + speech_out[i] = 0; } + + nout = f->n_speech_samples; } + } /* if (sync) .... */ + else { + /* if not in sync pass through analog samples */ + /* this lets us "hear" whats going on, e.g. during tuning */ + for(i=0; icodec2, speech_out, f->packed_codec_bits); - /* squelch if beneath SNR threshold */ + if (f->mode == FREEDV_MODE_700) { + float rx_bits[COHPSK_BITS_PER_FRAME]; + int reliable_sync_bit; - if (f->fdmdv_stats.snr_est < f->snr_thresh) { - for(i=0; inin; + cohpsk_demod(f->cohpsk, rx_bits, &reliable_sync_bit, demod_in, &f->nin); + + if (reliable_sync_bit) { - nout = FREEDV_NSAMPLES; + data_flag_index = codec2_get_spare_bit_index(f->codec2); + + for (j=0; jvaricode_dec_states, &ascii_out, abit, 1, 1); + if (n_ascii && (f->freedv_put_next_rx_char != NULL)) { + (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out); + } + } + + /* pack bits, MSB received first */ + + bit = 7; byte = 0; + memset(f->packed_codec_bits, 0, bytes_per_codec_frame); + for(i=0; ipacked_codec_bits[byte] |= ((rx_bits[j+i] < 0.0) << bit); + bit--; + if (bit < 0) { + bit = 7; + byte++; + } + } + + codec2_decode(f->codec2, speech_out, f->packed_codec_bits); + speech_out += codec2_samples_per_frame(f->codec2); + } + nout = f->n_speech_samples; } - } /* if (sync) .... */ - else { - /* if not in sync pass through analog samples */ - /* this lets us "hear" whats going on, e.g. during tuning */ - for(i=0; iftxt != NULL) { - fprintf(pstate->ftxt, "text char received callback: %c\n", c); + fprintf(stderr, "%c", c); } } int main(int argc, char *argv[]) { FILE *fin, *fout, *ftxt; - short speech_out[FREEDV_NSAMPLES]; - short demod_in[FREEDV_NSAMPLES]; + short *speech_out; + short *demod_in; struct freedv *freedv; int nin, nout, frame; struct my_callback_state my_cb_state; + int mode; - if (argc < 3) { - printf("usage: %s InputModemSpeechFile OutputSpeechawFile txtLogFile\n", argv[0]); - printf("e.g %s hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]); + if (argc < 4) { + printf("usage: %s 1600|700 InputModemSpeechFile OutputSpeechawFile txtLogFile\n", argv[0]); + printf("e.g %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]); exit(1); } - if (strcmp(argv[1], "-") == 0) fin = stdin; - else if ( (fin = fopen(argv[1],"rb")) == NULL ) { + mode = -1; + if (!strcmp(argv[1],"1600")) + mode = FREEDV_MODE_1600; + if (!strcmp(argv[1],"700")) + mode = FREEDV_MODE_700; + assert(mode != -1); + + if (strcmp(argv[2], "-") == 0) fin = stdin; + else if ( (fin = fopen(argv[2],"rb")) == NULL ) { fprintf(stderr, "Error opening input raw modem sample file: %s: %s.\n", - argv[1], strerror(errno)); + argv[2], strerror(errno)); exit(1); } - if (strcmp(argv[2], "-") == 0) fout = stdout; - else if ( (fout = fopen(argv[2],"wb")) == NULL ) { + if (strcmp(argv[3], "-") == 0) fout = stdout; + else if ( (fout = fopen(argv[3],"wb")) == NULL ) { fprintf(stderr, "Error opening output speech sample file: %s: %s.\n", - argv[2], strerror(errno)); + argv[3], strerror(errno)); exit(1); } ftxt = NULL; - if ( (argc > 3) && (strcmp(argv[3],"|") != 0) ) { - if ((ftxt = fopen(argv[3],"wt")) == NULL ) { + if ( (argc > 4) && (strcmp(argv[4],"|") != 0) ) { + if ((ftxt = fopen(argv[4],"wt")) == NULL ) { fprintf(stderr, "Error opening txt Log File: %s: %s.\n", - argv[3], strerror(errno)); + argv[4], strerror(errno)); exit(1); } } - freedv = freedv_open(FREEDV_MODE_1600); + freedv = freedv_open(mode); assert(freedv != NULL); + speech_out = (short*)malloc(sizeof(short)*freedv->n_speech_samples); + assert(speech_out != NULL); + demod_in = (short*)malloc(sizeof(short)*freedv->n_max_modem_samples); + assert(demod_in != NULL); + my_cb_state.ftxt = ftxt; freedv->callback_state = (void*)&my_cb_state; freedv->freedv_put_next_rx_char = &my_put_next_rx_char; @@ -118,6 +131,8 @@ int main(int argc, char *argv[]) { if (fin == stdin) fflush(stdin); } + free(speech_out); + free(demod_in); freedv_close(freedv); fclose(fin); fclose(fout); diff --git a/codec2-dev/src/freedv_tx.c b/codec2-dev/src/freedv_tx.c index ac0cdca8..c13303c7 100644 --- a/codec2-dev/src/freedv_tx.c +++ b/codec2-dev/src/freedv_tx.c @@ -51,34 +51,47 @@ char my_get_next_tx_char(void *callback_state) { int main(int argc, char *argv[]) { FILE *fin, *fout; - short speech_in[FREEDV_NSAMPLES]; - short mod_out[FREEDV_NSAMPLES]; + short *speech_in; + short *mod_out; struct freedv *freedv; struct my_callback_state my_cb_state; + int mode; - if (argc < 3) { - printf("usage: %s InputRawSpeechFile OutputModemRawFile\n", argv[0]); - printf("e.g %s hts1a.raw hts1a_fdmdv.raw\n", argv[0]); + if (argc < 4) { + printf("usage: %s 1600|700 InputRawSpeechFile OutputModemRawFile\n", argv[0]); + printf("e.g %s 1600 hts1a.raw hts1a_fdmdv.raw\n", argv[0]); exit(1); } - if (strcmp(argv[1], "-") == 0) fin = stdin; - else if ( (fin = fopen(argv[1],"rb")) == NULL ) { + mode = -1; + if (!strcmp(argv[1],"1600")) + mode = FREEDV_MODE_1600; + if (!strcmp(argv[1],"700")) + mode = FREEDV_MODE_700; + assert(mode != -1); + + if (strcmp(argv[2], "-") == 0) fin = stdin; + else if ( (fin = fopen(argv[2],"rb")) == NULL ) { fprintf(stderr, "Error opening input raw speech sample file: %s: %s.\n", - argv[1], strerror(errno)); + argv[2], strerror(errno)); exit(1); } - if (strcmp(argv[2], "-") == 0) fout = stdout; - else if ( (fout = fopen(argv[2],"wb")) == NULL ) { + if (strcmp(argv[3], "-") == 0) fout = stdout; + else if ( (fout = fopen(argv[3],"wb")) == NULL ) { fprintf(stderr, "Error opening output modem sample file: %s: %s.\n", - argv[2], strerror(errno)); + argv[3], strerror(errno)); exit(1); } - freedv = freedv_open(FREEDV_MODE_1600); + freedv = freedv_open(mode); assert(freedv != NULL); + speech_in = (short*)malloc(sizeof(short)*freedv->n_speech_samples); + assert(speech_in != NULL); + mod_out = (short*)malloc(sizeof(short)*freedv->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"); @@ -88,9 +101,9 @@ int main(int argc, char *argv[]) { /* OK main loop */ - while(fread(speech_in, sizeof(short), FREEDV_NSAMPLES, fin) == FREEDV_NSAMPLES) { + while(fread(speech_in, sizeof(short), freedv->n_speech_samples, fin) == freedv->n_speech_samples) { freedv_tx(freedv, mod_out, speech_in); - fwrite(mod_out, sizeof(short), FREEDV_NSAMPLES, fout); + fwrite(mod_out, sizeof(short), freedv->n_nom_modem_samples, fout); /* if this is in a pipeline, we probably don't want the usual buffering to occur */ @@ -99,6 +112,8 @@ int main(int argc, char *argv[]) { if (fin == stdin) fflush(stdin); } + free(speech_in); + free(mod_out); freedv_close(freedv); fclose(fin); fclose(fout); -- 2.25.1