summaryrefslogtreecommitdiff
path: root/gr-vocoder/lib/freedv_rx_ss_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-vocoder/lib/freedv_rx_ss_impl.cc')
-rw-r--r--gr-vocoder/lib/freedv_rx_ss_impl.cc146
1 files changed, 146 insertions, 0 deletions
diff --git a/gr-vocoder/lib/freedv_rx_ss_impl.cc b/gr-vocoder/lib/freedv_rx_ss_impl.cc
new file mode 100644
index 0000000000..748a5c10aa
--- /dev/null
+++ b/gr-vocoder/lib/freedv_rx_ss_impl.cc
@@ -0,0 +1,146 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "freedv_rx_ss_impl.h"
+
+#include <gnuradio/io_signature.h>
+#include <stdexcept>
+#include <assert.h>
+
+extern "C" {
+ void put_next_rx_char(void *callback_state, char c) {
+ struct freedv_rx_callback_state* pstate;
+
+ pstate = (struct freedv_rx_callback_state*) callback_state;
+ if (pstate->ftxt != NULL) {
+ //fprintf(pstate->ftxt, "%c\n", c);
+ }
+ return;
+ }
+}
+
+
+namespace gr {
+ namespace vocoder {
+
+ freedv_rx_ss::sptr
+ freedv_rx_ss::make(int mode, float squelch_thresh)
+ {
+ return gnuradio::get_initial_sptr
+ (new freedv_rx_ss_impl(mode, squelch_thresh));
+ }
+
+ freedv_rx_ss_impl::freedv_rx_ss_impl (int mode, float squelch_thresh)
+ : gr::block("vocoder_freedv_rx_ss",
+ io_signature::make(1, 1, sizeof(short)),
+ io_signature::make(1, 1, sizeof(short))),
+ d_mode(mode), d_squelch_thresh(squelch_thresh)
+ {
+ if((d_freedv = freedv_open(mode)) == NULL)
+ throw std::runtime_error("freedv_rx_ss_impl: freedv_open failed");
+ freedv_set_snr_squelch_thresh(d_freedv, d_squelch_thresh);
+ freedv_set_squelch_en(d_freedv, 0);
+ freedv_set_callback_txt(d_freedv, put_next_rx_char, NULL, (void *) &d_cb_state);
+ d_speech_samples = freedv_get_n_speech_samples(d_freedv);
+ d_max_modem_samples = freedv_get_n_max_modem_samples(d_freedv);
+ d_nin = freedv_nin(d_freedv);
+ set_output_multiple(d_max_modem_samples);
+ }
+
+ freedv_rx_ss_impl::~freedv_rx_ss_impl()
+ {
+ int total_bits;
+ int total_bit_errors;
+
+ if (freedv_get_test_frames(d_freedv)) {
+ total_bits = freedv_get_total_bits(d_freedv);
+ total_bit_errors = freedv_get_total_bit_errors(d_freedv);
+ fprintf(stderr, "bits: %d errors: %d BER: %3.2f\n", total_bits, total_bit_errors, (1.0*total_bit_errors)/total_bits);
+ }
+ freedv_close(d_freedv);
+ }
+
+ void
+ freedv_rx_ss_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = std::max(d_nin, noutput_items);
+ }
+
+ int
+ freedv_rx_ss_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ short *in = (short *) input_items[0];
+ short *out = (short *) output_items[0];
+
+ int in_offset = 0, out_offset = 0;
+
+ while ((noutput_items - out_offset) >= d_max_modem_samples
+ && (ninput_items[0] - in_offset) >= d_nin) {
+ d_nout = freedv_rx(d_freedv, out + out_offset, in + in_offset);
+ out_offset += d_nout;
+ in_offset += d_nin;
+ d_nin = freedv_nin(d_freedv);
+ }
+
+ freedv_get_modem_stats(d_freedv, &d_sync, &d_snr_est);
+ freedv_get_modem_extended_stats(d_freedv, &d_stats);
+ d_total_bit_errors = freedv_get_total_bit_errors(d_freedv);
+
+ consume_each(in_offset);
+ return out_offset;
+ }
+
+ void put_next_rx_proto(void *callback_state,char *proto_bits) {
+ return;
+ }
+
+ void datarx(void *callback_state, unsigned char *packet, size_t size) {
+ return;
+ }
+
+ void datatx(void *callback_state, unsigned char *packet, size_t *size) {
+ return;
+ }
+
+ void freedv_rx_ss_impl::set_squelch_thresh(float squelch_thresh)
+ {
+ gr::thread::scoped_lock l(d_setlock);
+ d_squelch_thresh = squelch_thresh;
+ freedv_set_snr_squelch_thresh(d_freedv, d_squelch_thresh);
+ }
+
+ float freedv_rx_ss_impl::squelch_thresh() {
+ return(d_squelch_thresh);
+ }
+
+ } /* namespace vocoder */
+} /* namespace gr */