Recently i published the first of a series of posts on radio listening, and while this is not technically part 2 yet, i figured something out that is quite important to my workflow of recording and then processing radio input.
i own a RTL SDR Blog V4 dongle, which is based on
the RTL2832U chip. The drivers you install come with a set of
binaries, including rtl_sdr
, which
lets you record a band of the spectrum into a raw data file. Later on, because i
use SDR++, i would ideally want to open those files
and process them with the UI in that program. SDR++ (or sdrpp
) is also capable
of recording raw bands of the spectrum into what it calls baseband files, but
it cannot immediately open raw files recorded from rtl_sdr
. The reason for
that is that rtl_sdr
outputs RAW "IQ" information, whereas sdrpp
reads "IQ"
information in a WAV file.
My understanding of the technical aspects of IQ data, by me, an idiot
For reasons that are too complex (lol) to get into and that are also somewhat starting to fade from my memory, an alternating electrical signal can be expressed as a complex number: it has a magnitude, a period as a function of time, and an initial shift. Complex numbers, represented in their more "vector" or "algebraic" form are essentially two numbers in a trench coat: one is real (let's call it Q), and one is "imaginary" (let's call it I). When reading from the RTL2832U chip, you get two samples, 8 bit each, for I then Q. What `rtl_sdr` does, roughly, after tuning, is reading a given number of those samples and writing them in a file, which is then *RAW IQ* (as in, just wrote the I and Q parts one after the other in a big sequence, no headers, no nothing).
What SDR++ and other tools will record and read, however, is WAV IQ, which is to say, IQ data that has been de-interleaved, processed into the appropriate number size for the program (SDR++ lets you choose, and GnuRadio uses 32-bit floating point numbers). How exactly the signal is created remains somewhat of a mystery to me at this point. My best guess is that the conversion process involves taking in the decoded complex number from IQ data and generating the corresponding input signal, and then mushing them all together. Exactly how that works? When i figure it out, i will update this part.
There is exactly one workflow where i would, ideally, not want to have to be on the UI and click a button to record on SDR++ at a precise time and again to stop it: satellite listening. Whether it be for catching SSTV from the ISS, LRPT from the Russian Weather Satellites, i do not want to get up at 7AM to do it. Or, rather, it is highly inconvenient that it's always the ideal time. i also recently discovered that, at least for SSTV from the ISS, a straight dipole is often fine.
So how about slapping a bunch of sleep
commands, a bit of CLI nonsense, and
get this recorded and opened in SDR++ later so i can actually record the track i
want? Well, reviewing the command i use for rtl_sdr
:
rtl_sdr -f 145.8e6 -s 60K -g 20 iq-145800000Hz.raw
Summing up what is going on:
-f 145.8e6
: tune to 145.8MHz-s 60K
: record a bandwidth of 60K.rtl_sdr
uses the term "sample rate" which is also used by SDR++; what it actually means is how many samples are taken around the tuning frequency, or how big the band you're seeing "at once" is-g 20
: set the gain to 20 on the dongle<file name>
: pretty explicit; this one includes the frequency, for a reason i will explain later
Now, i use sox
to process the raw data into a WAV container:
sox -t raw -r 200k -b 8 -e unsigned-integer iq-145800000Hz.raw \
-t wav -r 200k -b 16 iq_145800000Hz.wav
There is probably an equivalent for FFMPEG, but i haven't tested that yet.
What it does is, roughly:
- There is an input from file
iq-145800000Hz.raw
:- The bit per sample (
-b
) is 8 - There are
200k
samples per slice of input - The type is
raw
data - The integer type is
unsigned
(here for 8 bits:0-255
)
- The bit per sample (
- The file created as an output,
iq-145800000Hz.wav
is:- Of type
wav
, - Has a sample rate of
200k
- An integer type of
16
bits (you can change this part depending on what you use in SDR++)
- Of type
Now, opening the resulting file iq_145800000Hz.wav
with SDR++ should show
you exactly the recording you plan to use.
And why the frequency in the file name? Well, see, SDR++ needs to know a center frequency to show you on the tuner, and while it does not actually matter when reading a file (the waterfall will just display the entire band and let you zoom in on it and use other tuners like radio, NOAA, METEOR, etc. on parts of it), it is good to now where you are tuned in if you have for example bookmarks and such.
So how does SDR++ determine the center frequency from the WAV file? Easy, the fucking file name.
i kid you not; i spent a solid 20 minutes digging in the code only to figure out
that getFrequency
searches the filename with a regex to figure out the first
occurrence of [0-9]+Hz
, and returns 0Hz otherwise. That is actually a smart
choice considering the limitations of WAV files (i.e. you cannot use custom
labels for metadata and they are generally annoying to use in general).