This receives IQ data streamed from an RT-SDR dongle over TCP (using rtl-tcp) and plots a PSD and Spectrograph. Implemented in both python and C++. FFT is calculated using Numpy and KissFFT respectively.
Fc=100MHzFs=2.4GHz
-
Clone this repo to both the server (the machine with the RTL SDR USB dongle) and client (can be the same machine)
-
Install
rtl-sdron the server:sudo apt update sudo apt install rtl-sdr librtlsdr-dev -
Disable the default DVB USB dongle driver:
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf -
Run
scripts/restart_rtl_server.shon the server. Check for errors. -
Run one of the examples on the client.
NOTE: You can stop the RTL server with kill $(pgrep -a rtl_tcp)
Post processing of the FFT bins with a hann window will improve the clarity of the PSD plot. Without the window each bin's sinc-shaped response has slowly-decaying sidelobs, so energy from a strong signal smears into neighbouring bins. Multiplying each bin with the window increases the side-lobe decay which allows the the true shape of the spectrum to come through more clearly. You may need to zoom into see the difference.
| Without Hann Window | With Hann Window |
|---|---|
![]() |
![]() |
A standard periodogram provides an inconsistent estimate with high variance, making the resulting spectrum look jagged and noisy. We use Welch's method to reduce the random "noise" and variance inherent in standard periodograms by
- Splitting the signal into overlapping N-sample segments (50% overlap)
- Calculate the average power spectra for each bin across the whole FFT range.
More segments equals less noisy noise floor, at the cost of frequency resolution (bin width becomes sampleRate/N instead of sampleRate/n).
Note: --nfft N enables Welch's method.
| Without Welch's Method | With Welch's Method |
|---|---|
![]() |
![]() |
- Receive the IQ samples from the RTL SDR at an offset so to avoid the SDR's DC spike.
- Mix it down to baseband to remove the offset.
- Use a low-pass filter to isolate the FM channel and reject everything else
- Decimate down to a sane rate for demodulation
- FM demodulate
- Resample from the demod rate down to a standard audio rate
- Save as raw float32 PCM so it can be played back




