int main(int argc, char *argv[]) { FILE *fin, *fout; short speech_in[FREEDV_NSAMPLES]; short mod_out[FREEDV_NSAMPLES]; struct freedv *freedv; struct my_callback_state my_cb_state; if (argc < 3) { printf("usage: %s InputRawSpeechFile OutputModemRawFile\n", argv[0]); printf("e.g %s 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 ) { fprintf(stderr, "Error opening input raw speech sample file: %s: %s.\n", argv[1], strerror(errno)); exit(1); } if (strcmp(argv[2], "-") == 0) fout = stdout; else if ( (fout = fopen(argv[2],"wb")) == NULL ) { fprintf(stderr, "Error opening output modem sample file: %s: %s.\n", argv[2], strerror(errno)); exit(1); } freedv = freedv_open(FREEDV_MODE_1600); assert(freedv != NULL); /* set up callback for txt msg chars */ sprintf(my_cb_state.tx_str, "cq cq cq hello world\n"); my_cb_state.ptx_str = my_cb_state.tx_str; freedv->callback_state = (void*)&my_cb_state; freedv->freedv_get_next_tx_char = &my_get_next_tx_char; /* OK main loop */ while(fread(speech_in, sizeof(short), FREEDV_NSAMPLES, fin) == FREEDV_NSAMPLES) { freedv_tx(freedv, mod_out, speech_in); fwrite(mod_out, sizeof(short), FREEDV_NSAMPLES, fout); /* if this is in a pipeline, we probably don't want the usual buffering to occur */ if (fout == stdout) fflush(stdout); if (fin == stdin) fflush(stdin); } freedv_close(freedv); fclose(fin); fclose(fout); return 0; }
int main(int argc, char *argv[]) { FILE *fin, *fout, *ftxt; short *speech_out; short *demod_in; struct freedv *freedv; int nin, nout, frame = 0; struct my_callback_state my_cb_state; struct MODEM_STATS stats; int mode; int sync; int total_bits; int total_bit_errors; float snr_est; 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] [--codecrx]\n", argv[0]); printf("e.g %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]); exit(1); } mode = -1; if (!strcmp(argv[1],"1600")) mode = FREEDV_MODE_1600; if (!strcmp(argv[1],"700")) mode = FREEDV_MODE_700; if (!strcmp(argv[1],"700B")) mode = FREEDV_MODE_700B; if (!strcmp(argv[1],"2400A")) mode = FREEDV_MODE_2400A; if (!strcmp(argv[1],"2400B")) mode = FREEDV_MODE_2400B; if (!strcmp(argv[1],"800XA")) mode = FREEDV_MODE_800XA; 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[2], strerror(errno)); exit(1); } 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[3], strerror(errno)); exit(1); } freedv = freedv_open(mode); assert(freedv != NULL); 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); n_speech_samples = freedv_get_n_speech_samples(freedv); n_max_modem_samples = freedv_get_n_max_modem_samples(freedv); speech_out = (short*)malloc(sizeof(short)*n_speech_samples); assert(speech_out != NULL); demod_in = (short*)malloc(sizeof(short)*n_max_modem_samples); assert(demod_in != NULL); ftxt = fopen("freedv_rx_log.txt","wt"); assert(ftxt != NULL); 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 sample clock frequencies. Note also the number of output speech samples is time varying (nout). */ nin = freedv_nin(freedv); while(fread(demod_in, sizeof(short), nin, fin) == nin) { frame++; 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); freedv_get_modem_stats(freedv, &sync, &snr_est); freedv_get_modem_extended_stats(freedv,&stats); total_bit_errors = freedv_get_total_bit_errors(freedv); clock_offset = stats.clock_offset; /* log some side info to the txt file */ if (ftxt != NULL) { fprintf(ftxt, "frame: %d demod sync: %d nin:%d demod snr: %3.2f dB bit errors: %d clock_offset: %f\n", frame, sync, nin, snr_est, total_bit_errors, clock_offset); } /* if this is in a pipeline, we probably don't want the usual buffering to occur */ if (fout == stdout) fflush(stdout); if (fin == stdin) fflush(stdin); } if (freedv_get_test_frames(freedv)) { total_bits = freedv_get_total_bits(freedv); total_bit_errors = freedv_get_total_bit_errors(freedv); fprintf(stderr, "bits: %d errors: %d BER: %3.2f\n", total_bits, total_bit_errors, (float)total_bit_errors/total_bits); } free(speech_out); free(demod_in); freedv_close(freedv); fclose(fin); fclose(fout); return 0; }