The format and parsing of GNU Radio data acquisition files with COMPLEX data type
Share
GNU Radio COMPLEX IQ File Format and Parsing
GNU Radio allows SDR developers to store frequency-translated baseband signals from USRP devices into files, or replay pre-generated signals back to RF hardware. Understanding the COMPLEX IQ file format is essential for offline analysis, signal reconstruction, and waveform generation.
0 Introduction
Using GNU Radio, intermediate-frequency (IF) or baseband signals generated by USRP devices can be saved directly to files. These files may later be analyzed using external tools or regenerated as modulated signals for transmission. Therefore, understanding the structure and characteristics of GNU Radio COMPLEX files is critically important for SDR experimentation.
1 GNU Radio File Type Configuration
GNU Radio supports multiple data formats for both File Sink and File Source blocks. The most commonly used format is COMPLEX , representing complex baseband samples.

In this format:
- Each sample consists of an I (In-phase) component
- And a corresponding Q (Quadrature) component
- Both stored as 32-bit floating-point (float) values


Once the TYPE is set to COMPLEX, the file generated by File Sink can be directly reused by File Source. The file extension itself is not important.
2 COMPLEX File Format Analysis
By visualizing captured data with tools such as Audacity , the following characteristics can be observed: 
-
Two interleaved waveforms corresponding to I and Q channels - Each value is a float within the range [-1.0, 1.0]
This leads to the following inferred storage layout:
FLOAT_I0, FLOAT_Q0,
FLOAT_I1, FLOAT_Q1,
FLOAT_I2, FLOAT_Q2,
FLOAT_I3, FLOAT_Q3,
...
Each COMPLEX sample therefore occupies exactly 8 bytes (2 × 32-bit floats).
3 Parsing COMPLEX Files Using C
Based on the format analysis, parsing can be implemented easily in C. The following example reads a COMPLEX file generated by GNU Radio and extracts I/Q samples.
#define BUFF_SIZE (1024*1024*200)
unsigned char buff[BUFF_SIZE];
int buff_size;
int file2buff(char *fn, unsigned char *buff, int buff_len) {
FILE *fp;
int size;
fp = fopen(fn, "rb");
if (fp == NULL) {
printf("cannot read file\n");
getchar();
}
size = fread(buff, 1, buff_len, fp);
fclose(fp);
return size;
}
Since the file data is stored as interleaved floats, we can reinterpret the buffer using a float pointer:
int main() {
float *pfloat = (float*)buff;
int i, t;
int buff_size_in_float, buff_size_in_complex;
buff_size = file2buff("ring_recoder", buff, BUFF_SIZE);
buff_size_in_float = buff_size / sizeof(float);
buff_size_in_complex = buff_size_in_float / 2;
for (i = 0; i < buff_size_in_float; i += 2) {
if ((pfloat[i] > 0.5) || (pfloat[i+1] > 0.5)) {
printf("start address %d\n", i / 2);
break;
}
}
t = 0;
for (; i < buff_size_in_float; i += 2) {
printf("%f,%f\n", pfloat[i], pfloat[i+1]);
t++;
if (t == 300) break;
}
}
This program locates the first sample whose amplitude exceeds 0.5 and outputs the next 300 IQ samples.
4 Compilation and Experimental Verification
The code can be compiled using any standard C compiler. After compilation, output is redirected to a CSV file:
complex2csv.exe > aaa.csv
The generated CSV file can be imported into spreadsheet software to plot waveforms and compare them with Audacity visualizations. 

5 Result Comparison
The plotted waveform extracted from the CSV file exactly matches the waveform observed in Audacity at the corresponding sample index. This confirms the correctness of the parsing approach. 



6 Conclusion
- GNU Radio COMPLEX files store interleaved float I/Q samples
- Each sample range is limited to [-1, 1]
- Files use little-endian format on most modern CPUs (x86, ARM)
- No metadata (RF frequency, sample rate) is included
For clarity, it is recommended to encode parameters in filenames (eg, ring_recorder.RF433M.IF1M ). COMPLEX files generated this way can be directly reused as GNU Radio File Source inputs to transmit custom IQ waveforms via USRP devices such as the B210.
