/* -*- 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] = 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 i,n; d_nin = freedv_nin(d_freedv); if (ninput_items[0] < d_nin) { consume_each(0); return(0); } for (i=0,n=0; ((n+d_nin) <= noutput_items)&&(i <= ninput_items[0]);) { d_nout = freedv_rx(d_freedv, out, in); i += d_nin; n += d_nout; out = &(out[d_nout]); in = &(in[d_nin]); d_nin = freedv_nin(d_freedv); } if ((i > ninput_items[0])||((n+d_nin) > noutput_items)) { i -= d_nin; n -= d_nout; } // back up to where we left off processing freedv_rx 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(i); return(n); } 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 */