# Filter in rational resampler

**URL:** <https://www.ruby-forum.com/t/filter-in-rational-resampler/231257>\
**Category:** GNU Radio\
**Created:** [July 30, 2014, 6:43pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257 "2014-07-30T18:43:20Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [July 30, 2014, 6:43pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/1 "2014-07-30T18:43:20Z")

</div>

Hello,

I was studying the code of the rational resampler block in  
gnuradio/gr-filter/pythoin/rational\_resampler.py and I have a doubt  
about the low pass filter generated by the design\_filter() function.

It seems that the generated filter does not take into account the  
decimation factor. Is that correct? I don’t see how this may result in  
the correct anti-aliasing filter when it is applied by  
rational\_resampler\_base\_xxx.

Can someone point me to a relevant explanation?

Thanks a lot. Cheers,  
Daniele

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [July 30, 2014, 6:45pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/2 "2014-07-30T18:45:07Z")

</div>

On 07/30/2014 12:42 PM, Daniele N. wrote:

> Can someone point me to a relevant explanation?
> 
> Thanks a lot. Cheers,  
> Daniele
> 
> * * *
> 
> Discuss-gnuradio mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [Discuss-gnuradio Info Page](https://lists.gnu.org/mailman/listinfo/discuss-gnuradio)

The filtering happens _before_ resampling. It has to, or you end up  
with aliases.

–  
Marcus L.  
Principal Investigator  
Shirleys Bay Radio Astronomy Consortium

> **[Live Draw HK Tercepat | Result HK | HK Pools | Live HK | HK Prize Hari Ini](https://www.sbrac.org)**
>
> Temukan live draw hk tercepat melalui halaman hk pools yang resmi dan dapatkan result hk prize melalui live hk secara langsung di situs kami.

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 2:44pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/3 "2014-10-28T14:44:05Z")

</div>

On Thu, 2014-07-31 at 12:01 -0400, [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> about the low pass filter generated by the design\_filter() function.
> 
> It seems that the generated filter does not take into account the  
> decimation factor. Is that correct? I don’t see how this may result in  
> the correct anti-aliasing filter when it is applied by  
> rational\_resampler\_base\_xxx.
> 
> Can someone point me to a relevant explanation?
> 
> Thanks a lot. Cheers,  
> Daniele

Daniele,

I just had occasion to use the rational resampler for a 25 Ksps → 16  
Ksps resampling and low-pass filtering all in one step, with a LPF that  
cut off frequencies higher than 3000 Hz. I started by using this  
expression for the taps, following the filter design in  
gr-filter/python/rational\_resampler.py:

filter.firdes.low\_pass(16.0, 16000.0, 3250.0/16.0, 500.0/16.0,  
filter.firdes.WIN\_KAISER, 5.0)

That filter only includes the interpolation factor, 16.0, and seemed to  
do the wrong thing. The FFT scope showed the rolloff started at around  
~4700 Hz, about 25/16 \* 3000 Hz.

This expression for the taps, which included the decimation factor of  
25.0, appeared to do the right thing:

filter.firdes.low\_pass(16.0, 16000.0, 3250.0/25.0, 500.0/25.0,  
filter.firdes.WIN\_KAISER, 5.0)

Can someone else take a closer look at  
gr-filter/python/rational\_resampler.py and confirm it is doing the wrong  
thing?

Regards,  
Andy

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 4:40pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/4 "2014-10-28T16:40:27Z")

</div>

On 10/27/2014 04:40 PM, Andy W. wrote:

> > 
> 
> Can someone else take a closer look at  
> gr-filter/python/rational\_resampler.py and confirm it is doing the wrong  
> thing?
> 
> Regards,  
> Andy

It looks like the default filter is only valid where interp \> decim, and  
it’s not really meant to have an arbitrary cutoff. As Daniele pointed  
out, decim is not taken into account.

I think that ‘interpolation’ in design\_filter() should be replaced with  
'max(interpolation,decimation). If taps are supplied by the caller, it  
needs to understand how the taps will be used.

Andy, to mimic design\_filter, you’d need to do:

low\_pass(16.0, 25000.0, 3250.0, 500.0, …)

Not that I know if that’s right, but that’s what design\_filter() does.

- Jeff

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 6:02pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/5 "2014-10-28T18:02:49Z")

</div>

On Oct 27, 2014 6:36 PM, “Jeff L.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > Subject: [Discuss-gnuradio] Filter in rational resampler  
> > > rational\_resampler\_base\_xxx.  
> > > Ksps resampling and low-pass filtering all in one step, with a LPF that  
> > > cut off frequencies higher than 3000 Hz. I started by using this  
> > > expression for the taps, following the filter design in  
> > > gr-filter/python/rational\_resampler.py:
> > 
> > ```
> > filter.firdes.low_pass(16.0, 16000.0, 3250.0/16.0, 500.0/16.0,
> > 
> > ```

filter.firdes.WIN\_KAISER, 5.0)

