GNU Radio 3.7.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2013 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 00024 #ifndef INCLUDED_PFB_ARB_RESAMPLER_H 00025 #define INCLUDED_PFB_ARB_RESAMPLER_H 00026 00027 #include <gnuradio/filter/fir_filter.h> 00028 00029 namespace gr { 00030 namespace filter { 00031 namespace kernel { 00032 00033 /*! 00034 * \brief Polyphase filterbank arbitrary resampler with 00035 * gr_complex input, gr_complex output and float taps 00036 * \ingroup resamplers_blk 00037 * 00038 * \details 00039 * This takes in a signal stream and performs arbitrary 00040 * resampling. The resampling rate can be any real number 00041 * <EM>r</EM>. The resampling is done by constructing <EM>N</EM> 00042 * filters where <EM>N</EM> is the interpolation rate. We then 00043 * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. 00044 * 00045 * Using <EM>N</EM> and <EM>D</EM>, we can perform rational 00046 * resampling where <EM>N/D</EM> is a rational number close to 00047 * the input rate <EM>r</EM> where we have <EM>N</EM> filters 00048 * and we cycle through them as a polyphase filterbank with a 00049 * stride of <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>. 00050 * 00051 * To get the arbitrary rate, we want to interpolate between two 00052 * points. For each value out, we take an output from the 00053 * current filter, <EM>i</EM>, and the next filter <EM>i+1</EM> 00054 * and then linearly interpolate between the two based on the 00055 * real resampling rate we want. 00056 * 00057 * The linear interpolation only provides us with an 00058 * approximation to the real sampling rate specified. The error 00059 * is a quantization error between the two filters we used as 00060 * our interpolation points. To this end, the number of 00061 * filters, <EM>N</EM>, used determines the quantization error; 00062 * the larger <EM>N</EM>, the smaller the noise. You can design 00063 * for a specified noise floor by setting the filter size 00064 * (parameters <EM>filter_size</EM>). The size defaults to 32 00065 * filters, which is about as good as most implementations need. 00066 * 00067 * The trick with designing this filter is in how to specify the 00068 * taps of the prototype filter. Like the PFB interpolator, the 00069 * taps are specified using the interpolated filter rate. In 00070 * this case, that rate is the input sample rate multiplied by 00071 * the number of filters in the filterbank, which is also the 00072 * interpolation rate. All other values should be relative to 00073 * this rate. 00074 * 00075 * For example, for a 32-filter arbitrary resampler and using 00076 * the GNU Radio's firdes utility to build the filter, we build 00077 * a low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB 00078 * bandwidth of <EM>BW</EM> and a transition bandwidth of 00079 * <EM>TB</EM>. We can also specify the out-of-band attenuation 00080 * to use, <EM>ATT</EM>, and the filter window function (a 00081 * Blackman-harris window in this case). The first input is the 00082 * gain of the filter, which we specify here as the 00083 * interpolation rate (<EM>32</EM>). 00084 * 00085 * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB, 00086 * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> 00087 * 00088 * The theory behind this block can be found in Chapter 7.5 of 00089 * the following book. 00090 * 00091 * <B><EM>f. harris, "Multirate Signal Processing for Communication 00092 * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> 00093 */ 00094 class FILTER_API pfb_arb_resampler_ccf 00095 { 00096 private: 00097 std::vector<fir_filter_ccf*> d_filters; 00098 std::vector<fir_filter_ccf*> d_diff_filters; 00099 std::vector< std::vector<float> > d_taps; 00100 std::vector< std::vector<float> > d_dtaps; 00101 unsigned int d_int_rate; // the number of filters (interpolation rate) 00102 unsigned int d_dec_rate; // the stride through the filters (decimation rate) 00103 float d_flt_rate; // residual rate for the linear interpolation 00104 float d_acc; // accumulator; holds fractional part of sample 00105 unsigned int d_last_filter; // stores filter for re-entry 00106 unsigned int d_taps_per_filter; // num taps for each arm of the filterbank 00107 int d_delay; // filter's group delay 00108 float d_est_phase_change; // est. of phase change of a sine wave through filt. 00109 00110 /*! 00111 * Takes in the taps and convolves them with [-1,0,1], which 00112 * creates a differential set of taps that are used in the 00113 * difference filterbank. 00114 * \param newtaps (vector of floats) The prototype filter. 00115 * \param difftaps (vector of floats) (out) The differential filter taps. 00116 */ 00117 void create_diff_taps(const std::vector<float> &newtaps, 00118 std::vector<float> &difftaps); 00119 00120 /*! 00121 * Resets the filterbank's filter taps with the new prototype filter 00122 * \param newtaps (vector of floats) The prototype filter to populate the filterbank. 00123 * The taps should be generated at the interpolated sampling rate. 00124 * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. 00125 * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. 00126 */ 00127 void create_taps(const std::vector<float> &newtaps, 00128 std::vector< std::vector<float> > &ourtaps, 00129 std::vector<kernel::fir_filter_ccf*> &ourfilter); 00130 00131 public: 00132 /*! 00133 * Creates a kernel to perform arbitrary resampling on a set of samples. 00134 * \param rate (float) Specifies the resampling rate to use 00135 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate. 00136 * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly 00137 * related to quantization noise introduced during the resampling. 00138 * Defaults to 32 filters. 00139 */ 00140 pfb_arb_resampler_ccf(float rate, 00141 const std::vector<float> &taps, 00142 unsigned int filter_size); 00143 00144 ~pfb_arb_resampler_ccf(); 00145 00146 /*! 00147 * Resets the filterbank's filter taps with the new prototype filter 00148 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. 00149 */ 00150 void set_taps(const std::vector<float> &taps); 00151 00152 /*! 00153 * Return a vector<vector<>> of the filterbank taps 00154 */ 00155 std::vector<std::vector<float> > taps() const; 00156 00157 /*! 00158 * Print all of the filterbank taps to screen. 00159 */ 00160 void print_taps(); 00161 00162 /*! 00163 * Sets the resampling rate of the block. 00164 */ 00165 void set_rate(float rate); 00166 00167 /*! 00168 * Sets the current phase offset in radians (0 to 2pi). 00169 */ 00170 void set_phase(float ph); 00171 00172 /*! 00173 * Gets the current phase of the resampler in radians (2 to 2pi). 00174 */ 00175 float phase() const; 00176 00177 /*! 00178 * Gets the number of taps per filter. 00179 */ 00180 unsigned int taps_per_filter() const; 00181 00182 unsigned int interpolation_rate() const { return d_int_rate; } 00183 unsigned int decimation_rate() const { return d_dec_rate; } 00184 float fractional_rate() const { return d_flt_rate; } 00185 00186 /*! 00187 * Get the group delay of the filter. 00188 */ 00189 int group_delay() const { return d_delay; } 00190 00191 /*! 00192 * Calculates the phase offset expected by a sine wave of 00193 * frequency \p freq and sampling rate \p fs (assuming input 00194 * sine wave has 0 degree phase). 00195 */ 00196 float phase_offset(float freq, float fs); 00197 00198 /*! 00199 * Performs the filter operation that resamples the signal. 00200 * 00201 * This block takes in a stream of samples and outputs a 00202 * resampled and filtered stream. This block should be called 00203 * such that the output has \p rate * \p n_to_read amount of 00204 * space available in the \p output buffer. 00205 * 00206 * \param input An input vector of samples to be resampled 00207 * \param output The output samples at the new sample rate. 00208 * \param n_to_read Number of samples to read from \p input. 00209 * \param n_read (out) Number of samples actually read from \p input. 00210 * \return Number of samples put into \p output. 00211 */ 00212 int filter(gr_complex *input, gr_complex *output, 00213 int n_to_read, int &n_read); 00214 }; 00215 00216 00217 /**************************************************************/ 00218 00219 00220 /*! 00221 * \brief Polyphase filterbank arbitrary resampler with 00222 * float input, float output and float taps 00223 * \ingroup resamplers_blk 00224 * 00225 * \details 00226 * This takes in a signal stream and performs arbitrary 00227 * resampling. The resampling rate can be any real number 00228 * <EM>r</EM>. The resampling is done by constructing <EM>N</EM> 00229 * filters where <EM>N</EM> is the interpolation rate. We then 00230 * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. 00231 * 00232 * Using <EM>N</EM> and <EM>D</EM>, we can perform rational 00233 * resampling where <EM>N/D</EM> is a rational number close to 00234 * the input rate <EM>r</EM> where we have <EM>N</EM> filters 00235 * and we cycle through them as a polyphase filterbank with a 00236 * stride of <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>. 00237 * 00238 * To get the arbitrary rate, we want to interpolate between two 00239 * points. For each value out, we take an output from the 00240 * current filter, <EM>i</EM>, and the next filter <EM>i+1</EM> 00241 * and then linearly interpolate between the two based on the 00242 * real resampling rate we want. 00243 * 00244 * The linear interpolation only provides us with an 00245 * approximation to the real sampling rate specified. The error 00246 * is a quantization error between the two filters we used as 00247 * our interpolation points. To this end, the number of 00248 * filters, <EM>N</EM>, used determines the quantization error; 00249 * the larger <EM>N</EM>, the smaller the noise. You can design 00250 * for a specified noise floor by setting the filter size 00251 * (parameters <EM>filter_size</EM>). The size defaults to 32 00252 * filters, which is about as good as most implementations need. 00253 * 00254 * The trick with designing this filter is in how to specify the 00255 * taps of the prototype filter. Like the PFB interpolator, the 00256 * taps are specified using the interpolated filter rate. In 00257 * this case, that rate is the input sample rate multiplied by 00258 * the number of filters in the filterbank, which is also the 00259 * interpolation rate. All other values should be relative to 00260 * this rate. 00261 * 00262 * For example, for a 32-filter arbitrary resampler and using 00263 * the GNU Radio's firdes utility to build the filter, we build 00264 * a low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB 00265 * bandwidth of <EM>BW</EM> and a transition bandwidth of 00266 * <EM>TB</EM>. We can also specify the out-of-band attenuation 00267 * to use, <EM>ATT</EM>, and the filter window function (a 00268 * Blackman-harris window in this case). The first input is the 00269 * gain of the filter, which we specify here as the 00270 * interpolation rate (<EM>32</EM>). 00271 * 00272 * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB, 00273 * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> 00274 * 00275 * The theory behind this block can be found in Chapter 7.5 of 00276 * the following book. 00277 * 00278 * <B><EM>f. harris, "Multirate Signal Processing for Communication 00279 * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> 00280 */ 00281 class FILTER_API pfb_arb_resampler_fff 00282 { 00283 private: 00284 std::vector<fir_filter_fff*> d_filters; 00285 std::vector<fir_filter_fff*> d_diff_filters; 00286 std::vector< std::vector<float> > d_taps; 00287 std::vector< std::vector<float> > d_dtaps; 00288 unsigned int d_int_rate; // the number of filters (interpolation rate) 00289 unsigned int d_dec_rate; // the stride through the filters (decimation rate) 00290 float d_flt_rate; // residual rate for the linear interpolation 00291 float d_acc; // accumulator; holds fractional part of sample 00292 unsigned int d_last_filter; // stores filter for re-entry 00293 unsigned int d_taps_per_filter; // num taps for each arm of the filterbank 00294 int d_delay; // filter's group delay 00295 float d_est_phase_change; // est. of phase change of a sine wave through filt. 00296 00297 /*! 00298 * Takes in the taps and convolves them with [-1,0,1], which 00299 * creates a differential set of taps that are used in the 00300 * difference filterbank. 00301 * \param newtaps (vector of floats) The prototype filter. 00302 * \param difftaps (vector of floats) (out) The differential filter taps. 00303 */ 00304 void create_diff_taps(const std::vector<float> &newtaps, 00305 std::vector<float> &difftaps); 00306 00307 /*! 00308 * Resets the filterbank's filter taps with the new prototype filter 00309 * \param newtaps (vector of floats) The prototype filter to populate the filterbank. 00310 * The taps should be generated at the interpolated sampling rate. 00311 * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. 00312 * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. 00313 */ 00314 void create_taps(const std::vector<float> &newtaps, 00315 std::vector< std::vector<float> > &ourtaps, 00316 std::vector<kernel::fir_filter_fff*> &ourfilter); 00317 00318 public: 00319 /*! 00320 * Creates a kernel to perform arbitrary resampling on a set of samples. 00321 * \param rate (float) Specifies the resampling rate to use 00322 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps * should be generated at the filter_size sampling rate. 00323 * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly 00324 * related to quantization noise introduced during the resampling. 00325 * Defaults to 32 filters. 00326 */ 00327 pfb_arb_resampler_fff(float rate, 00328 const std::vector<float> &taps, 00329 unsigned int filter_size); 00330 00331 ~pfb_arb_resampler_fff(); 00332 00333 /*! 00334 * Resets the filterbank's filter taps with the new prototype filter 00335 * \param taps (vector/list of floats) The prototype filter to populate the filterbank. 00336 */ 00337 void set_taps(const std::vector<float> &taps); 00338 00339 /*! 00340 * Return a vector<vector<>> of the filterbank taps 00341 */ 00342 std::vector<std::vector<float> > taps() const; 00343 00344 /*! 00345 * Print all of the filterbank taps to screen. 00346 */ 00347 void print_taps(); 00348 00349 /*! 00350 * Sets the resampling rate of the block. 00351 */ 00352 void set_rate(float rate); 00353 00354 /*! 00355 * Sets the current phase offset in radians (0 to 2pi). 00356 */ 00357 void set_phase(float ph); 00358 00359 /*! 00360 * Gets the current phase of the resampler in radians (2 to 2pi). 00361 */ 00362 float phase() const; 00363 00364 /*! 00365 * Gets the number of taps per filter. 00366 */ 00367 unsigned int taps_per_filter() const; 00368 00369 unsigned int interpolation_rate() const { return d_int_rate; } 00370 unsigned int decimation_rate() const { return d_dec_rate; } 00371 float fractional_rate() const { return d_flt_rate; } 00372 00373 /*! 00374 * Get the group delay of the filter. 00375 */ 00376 int group_delay() const { return d_delay; } 00377 00378 /*! 00379 * Calculates the phase offset expected by a sine wave of 00380 * frequency \p freq and sampling rate \p fs (assuming input 00381 * sine wave has 0 degree phase). 00382 */ 00383 float phase_offset(float freq, float fs); 00384 00385 /*! 00386 * Performs the filter operation that resamples the signal. 00387 * 00388 * This block takes in a stream of samples and outputs a 00389 * resampled and filtered stream. This block should be called 00390 * such that the output has \p rate * \p n_to_read amount of 00391 * space available in the \p output buffer. 00392 * 00393 * \param input An input vector of samples to be resampled 00394 * \param output The output samples at the new sample rate. 00395 * \param n_to_read Number of samples to read from \p input. 00396 * \param n_read (out) Number of samples actually read from \p input. 00397 * \return Number of samples put into \p output. 00398 */ 00399 int filter(float *input, float *output, 00400 int n_to_read, int &n_read); 00401 }; 00402 00403 } /* namespace kernel */ 00404 } /* namespace filter */ 00405 } /* namespace gr */ 00406 00407 #endif /* INCLUDED_PFB_ARB_RESAMPLER_H */