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