Also known as: cs16, sc16, complex int16, ci16
cs16 (“complex signed 16-bit”, also written sc16) is a raw
IQ format: an interleaved stream of little-endian 16-bit signed
integers, I₀ Q₀ I₁ Q₁ …, with no header, no metadata, and nothing else in the
file.1 One complex sample costs 4 bytes — half the size of the float32
cfile — and because 12–16-bit
ADCs produce integer samples natively, cs16 is
often a bit-exact record of what the hardware delivered rather than a converted copy.
Conventions
- Scaling. Full scale is ±32767, which maps to 0 dBFS; consumers typically divide by 32768 to get ±1.0 floats. A capture’s peak level in dBFS is meaningful and portable — one reason integer captures are convenient evidence when overload or gain staging is in question.
- Endianness and order. Little-endian, I before Q, is the near-universal convention
(matching SoapySDR’s
CS16stream format and USRPsc16wire format), but nothing in the file enforces it — a byte-swapped or IQ-swapped read produces plausible-looking garbage, so trust but verify with a spectrum sanity check. - No metadata. Sample rate and centre frequency must be carried in a sidecar file, the
filename, or a note. SigMF exists precisely to formalise this; a
bare
.cs16/.rawfile depends on discipline.
Against its neighbours: a cfile (float32) spends twice the
bytes to preserve processing headroom beyond the ADC’s range — worthwhile for processed
signals, moot for raw captures of a 12-bit front end. 8-bit formats
(rtl_sdr’s unsigned u8) halve the size again at the cost of dynamic range. A 2-channel
16-bit WAV is cs16 plus a 44-byte header that documents the
sample rate — a big usability win the raw format trades away for simplicity.
Relevance to SDR
cs16 is GopherTrunk’s workhorse capture format: gophertrunk replay -in capture.raw
-format cs16 -sample-rate … replays one, the repository’s regression fixtures
(testdata/*.cs16) and operators’ field captures use it, and the pre-combine
diversity_capture tap writes one headerless cs16 file per receiver branch plus a JSON
sidecar carrying the metadata the format itself omits. The half-size-of-float economy is
the reason: a 30-second two-branch capture at 250 kS/s is ~120 MB in float32 and ~60 MB in
cs16, with nothing lost — the samples were 16-bit integers on the wire anyway. The habits
that make headerless captures useful later are the same ones this format demands: record
the sample rate, centre frequency, gain, and device alongside every file, at capture time,
every time.
Sources
-
SoapySDR wiki — Pothosware, on the CS16 complex-int16 stream format and its role as a native SDR sample type. ↩