Field Guide · term

Also known as: cfile, .cfile, complex float file

A cfile is GNU Radio’s raw IQ recording format: a headerless stream of interleaved little-endian 32-bit float I and Q values, eight bytes per complex sample.1 The c stands for complex and the format is nothing more than what a GNU Radio File Sink writes when fed a complex stream — which is exactly why it became the de-facto lossless capture format, and the format GopherTrunk replays via -format f32.

I₀ float324 bytes LE Q₀ float324 bytes LE I₁ float32 Q₁ float32 · · · 8 bytes = one sample
A cfile is pairs of little-endian float32 values, I then Q, eight bytes per complex sample, with no header.

How it works

The layout is deliberately trivial. Each I and each Q is one IEEE-754 single-precision float in little-endian byte order; they alternate I, Q, I, Q for the length of the recording. There is no magic number, no header, no embedded sample rate — the file is pure payload. That means, as with any raw IQ file, you must supply the sample rate and centre frequency separately: GNU Radio flowgraphs and every replay tool take them as parameters. Amplitudes are conventionally normalised to roughly ±1.0, the range GNU Radio sources emit, though nothing enforces it.

The float32 choice trades size for fidelity. At eight bytes per sample a cfile is four times larger than an 8-bit cu8 capture, but it preserves the full dynamic range of the samples and needs no scaling before DSP, since the values are already the floating-point form the math operates on. This makes cfiles the natural intermediate format for analysis and testing, where disk is cheap and losing bits is not acceptable.

Relevance to SDR

The cfile is the workhorse of GNU Radio experimentation: drop a File Sink after a source to record, drop a File Source to replay, and any flowgraph becomes an offline experiment. Tools across the ecosystem — Inspectrum, gr-based decoders, and analysis scripts in NumPy (numpy.fromfile(..., dtype=numpy.complex64)) — read the same bytes, because complex64 in NumPy is precisely two interleaved float32 values. The SigMF standard’s cf32_le datatype describes exactly this layout, so a cfile is a SigMF data file waiting for a sidecar.

GopherTrunk consumes cfiles directly. Its offline engine’s -format f32 decoder (also spelled float32 or cfile) reads interleaved little-endian float32 into the same production receiver and control-channel pipelines the live daemon runs, so a lock on a replayed cfile implies a lock on air, and a failure makes the capture a reproducible fixture. This is the format the project’s DSP and replay guidance refers to when it talks about replaying .cfile captures: a control-channel recording saved as a cfile can be re-run bit-for-bit to reproduce a decode problem on any developer’s machine, which is the backbone of GopherTrunk’s record-and-replay testing.

In practice

Because the extension is a convention, not a marker, cfiles appear as .cfile, .cf32, .fc32, or plain .iq — always verify the dtype, not the name. A quick sanity check: file size in bytes divided by eight is the sample count, and dividing that by the sample rate gives the capture duration; if the duration comes out sensible, the file really is float32 IQ.

Sources

  1. File Sink — GNU Radio wiki, documenting the File Sink block that writes raw interleaved samples (complex → interleaved float32, the cfile) with no header. 

See also