PFB resampler: fix it this way to avoid the signed/unsigned warning.
[debian/gnuradio] / gnuradio-core / src / lib / filter / gr_pfb_arb_resampler_ccf.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2009,2010 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
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)
10  * any later version.
11  * 
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.
16  * 
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.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gr_pfb_arb_resampler_ccf.h>
28 #include <gr_fir_ccf.h>
29 #include <gr_fir_util.h>
30 #include <gr_io_signature.h>
31 #include <cstdio>
32
33 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, 
34                                                              const std::vector<float> &taps,
35                                                              unsigned int filter_size)
36 {
37   return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_ccf (rate, taps,
38                                                                       filter_size));
39 }
40
41
42 gr_pfb_arb_resampler_ccf::gr_pfb_arb_resampler_ccf (float rate, 
43                                                     const std::vector<float> &taps,
44                                                     unsigned int filter_size)
45   : gr_block ("pfb_arb_resampler_ccf",
46               gr_make_io_signature (1, 1, sizeof(gr_complex)),
47               gr_make_io_signature (1, 1, sizeof(gr_complex))),
48     d_updated (false)
49 {
50   d_acc = 0; // start accumulator at 0
51
52   /* The number of filters is specified by the user as the filter size;
53      this is also the interpolation rate of the filter. We use it and the
54      rate provided to determine the decimation rate. This acts as a
55      rational resampler. The flt_rate is calculated as the residual
56      between the integer decimation rate and the real decimation rate and
57      will be used to determine to interpolation point of the resampling
58      process.
59   */
60   d_int_rate = filter_size;
61   d_dec_rate = (unsigned int)floor(d_int_rate/rate);
62   d_flt_rate = (d_int_rate/rate) - d_dec_rate;
63
64   // Store the last filter between calls to work
65   d_last_filter = 0;
66
67   d_start_index = 0;
68   
69   d_filters = std::vector<gr_fir_ccf*>(d_int_rate);
70   d_diff_filters = std::vector<gr_fir_ccf*>(d_int_rate);
71
72   // Create an FIR filter for each channel and zero out the taps
73   std::vector<float> vtaps(0, d_int_rate);
74   for(int i = 0; i < d_int_rate; i++) {
75     d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
76     d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
77   }
78
79   // Now, actually set the filters' taps
80   std::vector<float> dtaps;
81   create_diff_taps(taps, dtaps);
82   create_taps(taps, d_taps, d_filters);
83   create_taps(dtaps, d_dtaps, d_diff_filters);
84 }
85
86 gr_pfb_arb_resampler_ccf::~gr_pfb_arb_resampler_ccf ()
87 {
88   for(unsigned int i = 0; i < d_int_rate; i++) {
89     delete d_filters[i];
90   }
91 }
92
93 void
94 gr_pfb_arb_resampler_ccf::create_taps (const std::vector<float> &newtaps,
95                                        std::vector< std::vector<float> > &ourtaps,
96                                        std::vector<gr_fir_ccf*> &ourfilter)
97 {
98   int i,j;
99
100   unsigned int ntaps = newtaps.size();
101   d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
102
103   // Create d_numchan vectors to store each channel's taps
104   ourtaps.resize(d_int_rate);
105   
106   // Make a vector of the taps plus fill it out with 0's to fill
107   // each polyphase filter with exactly d_taps_per_filter
108   std::vector<float> tmp_taps;
109   tmp_taps = newtaps;
110   while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
111     tmp_taps.push_back(0.0);
112   }
113   
114   // Partition the filter
115   for(i = 0; i < d_int_rate; i++) {
116     // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
117     ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
118     for(j = 0; j < d_taps_per_filter; j++) {
119       ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
120     }
121     
122     // Build a filter for each channel and add it's taps to it
123     ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
124   }
125
126   // Set the history to ensure enough input items for each filter
127   set_history (d_taps_per_filter + 1);
128
129   d_updated = true;
130 }
131
132 void
133 gr_pfb_arb_resampler_ccf::create_diff_taps(const std::vector<float> &newtaps,
134                                            std::vector<float> &difftaps)
135 {
136   // Calculate the differential taps (derivative filter) by taking the difference
137   // between two taps. Duplicate the last one to make both filters the same length.
138   float tap;
139   difftaps.clear();
140   for(unsigned int i = 0; i < newtaps.size()-1; i++) {
141     tap = newtaps[i+1] - newtaps[i];
142     difftaps.push_back(tap);
143   }
144   difftaps.push_back(tap);
145 }
146
147 void
148 gr_pfb_arb_resampler_ccf::print_taps()
149 {
150   unsigned int i, j;
151   for(i = 0; i < d_int_rate; i++) {
152     printf("filter[%d]: [", i);
153     for(j = 0; j < d_taps_per_filter; j++) {
154       printf(" %.4e", d_taps[i][j]);
155     }
156     printf("]\n");
157   }
158 }
159
160 int
161 gr_pfb_arb_resampler_ccf::general_work (int noutput_items,
162                                         gr_vector_int &ninput_items,
163                                         gr_vector_const_void_star &input_items,
164                                         gr_vector_void_star &output_items)
165 {
166   gr_complex *in = (gr_complex *) input_items[0];
167   gr_complex *out = (gr_complex *) output_items[0];
168
169   if (d_updated) {
170     d_updated = false;
171     return 0;                // history requirements may have changed.
172   }
173
174   int i = 0, j, count = d_start_index;
175   gr_complex o0, o1;
176
177   // Restore the last filter position
178   j = d_last_filter;
179
180   // produce output as long as we can and there are enough input samples
181   int max_input = ninput_items[0]-(int)d_taps_per_filter;
182   while((i < noutput_items) && (count < max_input)) {
183
184     // start j by wrapping around mod the number of channels
185     while((j < d_int_rate) && (i < noutput_items)) {
186       // Take the current filter and derivative filter output
187       o0 = d_filters[j]->filter(&in[count]);
188       o1 = d_diff_filters[j]->filter(&in[count]);
189
190       out[i] = o0 + o1*d_acc;     // linearly interpolate between samples
191       i++;
192
193       // Adjust accumulator and index into filterbank
194       d_acc += d_flt_rate;
195       j += d_dec_rate + (int)floor(d_acc);
196       d_acc = fmodf(d_acc, 1.0);
197     }
198     if(i < noutput_items) {              // keep state for next entry
199       float ss = (int)(j / d_int_rate);  // number of items to skip ahead by
200       count += ss;                       // we have fully consumed another input
201       j = j % d_int_rate;                // roll filter around
202     }
203   }
204
205   // Store the current filter position and start of next sample
206   d_last_filter = j;
207   d_start_index = std::max(0, count - ninput_items[0]);
208
209   // consume all we've processed but no more than we can
210   consume_each(std::min(count, ninput_items[0]));
211   return i;
212 }