3 * Copyright 2009 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
27 #include <gr_histo_sink_f.h>
28 #include <gr_io_signature.h>
30 static float get_clean_num(float num){
31 if (num == 0) return 0;
32 /* extract sign and exponent from num */
33 int sign = (num < 0) ? -1 : 1; num = fabs(num);
34 float exponent = floor(log10(num));
35 /* search for closest number with base 1, 2, 5, 10 */
36 float closest_num = 10*pow(10, exponent);
37 if (fabs(num - 1*pow(10, exponent)) < fabs(num - closest_num))
38 closest_num = 1*pow(10, exponent);
39 if (fabs(num - 2*pow(10, exponent)) < fabs(num - closest_num))
40 closest_num = 2*pow(10, exponent);
41 if (fabs(num - 5*pow(10, exponent)) < fabs(num - closest_num))
42 closest_num = 5*pow(10, exponent);
43 return sign*closest_num;
47 gr_make_histo_sink_f (gr_msg_queue_sptr msgq)
49 return gr_histo_sink_f_sptr (new gr_histo_sink_f (msgq));
52 gr_histo_sink_f::gr_histo_sink_f (gr_msg_queue_sptr msgq)
53 : gr_sync_block ("histo_sink_f", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (0, 0, 0)),
54 d_msgq (msgq), d_num_bins(11), d_frame_size(1000), d_sample_count(0), d_bins(NULL), d_samps(NULL)
56 pthread_mutex_init(&d_mutex, 0);
57 //allocate arrays and clear
58 set_num_bins(d_num_bins);
59 set_frame_size(d_frame_size);
62 gr_histo_sink_f::~gr_histo_sink_f (void)
64 pthread_mutex_destroy(&d_mutex);
70 gr_histo_sink_f::work (int noutput_items,
71 gr_vector_const_void_star &input_items,
72 gr_vector_void_star &output_items)
74 const float *in = (const float *) input_items[0];
75 pthread_mutex_lock(&d_mutex);
76 for (unsigned int i = 0; i < (unsigned int)noutput_items; i++){
77 d_samps[d_sample_count] = in[i];
79 /* processed a frame? */
80 if (d_sample_count == d_frame_size){
85 pthread_mutex_unlock(&d_mutex);
90 gr_histo_sink_f::send_frame(void){
91 /* output queue full, drop the data */
92 if (d_msgq->full_p()) return;
93 /* find the minimum and maximum */
94 float minimum = d_samps[0];
95 float maximum = d_samps[0];
96 for (unsigned int i = 0; i < d_frame_size; i++){
97 if (d_samps[i] < minimum) minimum = d_samps[i];
98 if (d_samps[i] > maximum) maximum = d_samps[i];
100 minimum = get_clean_num(minimum);
101 maximum = get_clean_num(maximum);
102 if (minimum == maximum || minimum > maximum) return; //useless data or screw up?
105 float bin_width = (maximum - minimum)/(d_num_bins-1);
106 for (unsigned int i = 0; i < d_sample_count; i++){
107 index = round((d_samps[i] - minimum)/bin_width);
108 /* ensure the index range in case a small floating point error is involed */
109 if (index < 0) index = 0;
110 if (index >= (int)d_num_bins) index = d_num_bins-1;
113 /* Build a message to hold the output records */
114 gr_message_sptr msg = gr_make_message(0, minimum, maximum, d_num_bins*sizeof(float));
115 float *out = (float *)msg->msg(); // get pointer to raw message buffer
116 /* normalize the bins and put into message */
117 for (unsigned int i = 0; i < d_num_bins; i++){
118 out[i] = ((float)d_bins[i])/d_frame_size;
120 /* send the message */
125 gr_histo_sink_f::clear(void){
128 for (unsigned int i = 0; i < d_num_bins; i++){
133 /**************************************************
135 **************************************************/
137 gr_histo_sink_f::get_frame_size(void){
142 gr_histo_sink_f::get_num_bins(void){
146 /**************************************************
148 **************************************************/
150 gr_histo_sink_f::set_frame_size(unsigned int frame_size){
151 pthread_mutex_lock(&d_mutex);
152 d_frame_size = frame_size;
153 /* allocate a new sample array */
155 d_samps = new float[d_frame_size];
157 pthread_mutex_unlock(&d_mutex);
161 gr_histo_sink_f::set_num_bins(unsigned int num_bins){
162 pthread_mutex_lock(&d_mutex);
163 d_num_bins = num_bins;
164 /* allocate a new bin array */
166 d_bins = new unsigned int[d_num_bins];
168 pthread_mutex_unlock(&d_mutex);