GNU Radio Manual and C++ API Reference  3.7.13.4
The Free & Open Software Radio Ecosystem
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 output The output samples at the new sample rate.
207  * \param input An input vector of samples to be resampled
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 *output, gr_complex *input,
213  int n_to_read, int &n_read);
214  };
215 
216 
217  /**************************************************************/
218 
219 
221  {
222  private:
223  std::vector<fir_filter_ccc*> d_filters;
224  std::vector<fir_filter_ccc*> d_diff_filters;
225  std::vector< std::vector<gr_complex> > d_taps;
226  std::vector< std::vector<gr_complex> > d_dtaps;
227  unsigned int d_int_rate; // the number of filters (interpolation rate)
228  unsigned int d_dec_rate; // the stride through the filters (decimation rate)
229  float d_flt_rate; // residual rate for the linear interpolation
230  float d_acc; // accumulator; holds fractional part of sample
231  unsigned int d_last_filter; // stores filter for re-entry
232  unsigned int d_taps_per_filter; // num taps for each arm of the filterbank
233  int d_delay; // filter's group delay
234  float d_est_phase_change; // est. of phase change of a sine wave through filt.
235 
236  /*!
237  * Takes in the taps and convolves them with [-1,0,1], which
238  * creates a differential set of taps that are used in the
239  * difference filterbank.
240  * \param newtaps (vector of complex) The prototype filter.
241  * \param difftaps (vector of complex) (out) The differential filter taps.
242  */
243  void create_diff_taps(const std::vector<gr_complex> &newtaps,
244  std::vector<gr_complex> &difftaps);
245 
246  /*!
247  * Resets the filterbank's filter taps with the new prototype filter
248  * \param newtaps (vector of complex) The prototype filter to populate the filterbank.
249  * The taps should be generated at the interpolated sampling rate.
250  * \param ourtaps (vector of complex) Reference to our internal member of holding the taps.
251  * \param ourfilter (vector of ccc filters) Reference to our internal filter to set the taps for.
252  */
253  void create_taps(const std::vector<gr_complex> &newtaps,
254  std::vector< std::vector<gr_complex> > &ourtaps,
255  std::vector<kernel::fir_filter_ccc*> &ourfilter);
256 
257  public:
258  /*!
259  * Creates a kernel to perform arbitrary resampling on a set of samples.
260  * \param rate (float) Specifies the resampling rate to use
261  * \param taps (vector/list of complex) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate.
262  * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
263  * related to quantization noise introduced during the resampling.
264  * Defaults to 32 filters.
265  */
266  pfb_arb_resampler_ccc(float rate,
267  const std::vector<gr_complex> &taps,
268  unsigned int filter_size);
269 
271 
272  /*!
273  * Resets the filterbank's filter taps with the new prototype filter
274  * \param taps (vector/list of complex) The prototype filter to populate the filterbank.
275  */
276  void set_taps(const std::vector<gr_complex> &taps);
277 
278  /*!
279  * Return a vector<vector<>> of the filterbank taps
280  */
281  std::vector<std::vector<gr_complex> > taps() const;
282 
283  /*!
284  * Print all of the filterbank taps to screen.
285  */
286  void print_taps();
287 
288  /*!
289  * Sets the resampling rate of the block.
290  */
291  void set_rate(float rate);
292 
293  /*!
294  * Sets the current phase offset in radians (0 to 2pi).
295  */
296  void set_phase(float ph);
297 
298  /*!
299  * Gets the current phase of the resampler in radians (2 to 2pi).
300  */
301  float phase() const;
302 
303  /*!
304  * Gets the number of taps per filter.
305  */
306  unsigned int taps_per_filter() const;
307 
308  unsigned int interpolation_rate() const { return d_int_rate; }
309  unsigned int decimation_rate() const { return d_dec_rate; }
310  float fractional_rate() const { return d_flt_rate; }
311 
312  /*!
313  * Get the group delay of the filter.
314  */
315  int group_delay() const { return d_delay; }
316 
317  /*!
318  * Calculates the phase offset expected by a sine wave of
319  * frequency \p freq and sampling rate \p fs (assuming input
320  * sine wave has 0 degree phase).
321  */
322  float phase_offset(float freq, float fs);
323 
324  /*!
325  * Performs the filter operation that resamples the signal.
326  *
327  * This block takes in a stream of samples and outputs a
328  * resampled and filtered stream. This block should be called
329  * such that the output has \p rate * \p n_to_read amount of
330  * space available in the \p output buffer.
331  *
332  * \param output The output samples at the new sample rate.
333  * \param input An input vector of samples to be resampled
334  * \param n_to_read Number of samples to read from \p input.
335  * \param n_read (out) Number of samples actually read from \p input.
336  * \return Number of samples put into \p output.
337  */
338  int filter(gr_complex *output, gr_complex *input,
339  int n_to_read, int &n_read);
340  };
341 
342 
343  /**************************************************************/
344 
345 
346  /*!
347  * \brief Polyphase filterbank arbitrary resampler with
348  * float input, float output and float taps
349  * \ingroup resamplers_blk
350  *
351  * \details
352  * This takes in a signal stream and performs arbitrary
353  * resampling. The resampling rate can be any real number
354  * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
355  * filters where <EM>N</EM> is the interpolation rate. We then
356  * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
357  *
358  * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
359  * resampling where <EM>N/D</EM> is a rational number close to
360  * the input rate <EM>r</EM> where we have <EM>N</EM> filters
361  * and we cycle through them as a polyphase filterbank with a
362  * stride of <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
363  *
364  * To get the arbitrary rate, we want to interpolate between two
365  * points. For each value out, we take an output from the
366  * current filter, <EM>i</EM>, and the next filter <EM>i+1</EM>
367  * and then linearly interpolate between the two based on the
368  * real resampling rate we want.
369  *
370  * The linear interpolation only provides us with an
371  * approximation to the real sampling rate specified. The error
372  * is a quantization error between the two filters we used as
373  * our interpolation points. To this end, the number of
374  * filters, <EM>N</EM>, used determines the quantization error;
375  * the larger <EM>N</EM>, the smaller the noise. You can design
376  * for a specified noise floor by setting the filter size
377  * (parameters <EM>filter_size</EM>). The size defaults to 32
378  * filters, which is about as good as most implementations need.
379  *
380  * The trick with designing this filter is in how to specify the
381  * taps of the prototype filter. Like the PFB interpolator, the
382  * taps are specified using the interpolated filter rate. In
383  * this case, that rate is the input sample rate multiplied by
384  * the number of filters in the filterbank, which is also the
385  * interpolation rate. All other values should be relative to
386  * this rate.
387  *
388  * For example, for a 32-filter arbitrary resampler and using
389  * the GNU Radio's firdes utility to build the filter, we build
390  * a low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
391  * bandwidth of <EM>BW</EM> and a transition bandwidth of
392  * <EM>TB</EM>. We can also specify the out-of-band attenuation
393  * to use, <EM>ATT</EM>, and the filter window function (a
394  * Blackman-harris window in this case). The first input is the
395  * gain of the filter, which we specify here as the
396  * interpolation rate (<EM>32</EM>).
397  *
398  * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB,
399  * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
400  *
401  * The theory behind this block can be found in Chapter 7.5 of
402  * the following book:
403  *
404  * <B><EM>f. harris, "Multirate Signal Processing for Communication
405  * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
406  */
408  {
409  private:
410  std::vector<fir_filter_fff*> d_filters;
411  std::vector<fir_filter_fff*> d_diff_filters;
412  std::vector< std::vector<float> > d_taps;
413  std::vector< std::vector<float> > d_dtaps;
414  unsigned int d_int_rate; // the number of filters (interpolation rate)
415  unsigned int d_dec_rate; // the stride through the filters (decimation rate)
416  float d_flt_rate; // residual rate for the linear interpolation
417  float d_acc; // accumulator; holds fractional part of sample
418  unsigned int d_last_filter; // stores filter for re-entry
419  unsigned int d_taps_per_filter; // num taps for each arm of the filterbank
420  int d_delay; // filter's group delay
421  float d_est_phase_change; // est. of phase change of a sine wave through filt.
422 
423  /*!
424  * Takes in the taps and convolves them with [-1,0,1], which
425  * creates a differential set of taps that are used in the
426  * difference filterbank.
427  * \param newtaps (vector of floats) The prototype filter.
428  * \param difftaps (vector of floats) (out) The differential filter taps.
429  */
430  void create_diff_taps(const std::vector<float> &newtaps,
431  std::vector<float> &difftaps);
432 
433  /*!
434  * Resets the filterbank's filter taps with the new prototype filter
435  * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
436  * The taps should be generated at the interpolated sampling rate.
437  * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
438  * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
439  */
440  void create_taps(const std::vector<float> &newtaps,
441  std::vector< std::vector<float> > &ourtaps,
442  std::vector<kernel::fir_filter_fff*> &ourfilter);
443 
444  public:
445  /*!
446  * Creates a kernel to perform arbitrary resampling on a set of samples.
447  * \param rate (float) Specifies the resampling rate to use
448  * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate.
449  * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
450  * related to quantization noise introduced during the resampling.
451  * Defaults to 32 filters.
452  */
453  pfb_arb_resampler_fff(float rate,
454  const std::vector<float> &taps,
455  unsigned int filter_size);
456 
458 
459  /*!
460  * Resets the filterbank's filter taps with the new prototype filter
461  * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
462  */
463  void set_taps(const std::vector<float> &taps);
464 
465  /*!
466  * Return a vector<vector<>> of the filterbank taps
467  */
468  std::vector<std::vector<float> > taps() const;
469 
470  /*!
471  * Print all of the filterbank taps to screen.
472  */
473  void print_taps();
474 
475  /*!
476  * Sets the resampling rate of the block.
477  */
478  void set_rate(float rate);
479 
480  /*!
481  * Sets the current phase offset in radians (0 to 2pi).
482  */
483  void set_phase(float ph);
484 
485  /*!
486  * Gets the current phase of the resampler in radians (2 to 2pi).
487  */
488  float phase() const;
489 
490  /*!
491  * Gets the number of taps per filter.
492  */
493  unsigned int taps_per_filter() const;
494 
495  unsigned int interpolation_rate() const { return d_int_rate; }
496  unsigned int decimation_rate() const { return d_dec_rate; }
497  float fractional_rate() const { return d_flt_rate; }
498 
499  /*!
500  * Get the group delay of the filter.
501  */
502  int group_delay() const { return d_delay; }
503 
504  /*!
505  * Calculates the phase offset expected by a sine wave of
506  * frequency \p freq and sampling rate \p fs (assuming input
507  * sine wave has 0 degree phase).
508  */
509  float phase_offset(float freq, float fs);
510 
511  /*!
512  * Performs the filter operation that resamples the signal.
513  *
514  * This block takes in a stream of samples and outputs a
515  * resampled and filtered stream. This block should be called
516  * such that the output has \p rate * \p n_to_read amount of
517  * space available in the \p output buffer.
518  *
519  * \param output The output samples at the new sample rate.
520  * \param input An input vector of samples to be resampled
521  * \param n_to_read Number of samples to read from \p input.
522  * \param n_read (out) Number of samples actually read from \p input.
523  * \return Number of samples put into \p output.
524  */
525  int filter(float *output, float *input,
526  int n_to_read, int &n_read);
527  };
528 
529  } /* namespace kernel */
530  } /* namespace filter */
531 } /* namespace gr */
532 
533 #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:502
unsigned int decimation_rate() const
Definition: pfb_arb_resampler.h:183
float fractional_rate() const
Definition: pfb_arb_resampler.h:184
unsigned int decimation_rate() const
Definition: pfb_arb_resampler.h:309
unsigned int interpolation_rate() const
Definition: pfb_arb_resampler.h:308
Definition: pfb_arb_resampler.h:220
std::complex< float > gr_complex
Definition: gr_complex.h:27
unsigned int decimation_rate() const
Definition: pfb_arb_resampler.h:496
float fractional_rate() const
Definition: pfb_arb_resampler.h:497
Include this header to use the message passing features.
Definition: logger.h:695
int group_delay() const
Definition: pfb_arb_resampler.h:189
int group_delay() const
Definition: pfb_arb_resampler.h:315
static const float taps[NSTEPS+1][NTAPS]
Definition: interpolator_taps.h:9
unsigned int interpolation_rate() const
Definition: pfb_arb_resampler.h:495
Polyphase filterbank arbitrary resampler with float input, float output and float taps...
Definition: pfb_arb_resampler.h:407
#define FILTER_API
Definition: gr-filter/include/gnuradio/filter/api.h:30
float fractional_rate() const
Definition: pfb_arb_resampler.h:310