Filter in rational resampler

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

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
[email protected]
Discuss-gnuradio Info Page

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


Marcus L.
Principal Investigator
Shirleys Bay Radio Astronomy Consortium

On Thu, 2014-07-31 at 12:01 -0400, [email protected]
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

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

On Oct 27, 2014 6:36 PM, “Jeff L.” [email protected] 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

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

To: GNURadio 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/

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. :stuck_out_tongue:

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

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:
Introduction to Signal Processing
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

-----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:
Introduction to Signal Processing
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-----