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