summaryrefslogtreecommitdiff
path: root/gr-wxgui/lib/histo_sink_f_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-wxgui/lib/histo_sink_f_impl.cc')
-rw-r--r--gr-wxgui/lib/histo_sink_f_impl.cc186
1 files changed, 186 insertions, 0 deletions
diff --git a/gr-wxgui/lib/histo_sink_f_impl.cc b/gr-wxgui/lib/histo_sink_f_impl.cc
new file mode 100644
index 0000000000..9b168de547
--- /dev/null
+++ b/gr-wxgui/lib/histo_sink_f_impl.cc
@@ -0,0 +1,186 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2011,2013 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 "histo_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <boost/math/special_functions/round.hpp>
+
+namespace gr {
+ namespace wxgui {
+
+ static float get_clean_num(float num)
+ {
+ if(num == 0)
+ return 0;
+ /* extract sign and exponent from num */
+ int sign = (num < 0) ? -1 : 1; num = fabs(num);
+ float exponent = floor(log10(num));
+ /* search for closest number with base 1, 2, 5, 10 */
+ float closest_num = 10*pow(10, exponent);
+ if(fabs(num - 1*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 1*pow(10, exponent);
+ if(fabs(num - 2*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 2*pow(10, exponent);
+ if(fabs(num - 5*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 5*pow(10, exponent);
+ return sign*closest_num;
+ }
+
+ histo_sink_f::sptr
+ histo_sink_f::make(gr_msg_queue_sptr msgq)
+ {
+ return gnuradio::get_initial_sptr
+ (new histo_sink_f_impl(msgq));
+ }
+
+ histo_sink_f_impl::histo_sink_f_impl(gr_msg_queue_sptr msgq)
+ : gr_sync_block("histo_sink_f",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_msgq(msgq), d_num_bins(11), d_frame_size(1000),
+ d_sample_count(0), d_bins(NULL), d_samps(NULL)
+ {
+ //allocate arrays and clear
+ set_num_bins(d_num_bins);
+ set_frame_size(d_frame_size);
+ }
+
+ histo_sink_f_impl::~histo_sink_f_impl(void)
+ {
+ delete [] d_samps;
+ delete [] d_bins;
+ }
+
+ int
+ histo_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ for(unsigned int i = 0; i < (unsigned int)noutput_items; i++) {
+ d_samps[d_sample_count] = in[i];
+ d_sample_count++;
+ /* processed a frame? */
+ if(d_sample_count == d_frame_size) {
+ send_frame();
+ clear();
+ }
+ }
+ return noutput_items;
+ }
+
+ void
+ histo_sink_f_impl::send_frame(void)
+ {
+ /* output queue full, drop the data */
+ if(d_msgq->full_p())
+ return;
+ /* find the minimum and maximum */
+ float minimum = d_samps[0];
+ float maximum = d_samps[0];
+ for(unsigned int i = 0; i < d_frame_size; i++) {
+ if(d_samps[i] < minimum) minimum = d_samps[i];
+ if(d_samps[i] > maximum) maximum = d_samps[i];
+ }
+ minimum = get_clean_num(minimum);
+ maximum = get_clean_num(maximum);
+ if(minimum == maximum || minimum > maximum)
+ return; //useless data or screw up?
+ /* load the bins */
+ int index;
+ float bin_width = (maximum - minimum)/(d_num_bins-1);
+ for(unsigned int i = 0; i < d_sample_count; i++) {
+ index = boost::math::iround((d_samps[i] - minimum)/bin_width);
+ /* ensure the index range in case a small floating point error is involed */
+ if(index < 0)
+ index = 0;
+ if(index >= (int)d_num_bins)
+ index = d_num_bins-1;
+ d_bins[index]++;
+ }
+ /* Build a message to hold the output records */
+ gr_message_sptr msg = gr_make_message(0, minimum, maximum, d_num_bins*sizeof(float));
+ float *out = (float *)msg->msg(); // get pointer to raw message buffer
+ /* normalize the bins and put into message */
+ for(unsigned int i = 0; i < d_num_bins; i++) {
+ out[i] = ((float)d_bins[i])/d_frame_size;
+ }
+ /* send the message */
+ d_msgq->handle(msg);
+ }
+
+ void
+ histo_sink_f_impl::clear(void)
+ {
+ d_sample_count = 0;
+ /* zero the bins */
+ for(unsigned int i = 0; i < d_num_bins; i++) {
+ d_bins[i] = 0;
+ }
+ }
+
+ /**************************************************
+ * Getters
+ **************************************************/
+ unsigned int
+ histo_sink_f_impl::get_frame_size(void)
+ {
+ return d_frame_size;
+ }
+
+ unsigned int
+ histo_sink_f_impl::get_num_bins(void)
+ {
+ return d_num_bins;
+ }
+
+ /**************************************************
+ * Setters
+ **************************************************/
+ void
+ histo_sink_f_impl::set_frame_size(unsigned int frame_size)
+ {
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ d_frame_size = frame_size;
+ /* allocate a new sample array */
+ delete [] d_samps;
+ d_samps = new float[d_frame_size];
+ clear();
+ }
+
+ void
+ histo_sink_f_impl::set_num_bins(unsigned int num_bins) {
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ d_num_bins = num_bins;
+ /* allocate a new bin array */
+ delete [] d_bins;
+ d_bins = new unsigned int[d_num_bins];
+ clear();
+ }
+
+ } /* namespace wxgui */
+} /* namespace gr */