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