3 * Copyright 2009 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
24 #ifndef INCLUDED_GR_PFB_ARB_RESAMPLER_CCF_H
25 #define INCLUDED_GR_PFB_ARB_RESAMPLER_CCF_H
29 class gr_pfb_arb_resampler_ccf;
30 typedef boost::shared_ptr<gr_pfb_arb_resampler_ccf> gr_pfb_arb_resampler_ccf_sptr;
31 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate,
32 const std::vector<float> &taps,
33 unsigned int filter_size=32);
38 * \class gr_pfb_arb_resampler_ccf
40 * \brief Polyphase filterbank arbitrary resampler with
41 * gr_complex input, gr_complex output and float taps
45 * This block takes in a signal stream and performs arbitrary
46 * resampling. The resampling rate can be any real
47 * number <EM>r</EM>. The resampling is done by constructing
48 * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate. We
49 * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
51 * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling
52 * where <EM>N/D</EM> is a rational number close to the input rate
53 * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through
54 * them as a polyphase filterbank with a stride of <EM>D</EM> so that
55 * <EM>i+1 = (i + D) % N</EM>.
57 * To get the arbitrary rate, we want to interpolate between two
58 * points. For each value out, we take an output from the current
59 * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
60 * linearly interpolate between the two based on the real resampling
63 * The linear interpolation only provides us with an approximation to
64 * the real sampling rate specified. The error is a quantization error
65 * between the two filters we used as our interpolation points. To
66 * this end, the number of filters, <EM>N</EM>, used determines the
67 * quantization error; the larger <EM>N</EM>, the smaller the
68 * noise. You can design for a specified noise floor by setting the
69 * filter size (parameters <EM>filter_size</EM>). The size defaults to
70 * 32 filters, which is about as good as most implementations need.
72 * The trick with designing this filter is in how to specify the taps
73 * of the prototype filter. Like the PFB interpolator, the taps are
74 * specified using the interpolated filter rate. In this case, that
75 * rate is the input sample rate multiplied by the number of filters
76 * in the filterbank, which is also the interpolation rate. All other
77 * values should be relative to this rate.
79 * For example, for a 32-filter arbitrary resampler and using the
80 * GNU Radio's firdes utility to build the filter, we build a low-pass
81 * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of
82 * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also
83 * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the
84 * filter window function (a Blackman-harris window in this case). The
85 * first input is the gain of the filter, which we specify here as the
86 * interpolation rate (<EM>32</EM>).
88 * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB,
89 * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
91 * The theory behind this block can be found in Chapter 7.5 of
94 * <B><EM>f. harris, Multirate Signal Processing for Communication
95 * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
98 class gr_pfb_arb_resampler_ccf : public gr_block
102 * Build the polyphase filterbank arbitray resampler.
103 * \param rate (float) Specifies the resampling rate to use
104 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
105 * should be generated at the filter_size sampling rate.
106 * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
107 related to quantization noise introduced during the resampling.
108 Defaults to 32 filters.
110 friend gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate,
111 const std::vector<float> &taps,
112 unsigned int filter_size);
114 std::vector<gr_fir_ccf*> d_filters;
115 std::vector< std::vector<float> > d_taps;
116 unsigned int d_int_rate; // the number of filters (interpolation rate)
117 unsigned int d_dec_rate; // the stride through the filters (decimation rate)
118 float d_flt_rate; // residual rate for the linear interpolation
120 unsigned int d_last_filter;
121 unsigned int d_taps_per_filter;
125 * Build the polyphase filterbank arbitray resampler.
126 * \param rate (float) Specifies the resampling rate to use
127 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
128 * should be generated at the filter_size sampling rate.
129 * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
130 related to quantization noise introduced during the resampling.
131 Defaults to 32 filters.
133 gr_pfb_arb_resampler_ccf (float rate,
134 const std::vector<float> &taps,
135 unsigned int filter_size);
138 ~gr_pfb_arb_resampler_ccf ();
141 * Resets the filterbank's filter taps with the new prototype filter
142 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
143 * should be generated at the interpolated sampling rate.
145 void set_taps (const std::vector<float> &taps);
148 * Print all of the filterbank taps to screen.
152 int general_work (int noutput_items,
153 gr_vector_int &ninput_items,
154 gr_vector_const_void_star &input_items,
155 gr_vector_void_star &output_items);