I’ve been experimenting a bit with Software Defined Radio, and specifically the gqrx and gnuradio tools. One thing that took me longer than expected was figuring out how to work with the .raw files that gqrx can create when using the I/Q (In-Phase/Quadrature components) recorder – compared to .wav files (for which a plethora of tools exist), the .raw I/Q files record the entire spectrum visible in the waterfall window.
My basic requirement was extracting a few seconds worth of data from a longer recording to speed up my development cycle in gnuradio. I suspect many people use MATLAB or Octave for these kinds of things, but I thought there must be a simpler way.
I came across the following useful snippets while researching how to do this:
- According to this thread on discuss-gnuradio, the files contain “cf32, pairs of 32-bit floats representing I and Q.”
- Apparently, they are compatible with gnuradio’s file source/sink
- This gnuradio FAQ entry on reading file sink-produced files suggests using scipy.fromfile to read the data.
This is a good start, and I can now pull out the data I’m interested in using something like:
import matplotlib.pyplot as plt import scipy # gqrx_yyyymmdd_hhmmss_freq_samplerate_fc.raw input_filename = "gqrx_20180410_201900_123430000_1800000_fc.raw" output_suffix = "subset" sample_rate = input_filename.split('_') with open(input_filename, 'rb') as f: x = scipy.fromfile(f, dtype=scipy.complex64) len(x) # Look at the data plt.plot(abs(x)) plt.show()
This produced a plot that looked something like this:
The signal of interest is clearly visible in the centre of the plot. This can now be extracted crudely using something like this:
# Determine region of interest & extract start = int(2.8e7) end = int(4.2e7) roi = x[start:end]
Double-check your orders of magnitude 🙂
Figuring out the writing part took a bit of time and trial and error, but eventually I discovered that the following worked:
output_filename = input_filename.replace(".raw", output_suffix + ".raw") with open(output_filename, 'wb') as f: f.write(roi.tobytes())
It’s worth pointing out that gqrx determines the length of the file using the following code:
rec_len = (int)(info.size() / (sample_rate * bytes_per_sample));
, where sample_rate comes from the file name and bytes_per_sample is fixed at 8. This needs to give a sensible result.
Now I can use my smaller file in gnuradio and gqrx!
Please do leave a comment if this helped you, you know of a any other resources which discuss basic I/Q file editing, spot any mistakes or if you have anything else to add!