diff options
-rw-r--r-- | docs/doxygen/other/group_defs.dox | 1 | ||||
-rw-r--r-- | docs/doxygen/other/main_page.dox | 2 | ||||
-rw-r--r-- | docs/doxygen/other/pfb_intro.dox | 82 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h | 128 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h | 128 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h | 1 |
11 files changed, 232 insertions, 115 deletions
diff --git a/docs/doxygen/other/group_defs.dox b/docs/doxygen/other/group_defs.dox index 646df6855..6288d1f0a 100644 --- a/docs/doxygen/other/group_defs.dox +++ b/docs/doxygen/other/group_defs.dox @@ -31,6 +31,7 @@ /*! \defgroup qtgui_blk QT Graphical Interfaces */ /*! \defgroup uhd_blk UHD Interface */ /*! \defgroup audio_blk Audio Interface */ +/*! \defgroup pfb_blk Polyphase Filterbank */ /*! * \defgroup base_blk Base classes for GR Blocks diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox index f8d0dcf73..7d78bbbbb 100644 --- a/docs/doxygen/other/main_page.dox +++ b/docs/doxygen/other/main_page.dox @@ -15,5 +15,5 @@ More details on packages in GNU Radio: \li \ref page_qtgui \li \ref page_uhd \li \ref page_vocoder - +\li \ref page_pfb */ diff --git a/docs/doxygen/other/pfb_intro.dox b/docs/doxygen/other/pfb_intro.dox new file mode 100644 index 000000000..8b82d96d7 --- /dev/null +++ b/docs/doxygen/other/pfb_intro.dox @@ -0,0 +1,82 @@ +/*! \page page_pfb Polyphase Filterbanks + +\section Introduction + +Polyphase filterbanks (PFB) are a very powerful set of filtering tools +that can efficiently perform many multi-rate signal processing +tasks. GNU Radio has a set of polyphase filterbank blocks to be used +in all sorts of applications. These blocks and their documentation can +be found in \ref pfb_blk. + +\section Usage + +See the documentation for the individual blocks for details about what +they can do and how they should be used. Furthermore, there are +examples for these blocks in <b>gnuradio-examples/python/pfb</b>. + +The main issue when using the PFB blocks is defining the prototype +filter, which is passed to all of the blocks as a vector of \p +taps. The taps from the prototype filter which get partitioned among +the \p N channels of the channelizer. + +An example of creating a set of filter taps for a PFB channelizer is +found on line 49 of <b>gnuradio-examples/python/pfb/channelizer.py</b> +and reproduced below. Notice that the sample rate is the sample rate +at the input to the channelizer while the bandwidth and transition +width are defined for the channel bandwidths. This makes a fairly long +filter that is then split up between the \p N channels of the PFB. + +\code + self._fs = 9000 # input sample rate + self._M = 9 # Number of channels to channelize + + self._taps = gr.firdes.low_pass_2(1, self._fs, 475.50, 50, + attenuation_dB=100, + window=gr.firdes.WIN_BLACKMAN_hARRIS) +\endcode + +In this example, the signal into the channelizer is sampled at 9 ksps +(complex, so 9 kHz of bandwidth). The filter uses 9 channels, so each +output channel will have a bandwidth and sample rate of 1 kHz. We want +to pass most of the channel, so we define the channel bandwidth to be +a low pass filter with a bandwidth of 475.5 Hz and a transition +bandwidth of 50 Hz, but we have defined this using a sample rate of +the original 9 kHz. The prototype filter has 819 taps to be divided up +between the 9 channels, so each channel uses 91 taps. This is probably +over-kill for a channelizer, and we could reduce the amount of taps +per channel to a couple of dozen with no ill effects. + +The basic rule when defining a set of taps for a PFB block is to think +about the filter running at the highest rate it will see while the +bandwidth is defined for the size of the channels. In the channelizer +case, the highest rate is defined as the rate of the incoming signal, +but in other PFB blocks, this is not so obvious. + +Two very useful blocks to use are the arbitrary resampler and the +clock synchronizer (for PAM signals). These PFBs are defined with a +set number of filters based on the fidelity required from them, not +the rate changes. By default, the \p filter_size is set to 32 for +these blocks, which is a reasonable default for most tasks. Because +the PFB uses this number of filters in the filterbank, the maximum +rate of the bank is defined from this (see the theory of a polyphase +interpolator for a justification of this). So the prototype filter is +defined to use a sample rate of \p filter_size times the signal's +sampling rate. + +A helpful wrapper for the arbitrary resampler is found in +<b>gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py</b>, +which is exposed in Python as <b>blks2.pfb_arb_resampler_ccf</b> and +<b>blks2.pfb_arb_resampler_fff</b>. This block is set up so that the +user only needs to pass it the real number \p rate as the resampling +rate. With just this information, this hierarchical block +automatically creates a filter that fully passes the signal bandwidth +being resampled but does not pass any out-of-band noise. See the code +for this block for details of how the filter is constructed. + +Of course, a user can create his or her own taps and use them in the +arbitrary resampler for more specific requirements. Some of the UHD +examples (<b>gr-uhd/examples</b>) use this ability to create a +received matched filter or channel filter that also resamples the +signal. + +*/ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h index 2c36c95f9..806c33d92 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h @@ -41,6 +41,7 @@ class gr_fir_ccf; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs arbitrary * resampling. The resampling rate can be any real diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h index 541df8aa4..69331a2c6 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h @@ -41,6 +41,7 @@ class gr_fir_fff; * float input, float output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs arbitrary * resampling. The resampling rate can be any real diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h index 751673bc7..68476ed3c 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h @@ -43,6 +43,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in complex inputs and channelizes it to <EM>M</EM> * channels of equal bandwidth. Each of the resulting channels is diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h index 06a6f5720..674dee181 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h @@ -43,71 +43,85 @@ class gr_fir_ccf; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * - * This block performs timing synchronization for PAM signals by minimizing the - * derivative of the filtered signal, which in turn maximizes the SNR and - * minimizes ISI. + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. * - * This approach works by setting up two filterbanks; one filterbank contains the - * signal's pulse shaping matched filter (such as a root raised cosine filter), - * where each branch of the filterbank contains a different phase of the filter. - * The second filterbank contains the derivatives of the filters in the first - * filterbank. Thinking of this in the time domain, the first filterbank contains - * filters that have a sinc shape to them. We want to align the output signal to - * be sampled at exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)' = 0). - * Furthermore, the region around the zero point is relatively linear. We make - * use of this fact to generate the error signal. + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. * - * If the signal out of the derivative filters is d_i[n] for the ith filter, and - * the output of the matched filter is x_i[n], we calculate the error as: - * e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 - * This equation averages the error in the real and imaginary parts. There are two - * reasons we multiply by the signal itself. First, if the symbol could be positive - * or negative going, but we want the error term to always tell us to go in the - * same direction depending on which side of the zero point we are on. The sign of - * x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales - * the error term depending on the symbol's amplitude, so larger signals give us - * a stronger error term because we have more confidence in that symbol's value. - * Using the magnitude of x_i[n] instead of just the sign is especially good for - * signals with low SNR. + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. * - * The error signal, e[n], gives us a value proportional to how far away from the zero - * point we are in the derivative signal. We want to drive this value to zero, so we - * set up a second order loop. We have two variables for this loop; d_k is the filter - * number in the filterbank we are on and d_rate is the rate which we travel through - * the filters in the steady state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference and would traverse - * the filter phase paths to keep the receiver locked. Thinking of this as a second-order - * PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, d_alpha and d_beta. - * We have these two values set based on each other for a critically damped system, so in - * the block constructor, we just ask for "gain," which is d_alpha while d_beta is - * equal to (gain^2)/4. + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. * - * The clock sync block needs to know the number of samples per symbol (sps), because it - * only returns a single point representing the symbol. The sps can be any positive real - * number and does not need to be an integer. The filter taps must also be specified. The - * taps are generated by first conceiving of the prototype filter that would be the signal's - * matched filter. Then interpolate this by the number of filters in the filterbank. These - * are then distributed among all of the filters. So if the prototype filter was to have - * 45 taps in it, then each path of the filterbank will also have 45 taps. This is easily - * done by building the filter with the sample rate multiplied by the number of filters - * to use. + * The clock sync block needs to know the number of samples per symbol + * (sps), because it only returns a single point representing the + * symbol. The sps can be any positive real number and does not need + * to be an integer. The filter taps must also be specified. The taps + * are generated by first conceiving of the prototype filter that + * would be the signal's matched filter. Then interpolate this by the + * number of filters in the filterbank. These are then distributed + * among all of the filters. So if the prototype filter was to have 45 + * taps in it, then each path of the filterbank will also have 45 + * taps. This is easily done by building the filter with the sample + * rate multiplied by the number of filters to use. * - * The number of filters can also be set and defaults to 32. With 32 filters, you get a - * good enough resolution in the phase to produce very small, almost unnoticeable, ISI. - * Going to 64 filters can reduce this more, but after that there is very little gained - * for the extra complexity. + * The number of filters can also be set and defaults to 32. With 32 + * filters, you get a good enough resolution in the phase to produce + * very small, almost unnoticeable, ISI. Going to 64 filters can + * reduce this more, but after that there is very little gained for + * the extra complexity. * - * The initial phase is another settable parameter and refers to the filter path the - * algorithm initially looks at (i.e., d_k starts at init_phase). This value defaults - * to zero, but it might be useful to start at a different phase offset, such as the mid- - * point of the filters. + * The initial phase is another settable parameter and refers to the + * filter path the algorithm initially looks at (i.e., d_k starts at + * init_phase). This value defaults to zero, but it might be useful to + * start at a different phase offset, such as the mid- point of the + * filters. * - * The final parameter is the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from 0. Constraining the rate can help - * keep the algorithm from walking too far away to lock during times when there is no signal. + * The final parameter is the max_rate_devitation, which defaults to + * 1.5. This is how far we allow d_rate to swing, positive or + * negative, from 0. Constraining the rate can help keep the algorithm + * from walking too far away to lock during times when there is no + * signal. * */ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h index fa1279a7c..d7c646801 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h @@ -42,71 +42,85 @@ class gr_fir_fff; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * - * This block performs timing synchronization for PAM signals by minimizing the - * derivative of the filtered signal, which in turn maximizes the SNR and - * minimizes ISI. + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. * - * This approach works by setting up two filterbanks; one filterbanke contains the - * signal's pulse shaping matched filter (such as a root raised cosine filter), - * where each branch of the filterbank contains a different phase of the filter. - * The second filterbank contains the derivatives of the filters in the first - * filterbank. Thinking of this in the time domain, the first filterbank contains - * filters that have a sinc shape to them. We want to align the output signal to - * be sampled at exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)' = 0). - * Furthermore, the region around the zero point is relatively linear. We make - * use of this fact to generate the error signal. + * This approach works by setting up two filterbanks; one filterbanke + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. * - * If the signal out of the derivative filters is d_i[n] for the ith filter, and - * the output of the matched filter is x_i[n], we calculate the error as: - * e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 - * This equation averages the error in the real and imaginary parts. There are two - * reasons we multiply by the signal itself. First, if the symbol could be positive - * or negative going, but we want the error term to always tell us to go in the - * same direction depending on which side of the zero point we are on. The sign of - * x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales - * the error term depending on the symbol's amplitude, so larger signals give us - * a stronger error term because we have more confidence in that symbol's value. - * Using the magnitude of x_i[n] instead of just the sign is especially good for - * signals with low SNR. + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. * - * The error signal, e[n], gives us a value proportional to how far away from the zero - * point we are in the derivative signal. We want to drive this value to zero, so we - * set up a second order loop. We have two variables for this loop; d_k is the filter - * number in the filterbank we are on and d_rate is the rate which we travel through - * the filters in the steady state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference and would traverse - * the filter phase paths to keep the receiver locked. Thinking of this as a second-order - * PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, d_alpha and d_beta. - * We have these two values set based on each other for a critically damped system, so in - * the block constructor, we just ask for "gain," which is d_alpha while d_beta is - * equal to (gain^2)/4. + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. * - * The clock sync block needs to know the number of samples per second (sps), because it - * only returns a single point representing the sample. The sps can be any positive real - * number and does not need to be an integer. The filter taps must also be specified. The - * taps are generated by first conceiving of the prototype filter that would be the signal's - * matched filter. Then interpolate this by the number of filters in the filterbank. These - * are then distributed among all of the filters. So if the prototype filter was to have - * 45 taps in it, then each path of the filterbank will also have 45 taps. This is easily - * done by building the filter with the sample rate multiplied by the number of filters - * to use. + * The clock sync block needs to know the number of samples per second + * (sps), because it only returns a single point representing the + * sample. The sps can be any positive real number and does not need + * to be an integer. The filter taps must also be specified. The taps + * are generated by first conceiving of the prototype filter that + * would be the signal's matched filter. Then interpolate this by the + * number of filters in the filterbank. These are then distributed + * among all of the filters. So if the prototype filter was to have 45 + * taps in it, then each path of the filterbank will also have 45 + * taps. This is easily done by building the filter with the sample + * rate multiplied by the number of filters to use. * - * The number of filters can also be set and defaults to 32. With 32 filters, you get a - * good enough resolution in the phase to produce very small, almost unnoticeable, ISI. - * Going to 64 filters can reduce this more, but after that there is very little gained - * for the extra complexity. + * The number of filters can also be set and defaults to 32. With 32 + * filters, you get a good enough resolution in the phase to produce + * very small, almost unnoticeable, ISI. Going to 64 filters can + * reduce this more, but after that there is very little gained for + * the extra complexity. * - * The initial phase is another settable parameter and refers to the filter path the - * algorithm initially looks at (i.e., d_k starts at init_phase). This value defaults - * to zero, but it might be useful to start at a different phase offset, such as the mid- - * point of the filters. + * The initial phase is another settable parameter and refers to the + * filter path the algorithm initially looks at (i.e., d_k starts at + * init_phase). This value defaults to zero, but it might be useful to + * start at a different phase offset, such as the mid- point of the + * filters. * - * The final parameter is the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from 0. Constraining the rate can help - * keep the algorithm from walking too far away to lock during times when there is no signal. + * The final parameter is the max_rate_devitation, which defaults to + * 1.5. This is how far we allow d_rate to swing, positive or + * negative, from 0. Constraining the rate can help keep the algorithm + * from walking too far away to lock during times when there is no + * signal. * */ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h index 200adee3d..6b75c5859 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h @@ -41,6 +41,7 @@ class gri_fft_complex; * input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger down- * sampling (decimation) with a polyphase filterbank. The first input diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h index d2efc591a..3dc52938e 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h @@ -39,6 +39,7 @@ class gr_fir_ccf; * gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger up- * sampling (interpolation) with a polyphase filterbank. The first diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h index f5b1cbb94..7e3700921 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -42,6 +42,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk */ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator |