Processing expectations

I’m brand new to SDR and I’m just trying to calibrate my expectations of
what will be possible in real time. I’m hoping someone here can give me
a
pointer or two.

I’m running GNU Radio 3.7.2 on Ubuntu 14.04, having installed from the
Ubuntu repositories. The machine I’m using has an Intel Core i5-2520M
running at 2500MHz.

I’m constructing flowgraphs in GRC and using an RTL-2832U-based USB
dongle
as a receiver.

I’ve built a fairly simple broadcast FM stereo receiver as an example.
It
has the following components:

  • RTL-SDR source (768k sample rate).
  • Low pass filter (768k sample rate, 96k cutoff, 4k transition)
  • Rational resampler (4x decimation)
  • WBFM receiver (quadrature rate 192k)
  • Low pass filter (1x decimation, 192k sample rate, 15k cutoff, 2k
    transition)
  • 2x Band pass filter (1x decimation, 192k sample rate, differing cutoff
    and transition)
  • Multiply
  • Low pass filter (192k sample rate, 15k cutoff, 2k transition)
  • Add, subtract
  • 2 x rational resampler (4x decimation)
  • Audio sink (sample rate 48k)

My system is not able to run this in realtime, producing regular
underruns
(about two per second). Decreasing the receiver sample rate to 384k and
decreasing the decimation factor in the first resampler to 2 allows it
to
run in without underruns, from which I deduce that the CPU is right on
the
edge of being able to process the flowchart in realtime.

Are my expectations of what I’ll be able to do in realtime unreasonably
high? Is there something I’m missing, that I can do to make this run
much
faster?

Thanks,
Tom

With a processor like that, you should be able to clock your dongle at 2
Msps all the time, and then resample. I remember faintly that there was
some issue with rtlsdr dongles not working will with lower sampling
rates, maybe that’s what it is.

On a side note, this allows you to offset-tune and avoid DC spurs, which
can be pretty ugly on the RTLSDR.

M

You may also want to have a look at
http://stats.gnuradio.org/
To get a feel for how fast different sdr kernels run on different
processing platforms

Tim

On Fri, Aug 7, 2015 at 2:47 PM, Tom C. [email protected] wrote:

You’ve just strung together 5 filters in a row here. You can do your
decimation step in the low pass filter, and the WBFM stage has a filter
in
it, as well. That 4k transition in the initial LPF at 768 kHz will make
for
a long filter; if that’s also doing 4x down sampling, you’ll remove a
lot
of processing requirements there.

Think about all of these filter stages and how you might be able to
combine
them and reduce their overall power requirement.s

  • Multiply
  • Low pass filter (192k sample rate, 15k cutoff, 2k transition)
  • Add, subtract
  • 2 x rational resampler (4x decimation)
  • Audio sink (sample rate 48k)

Again, you can do the resampling and LPF together; that resampler
implements its own filter. You can also integrate the multiply stage
into
the LPF by setting the gain of the taps to your multiply value.

Thanks,
Tom

It sounds like you’re close to what you need to get this working. Just
think more about the filter stages and values. Use gr_filter_design to
plot
them and see how many taps you’re using to help you reduce the
computational requirements.

Tom

Many thanks to all who responded here. As Martin remembered faintly,
the
RTL-SDR dongle does not work well at low sample rates, and it gives
considerably better reception to run it at (eg) 1.536 Msps and then
resample it to 384 ksps than to use 384 ksps from the start.

Thanks to Tom for pointing out the ways of combining resampling and
filtering. 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 don’t have GRC to hand, but
I
don’t remember it being in the documentation for the block. The
documentation for the rational_resampler_base_fff class sort of hints at
it
without saying as much, and it took me quite a while to figure out where
to
find even that.

At any rate, I’ve got the thing running in realtime, and performing
quite
well after replacing the crummy antenna provided with the dongle with a
VHF
TV antenna pointed in the right direction.

Thanks again,
Tom


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Hi Tom,

I just had to look this up. If you’re in GRC, you have “rationale
resampler” and “rational resampler base”; they do basically the same,
but if you use the one without “base”, and don’t specify the taps, GNU
Radio just automatically designs a filter that avoids all aliasing and
imaging, which is done with a python wrapper around the C++
rational_resampler_base_xxx’s make function[1]. That’s pretty handy in
most use cases, but not too much if you want your own filter for some
reason.

If you’re using the “base” variant, you /must/ specify the taps
yourself, because you directly invoke the C++ block’s maker. If you go
ahead and just use “[1.0]” as taps, you get the aliased results from my
pictures.

So if you happen to /want /to specify the taps, because you can
integrate the functionality of a downstream filter into the resampler to
save CPU cycles, it doesn’t make a difference which block you use.

Best regards,
Marcus

[1]
https://github.com/gnuradio/gnuradio/blob/master/gr-filter/python/filter/rational_resampler.py

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 Minput sample rate,
and use that. Due to [2], rational resamplers don’t actually run at
M
input 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

Hi Tom,

added the block, opened the block properties, had a look at the id; I
knew that these kind of blocks live within gr-filter, so

cd gr-filter
vim grc/rational.grc ##that’s where the block definitions for GRC
reside

found out that the non-base variant used rational_resampler_$(type), but
I had a look into filter, and only found rational_resampler_base_*; so I
guessed it was a python file.
Went into python/filter, and opened rational_resampler.py, based on it
being the only python file that was possibly relevant here.

You know, that’s really unintuitive, and I think we’ll need some helpers
or better documentation that makes finding such things easier.

Best regards,
Marcus

On Mon, 10 Aug 2015 at 13:14 Marcus Müller [email protected]
wrote:

If you’re using the “base” variant, you must specify the taps yourself,
because you directly invoke the C++ block’s maker. If you go ahead and just
use “[1.0]” as taps, you get the aliased results from my pictures.

So if you happen to *want *to specify the taps, because you can integrate
the functionality of a downstream filter into the resampler to save CPU
cycles, it doesn’t make a difference which block you use.

Ah, I see. Many thanks for taking the time to explain this. Where did
you
look to find out that ‘rational resampler’ block does an automatic
filter
design for you?

Regards,
Tom

With GNU Radio, never feel stupid :wink:
Documentation did turn out quite great in most places, but as soon as
you want to figure out what happens inside, you’re pretty much on your
own, often. grep/ack/git grep is a constant friend, but it’s not always
easy to figure out how stuff works internally. There’s a delicate
balance between writing code and documenting that outside of the code
itself, especially since GNU Radio has quite a lot of contributors.

Cheers,
Marcus

I see. I don’t feel quite so stupid for having not found it myself,
now!

Okay. Time to fork on github, methinks, and start contributing
documentation patches.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs