GNU Radio 3.7.2 C++ API
pfb_arb_resampler.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2013 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 
24 #ifndef INCLUDED_PFB_ARB_RESAMPLER_H
25 #define INCLUDED_PFB_ARB_RESAMPLER_H
26 
28 
29 namespace gr {
30  namespace filter {
31  namespace kernel {
32 
33  /*!
34  * \brief Polyphase filterbank arbitrary resampler with
35  * gr_complex input, gr_complex output and float taps
36  * \ingroup resamplers_blk
37  *
38  * \details
39  * This takes in a signal stream and performs arbitrary
40  * resampling. The resampling rate can be any real number
41  * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
42  * filters where <EM>N</EM> is the interpolation rate. We then
43  * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
44  *
45  * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
46  * resampling where <EM>N/D</EM> is a rational number close to
47  * the input rate <EM>r</EM> where we have <EM>N</EM> filters
48  * and we cycle through them as a polyphase filterbank with a
49  * stride of <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
50  *
51  * To get the arbitrary rate, we want to interpolate between two
52  * points. For each value out, we take an output from the
53  * current filter, <EM>i</EM>, and the next filter <EM>i+1</EM>
54  * and then linearly interpolate between the two based on the
55  * real resampling rate we want.
56  *
57  * The linear interpolation only provides us with an
58  * approximation to the real sampling rate specified. The error
59  * is a quantization error between the two filters we used as
60  * our interpolation points. To this end, the number of
61  * filters, <EM>N</EM>, used determines the quantization error;
62  * the larger <EM>N</EM>, the smaller the noise. You can design
63  * for a specified noise floor by setting the filter size
64  * (parameters <EM>filter_size</EM>). The size defaults to 32
65  * filters, which is about as good as most implementations need.
66  *
67  * The trick with designing this filter is in how to specify the
68  * taps of the prototype filter. Like the PFB interpolator, the
69  * taps are specified using the interpolated filter rate. In
70  * this case, that rate is the input sample rate multiplied by
71  * the number of filters in the filterbank, which is also the
72  * interpolation rate. All other values should be relative to
73  * this rate.
74  *
75  * For example, for a 32-filter arbitrary resampler and using
76  * the GNU Radio's firdes utility to build the filter, we build
77  * a low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
78  * bandwidth of <EM>BW</EM> and a transition bandwidth of
79  * <EM>TB</EM>. We can also specify the out-of-band attenuation
80  * to use, <EM>ATT</EM>, and the filter window function (a
81  * Blackman-harris window in this case). The first input is the
82  * gain of the filter, which we specify here as the
83  * interpolation rate (<EM>32</EM>).
84  *
85  * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB,
86  * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
87  *
88  * The theory behind this block can be found in Chapter 7.5 of
89  * the following book.
90  *
91  * <B><EM>f. harris, "Multirate Signal Processing for Communication
92  * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
93  */
95  {
96  private:
97  std::vector<fir_filter_ccf*> d_filters;
98  std::vector<fir_filter_ccf*> d_diff_filters;
99  std::vector< std::vector<float> > d_taps;
100  std::vector< std::vector<float> > d_dtaps;
101  unsigned int d_int_rate; // the number of filters (interpolation rate)
102  unsigned int d_dec_rate; // the stride through the filters (decimation rate)
103  float d_flt_rate; // residual rate for the linear interpolation
104  float d_acc; // accumulator; holds fractional part of sample
105  unsigned int d_last_filter; // stores filter for re-entry
106  unsigned int d_taps_per_filter; // num taps for each arm of the filterbank
107  int d_delay; // filter's group delay
108  float d_est_phase_change; // est. of phase change of a sine wave through filt.
109 
110  /*!
111  * Takes in the taps and convolves them with [-1,0,1], which
112  * creates a differential set of taps that are used in the
113  * difference filterbank.
114  * \param newtaps (vector of floats) The prototype filter.
115  * \param difftaps (vector of floats) (out) The differential filter taps.
116  */
117  void create_diff_taps(const std::vector<float> &newtaps,
118  std::vector<float> &difftaps);
119 
120  /*!
121  * Resets the filterbank's filter taps with the new prototype filter
122  * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
123  * The taps should be generated at the interpolated sampling rate.
124  * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
125  * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
126  */
127  void create_taps(const std::vector<float> &newtaps,
128  std::vector< std::vector<float> > &ourtaps,
129  std::vector<kernel::fir_filter_ccf*> &ourfilter);
130 
131  public:
132  /*!
133  * Creates a kernel to perform arbitrary resampling on a set of samples.
134  * \param rate (float) Specifies the resampling rate to use
135  * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate.
136  * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
137  * related to quantization noise introduced during the resampling.
138  * Defaults to 32 filters.
139  */
140  pfb_arb_resampler_ccf(float rate,
141  const std::vector<float> &taps,
142  unsigned int filter_size);
143 
145 
146  /*!
147  * Resets the filterbank's filter taps with the new prototype filter
148  * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
149  */
150  void set_taps(const std::vector<float> &taps);
151 
152  /*!
153  * Return a vector<vector<>> of the filterbank taps
154  */
155  std::vector<std::vector<float> > taps() const;
156 
157  /*!
158  * Print all of the filterbank taps to screen.
159  */
160  void print_taps();
161 
162  /*!
163  * Sets the resampling rate of the block.
164  */
165  void set_rate(float rate);
166 
167  /*!
168  * Sets the current phase offset in radians (0 to 2pi).
169  */
170  void set_phase(float ph);
171 
172  /*!
173  * Gets the current phase of the resampler in radians (2 to 2pi).
174  */
175  float phase() const;
176 
177  /*!
178  * Gets the number of taps per filter.
179  */
180  unsigned int taps_per_filter() const;
181 
182  unsigned int interpolation_rate() const { return d_int_rate; }
183  unsigned int decimation_rate() const { return d_dec_rate; }
184  float fractional_rate() const { return d_flt_rate; }
185 
186  /*!
187  * Get the group delay of the filter.
188  */
189  int group_delay() const { return d_delay; }
190 
191  /*!
192  * Calculates the phase offset expected by a sine wave of
193  * frequency \p freq and sampling rate \p fs (assuming input
194  * sine wave has 0 degree phase).
195  */
196  float phase_offset(float freq, float fs);
197 
198  /*!
199  * Performs the filter operation that resamples the signal.
200  *
201  * This block takes in a stream of samples and outputs a
202  * resampled and filtered stream. This block should be called
203  * such that the output has \p rate * \p n_to_read amount of
204  * space available in the \p output buffer.
205  *
206  * \param input An input vector of samples to be resampled
207  * \param output The output samples at the new sample rate.
208  * \param n_to_read Number of samples to read from \p input.
209  * \param n_read (out) Number of samples actually read from \p input.
210  * \return Number of samples put into \p output.
211  */
212  int filter(gr_complex *input, gr_complex *output,
213  int n_to_read, int &n_read);
214  };
215 
216 
217  /**************************************************************/
218 
219 
220  /*!
221  * \brief Polyphase filterbank arbitrary resampler with
222  * float input, float output and float taps
223  * \ingroup resamplers_blk
224  *
225  * \details
226  * This takes in a signal stream and performs arbitrary
227  * resampling. The resampling rate can be any real number
228  * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
229  * filters where <EM>N</EM> is the interpolation rate. We then
230  * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
231  *
232  * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
233  * resampling where <EM>N/D</EM> is a rational number close to
234  * the input rate <EM>r</EM> where we have <EM>N</EM> filters
235  * and we cycle through them as a polyphase filterbank with a
236  * stride of <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
237  *
238  * To get the arbitrary rate, we want to interpolate between two
239  * points. For each value out, we take an output from the
240  * current filter, <EM>i</EM>, and the next filter <EM>i+1</EM>
241  * and then linearly interpolate between the two based on the
242  * real resampling rate we want.
243  *
244  * The linear interpolation only provides us with an
245  * approximation to the real sampling rate specified. The error
246  * is a quantization error between the two filters we used as
247  * our interpolation points. To this end, the number of
248  * filters, <EM>N</EM>, used determines the quantization error;
249  * the larger <EM>N</EM>, the smaller the noise. You can design
250  * for a specified noise floor by setting the filter size
251  * (parameters <EM>filter_size</EM>). The size defaults to 32
252  * filters, which is about as good as most implementations need.
253  *
254  * The trick with designing this filter is in how to specify the
255  * taps of the prototype filter. Like the PFB interpolator, the
256  * taps are specified using the interpolated filter rate. In
257  * this case, that rate is the input sample rate multiplied by
258  * the number of filters in the filterbank, which is also the
259  * interpolation rate. All other values should be relative to
260  * this rate.
261  *
262  * For example, for a 32-filter arbitrary resampler and using
263  * the GNU Radio's firdes utility to build the filter, we build
264  * a low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
265  * bandwidth of <EM>BW</EM> and a transition bandwidth of
266  * <EM>TB</EM>. We can also specify the out-of-band attenuation
267  * to use, <EM>ATT</EM>, and the filter window function (a
268  * Blackman-harris window in this case). The first input is the
269  * gain of the filter, which we specify here as the
270  * interpolation rate (<EM>32</EM>).
271  *
272  * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB,
273  * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
274  *
275  * The theory behind this block can be found in Chapter 7.5 of
276  * the following book.
277  *
278  * <B><EM>f. harris, "Multirate Signal Processing for Communication
279  * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
280  */
282  {
283  private:
284  std::vector<fir_filter_fff*> d_filters;
285  std::vector<fir_filter_fff*> d_diff_filters;
286  std::vector< std::vector<float> > d_taps;
287  std::vector< std::vector<float> > d_dtaps;
288  unsigned int d_int_rate; // the number of filters (interpolation rate)
289  unsigned int d_dec_rate; // the stride through the filters (decimation rate)
290  float d_flt_rate; // residual rate for the linear interpolation
291  float d_acc; // accumulator; holds fractional part of sample
292  unsigned int d_last_filter; // stores filter for re-entry
293  unsigned int d_taps_per_filter; // num taps for each arm of the filterbank
294  int d_delay; // filter's group delay
295  float d_est_phase_change; // est. of phase change of a sine wave through filt.
296 
297  /*!
298  * Takes in the taps and convolves them with [-1,0,1], which
299  * creates a differential set of taps that are used in the
300  * difference filterbank.
301  * \param newtaps (vector of floats) The prototype filter.
302  * \param difftaps (vector of floats) (out) The differential filter taps.
303  */
304  void create_diff_taps(const std::vector<float> &newtaps,
305  std::vector<float> &difftaps);
306 
307  /*!
308  * Resets the filterbank's filter taps with the new prototype filter
309  * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
310  * The taps should be generated at the interpolated sampling rate.
311  * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
312  * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
313  */
314  void create_taps(const std::vector<float> &newtaps,
315  std::vector< std::vector<float> > &ourtaps,
316  std::vector<kernel::fir_filter_fff*> &ourfilter);
317 
318  public:
319  /*!
320  * Creates a kernel to perform arbitrary resampling on a set of samples.
321  * \param rate (float) Specifies the resampling rate to use
322  * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate.
323  * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
324  * related to quantization noise introduced during the resampling.
325  * Defaults to 32 filters.
326  */
327  pfb_arb_resampler_fff(float rate,
328  const std::vector<float> &taps,
329  unsigned int filter_size);
330 
332 
333  /*!
334  * Resets the filterbank's filter taps with the new prototype filter
335  * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
336  */
337  void set_taps(const std::vector<float> &taps);
338 
339  /*!
340  * Return a vector<vector<>> of the filterbank taps
341  */
342  std::vector<std::vector<float> > taps() const;
343 
344  /*!
345  * Print all of the filterbank taps to screen.
346  */
347  void print_taps();
348 
349  /*!
350  * Sets the resampling rate of the block.
351  */
352  void set_rate(float rate);
353 
354  /*!
355  * Sets the current phase offset in radians (0 to 2pi).
356  */
357  void set_phase(float ph);
358 
359  /*!
360  * Gets the current phase of the resampler in radians (2 to 2pi).
361  */
362  float phase() const;
363 
364  /*!
365  * Gets the number of taps per filter.
366  */
367  unsigned int taps_per_filter() const;
368 
369  unsigned int interpolation_rate() const { return d_int_rate; }
370  unsigned int decimation_rate() const { return d_dec_rate; }
371  float fractional_rate() const { return d_flt_rate; }
372 
373  /*!
374  * Get the group delay of the filter.
375  */
376  int group_delay() const { return d_delay; }
377 
378  /*!
379  * Calculates the phase offset expected by a sine wave of
380  * frequency \p freq and sampling rate \p fs (assuming input
381  * sine wave has 0 degree phase).
382  */
383  float phase_offset(float freq, float fs);
384 
385  /*!
386  * Performs the filter operation that resamples the signal.
387  *
388  * This block takes in a stream of samples and outputs a
389  * resampled and filtered stream. This block should be called
390  * such that the output has \p rate * \p n_to_read amount of
391  * space available in the \p output buffer.
392  *
393  * \param input An input vector of samples to be resampled
394  * \param output The output samples at the new sample rate.
395  * \param n_to_read Number of samples to read from \p input.
396  * \param n_read (out) Number of samples actually read from \p input.
397  * \return Number of samples put into \p output.
398  */
399  int filter(float *input, float *output,
400  int n_to_read, int &n_read);
401  };
402 
403  } /* namespace kernel */
404  } /* namespace filter */
405 } /* namespace gr */
406 
407 #endif /* INCLUDED_PFB_ARB_RESAMPLER_H */
unsigned int interpolation_rate() const
Definition: pfb_arb_resampler.h:182
Polyphase filterbank arbitrary resampler with gr_complex input, gr_complex output and float taps...
Definition: pfb_arb_resampler.h:94
int group_delay() const
Definition: pfb_arb_resampler.h:376
unsigned int decimation_rate() const
Definition: pfb_arb_resampler.h:183
float fractional_rate() const
Definition: pfb_arb_resampler.h:184
std::complex< float > gr_complex
Definition: gr_complex.h:27
unsigned int decimation_rate() const
Definition: pfb_arb_resampler.h:370
float fractional_rate() const
Definition: pfb_arb_resampler.h:371
int group_delay() const
Definition: pfb_arb_resampler.h:189
static const float taps[NSTEPS+1][NTAPS]
Definition: interpolator_taps.h:9
unsigned int interpolation_rate() const
Definition: pfb_arb_resampler.h:369
Polyphase filterbank arbitrary resampler with float input, float output and float taps...
Definition: pfb_arb_resampler.h:281
#define FILTER_API
Definition: gr-filter/include/gnuradio/filter/api.h:30