> > That filter only includes the interpolation factor, 16.0, and seemed to  
> > do the wrong thing. The FFT scope showed the rolloff started at around  
> > ~4700 Hz, about 25/16 \* 3000 Hz.
> > 
> > This expression for the taps, which included the decimation factor of  
> > 25.0, appeared to do the right thing:
> > 
> > ```
> > filter.firdes.low_pass(16.0, 16000.0, 3250.0/25.0, 500.0/25.0,
> > 
> > ```

filter.firdes.WIN\_KAISER, 5.0)

> It looks like the default filter is only valid where interp \> decim, and  
> it’s not really meant to have an arbitrary cutoff. As Daniele pointed  
> out,  
> decim is not taken into account.
> 
> I think that ‘interpolation’ in design\_filter() should be replaced with  
> 'max(interpolation,decimation). If taps are supplied by the caller, it  
> needs to understand how the taps will be used.
> 
> Andy, to mimic design\_filter, you’d need to do:
> 
> low\_pass(16.0, 25000.0, 3250.0, 500.0, …)
> 
> Not that I know if that’s right, but that’s what design\_filter() does.

Andy, ignore that last part. Your params are right and that filter  
actually  
makes sense. The filter is applied after interp and before decim, which  
is  
not obvious from the API.

- Jeff

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 9:18pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/6 "2014-10-28T21:18:37Z")

</div>

From:  
Jeff L.  
Subject:  
Re: [Discuss-gnuradio] Filter in  
rational resampler  
Date:  
Tue, 28 Oct 2014 04:31:30 -0400

> > > > To: GNURadio [address@hidden](mailto:address@hidden)  
> > > > It seems that the generated filter does not take into account the
> > > 
> > > ```
> > > filter.firdes.low_pass(16.0, 16000.0, 3250.0/16.0,
> > > 
> > > ```
> > > 
> > > 25.0, appeared to do the right thing:  
> > > Regards,  
> > > Andy
> > 
> > It looks like the default filter is only valid where interp \> decim,  
> > and it’s not really meant to have an arbitrary cutoff. As Daniele  
> > pointed out, decim is not taken into account.
> > 
> > I think that ‘interpolation’ in design\_filter() should be replaced  
> > with 'max(interpolation,decimation).

Right, or something similar. Basically design\_filter() should design  
the narrower of the required anti-image postfilter or anti-alias  
prefilter.

Section 12.6 on page 691 of this book has a nice explanation:  
[http://www.ece.rutgers.edu/~orfanidi/intro2sp/](http://www.ece.rutgers.edu/~orfanidi/intro2sp/)  
[http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf](http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf)

I’ll submit a bug to the issue tracker.

> Andy, ignore that last part. Your params are right and that filter  
> actually makes sense.

Yeah. I experimentally knew what I had was right. I just needed to go  
back and confirm it, by reading my Orfanidis book to refresh my memory  
on what I learned over 17 years ago. 😛

FWIW, after the upsampling, for my specific case, the Fs of the filter  
is 16 \* 25000 sps. So to get my desired 3000 Hz cutoff, which is  
narrower than both the required anti-image and anti-alias filter  
cutoffs, I should have used:

```
 low_pass(16.0, 16.0*25000.0, 3250.0, 500.0, ...)

```

but

```
 low_pass(16.0, 16000.0, 3250.0/25.0, 500.0/25.0, ...)

```

is equivalent.

> The filter is applied after interp and before decim, which is not  
> obvious from the API.
> 
> - Jeff

Thanks for looking at this!

Regards,  
Andy

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 9:29pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/7 "2014-10-28T21:29:58Z")

