Hi Tom,

Was I supposed to know somehow that the rational resampler includes

the necessary aliasing filters? That’s not meant to be a sarcastic

question - I’m trying to figure out where to look in the documentation

for these sorts of things.

I think it’s actually a good question! It’s always better to ask how you

can figure out something rather then just relying on pre-made solutions.

I don’t have GRC to hand, but I don’t remember it being in the

documentation for the block.

GRC docs typically only contain a small piece of the information in the

full doxygen.

So the point here is that the doxygen [1] does mention it builds a

rational resampling polyphase FIR out of the taps that you need to

supply.

Also, it quite explicitely says that you need to use a filter that will

suppress the aliases or images (depending on what’s higher, decimation

or interpolation).

So the thing that’s happening here is that you want to achieve a M/N

resampling; you actually[2] do the following:

—>[??? M] --> [??? N] -->

So you pad 1 input sample to M “intermediate” samples by simply adding

M-1 zeros after each sample, and then you throw away N-1 out N samples.

Simple as that? Not really. First of all, as you’ve noticed, the M

interpolation introduces aliases.

So assume the input spectrum might look like this:

input spectrum

Obviously, we’re wasting sample space here. So having a sharp look, we

determine that this only needs 3/5 of the original bandwidth; hence M=3,

N=5.

What we want to have looks like:

Wanted output spectrum

I.e. we want spectrum that as closely fits the full Nyquist bandwidth,

but doesn’t “overlap” the edges, ie. there’s no aliasing at the edges.

Notice that at the band edges, the spectral power goes down by > 20dB.

What we actually get if we just interpolate and decimate (GRC file here

[3]) however looks like

actual output spectrum

The output spectrum is a obviously continuous piece of overlaid signal;

if you look closely, you’ll notice that these two center peaks seem to

re-appear at ~±7kHz. Something is wrong here.

But it’s not really surprising: If you take a look at the intermediate

spectrum [4], there’s the 3 repetitions we’d expect from interpolation.

Now, mentally cut the intermediate spectrum in five equally wide parts,

and mentally shift them the four outer ones over the center one. That

aliasing is what ruins our signal!

That demonstrates what’s necessary to get rid of this: in the

intermediate spectrum, we’ll need to suppress everything that isn’t in

the “middle” zone. Doing that yields [5], which is what we wanted.

Here, M < N, and that’s why you need an anti-alias filter; but the same

M repetitions appear for any M, and the same “cut up and overlay” logic

applies to any N; this explains why for M > N, you need an anti-imaging

filter.

The point here is, though, that you just really need one filter here,

and it needs to be the stricter one of both (cutoff at

decimation/interpolation or at interpolation/decimation). Of course, if

you follow up with another filter that already fulfills that, you might

as well just interpolate that filter to match the M*input sample rate,*

and use that. Due to [2], rational resamplers don’t actually run at

Minput sample rate (that would be computationally terrible!), so the

resulting filter might actually be not much worse than the minimal

filter that you’d use just to guarantee proper resampling, but you might

just save a whole separate filter.

Best regards,

Marcus

[1]

https://gnuradio.org/doc/doxygen/classgr_1_1filter_1_1rational__resampler__base__fff.html#details

[2] Note that there’s polyphase trickery that /mathematicall//y/ does

the same as just actually adding the zeros, and throwing away samples,

but without doing the unnecessary operations (who needs samples that get

thrown away? Who needs to multiply something with 0 to then add it up?)

[3]

https://gist.github.com/marcusmueller/24d64e67709fafbf036f#file-spec-grc

[4]

https://gist.github.com/marcusmueller/24d64e67709fafbf036f#file-nofilter-png

[5]

https://gist.github.com/marcusmueller/24d64e67709fafbf036f#file-proper-png