</div>

On 10/28/2014 07:47 AM, Andy W. wrote:

> > > > >
> > 
> > result in
> > 
> > > > ```
> > > > filter.firdes.low_pass(16.0, 16000.0, 3250.0/25.0,
> > > > 
> > > > ```
> 
> prefilter.
> 
> Section 12.6 on page 691 of this book has a nice explanation:  
> [http://www.ece.rutgers.edu/~orfanidi/intro2sp/](http://www.ece.rutgers.edu/~orfanidi/intro2sp/)  
> [http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf](http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf)
> 
> I’ll submit a bug to the issue tracker.

Andy,

I already put a bug report in last night. Fix default filter, plus maybe  
documentation of what user taps really means.

- Jeff

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [October 28, 2014, 9:31pm UTC](https://www.ruby-forum.com/t/filter-in-rational-resampler/231257/8 "2014-10-28T21:31:45Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA512

On 28.10.2014 14:47, Andy W. wrote:

> Right, or something similar. Basically design\_filter() should  
> design the narrower of the required anti-image postfilter or  
> anti-alias prefilter.
> 
> Section 12.6 on page 691 of this book has a nice explanation:  
> [http://www.ece.rutgers.edu/~orfanidi/intro2sp/](http://www.ece.rutgers.edu/~orfanidi/intro2sp/)  
> [http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf](http://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf)
> 
> I’ll submit a bug to the issue tracker.  
> So, I’m not mad, and understand this problem right (see my message  
> without answer with subject “rational\_resampler vs pfb\_arb\_resampler  
> filter design – why such strange cut frequencies in both cases?”),  
> good.

* * *

// Black Lion AKA Lev Serebryakov  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v2.0.22 (MingW32)

iQJ8BAEBCgBmBQJUT4VQXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w  
ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXRGOTZEMUNBMEI1RjQzMThCNjc0QjMzMEFF  
QUIwM0M1OEJGREM0NzhGAAoJEOqwPFi/3EePlOkP/2bV9N3BYUv3PD8lkw+p9fe9  
HQ1p9mnwuKOkhOulZK4bA2Nd00/KsnpsBQ1kNtSdCiH5ikkbvIXNgPvSjXi/5U5I  
0kFypk75TAI7Lubvzv9+uoIP3N2CenpbfYv9d1UhYoZA+agdk3aO4vwi1HpcmVwP  
DG1SOmpmqNFPh0cVEaF35AuOCFdm1ieLwHQjloBA1uh8IyeMNvpons7upPVmUWOq  
Bb2NyuidftOzc8zDtw/GJ2rDMp/MAJuZthoRKE9wZ+3IP7ellec0n+B6bNCnqGAR  
aP094kdYgRkd7ydDX9lXRuE3ponSgOILbYQfKrdYtIxfEiTBVgyr6VxNOEXMt5jx  
QOqSx1/GT9i7j94mZwOLGU03G2DrgzhhTBJLK9EyLTrOrGb63oa5vUn8Qil3cQna  
F3aDEV/x5MwuN/Yhq8h6Vx6uvqIrsoke90kHty0bmuczk4DTMeF0Iy7kAYHKNhq3  
jl/urV4eKGYBFjFUTUGFW93BNXjNUsiFM1kMNAmXRbvSlMr33kKAso4tHl+1SmSn  
8uj7rVbNrJNa8Cn7Y96GcccVGDpKENXslNj0HtpL+86VhyR9PrBytesBFJVbWFh6  
nh3mhD2NZXCEA4T0fKRZNiD2+Sc2M1nDGFrueyD3yfzYheTMW4IbOIKZK9/tDWxa  
c5RMvdetxkJb0xE1LMxv  
=bZiC  
-----END PGP SIGNATURE-----
