Reading and Writing Binary Files
Binary files allow RF information to be recorded for offline usage. Before continuing it is useful to refer to the tutorial Signal Data Types which describes different data types in GNU Radio.
Data File Formats
Each binary file will have a specific data format, with the two most common being 32-bit floats and 16-bit integers. RF samples can be both positive and negative, and therefore all integers will be implied to be signed integers, for simplicity. The binary file will save all samples in the same format back to back. For example, a binary file of 16-bit integers will save sample 0 as 16 bits, then sample 1 as 16-bits, sample 2 as 16-bits, and so on.
[ sample 0: 16 bit int ][ sample 1: 16 bit int ][ sample 2: 16 bit int ] ...
For example, a binary file of 32-bit floats will save sample 0 as 32 bits, then sample 1 as 32-bits, sample 2 as 32-bits, and so on.
[ sample 0: 32 bit float ][ sample 1: 32 bit float ][ sample 2: 32 bit float ] ...
Real and Complex Formats
RF samples can be either real or complex. When a real sample is saved to a binary file each sample is saved in order: sample 0, then sample 1, then sample 2, and so on.
[ real sample 0 ][ real sample 1 ][ real sample 2 ] ...
A complex sample, I + jQ, has both a real component (I) and imaginary component (Q). The I and Q components of each sample will be interleaved when saved to a binary file. I of sample 0, then Q of sample 0, then I of sample 1, then Q of sample 1, then I of sample 2, then Q of sample 2, and so on.
[ I sample 0 ][ Q sample 0 ][ I sample 1 ][ Q sample 1 ][ I sample 2 ][ Q sample 2 ] ...
Saving Samples as Binary Files
The different types of sample representations and binary file formats can be mixed and matched:
- Real samples stored as 16-bit integers
- Real samples stored as 32-bit floats
- Complex samples stored as interleaved 16-bit integers
- Complex samples stored as interleaved 32-bit floats
Real samples stored as 16-bit integers:
[ sample 0: 16 bit int ][ sample 1: 16 bit int ][ sample 2: 16 bit int ] ...
Real samples stored as 32-bit floats:
[ sample 0: 32 bit float ][ sample 1: 32 bit float ][ sample 2: 32 bit float ] ...
Complex samples stored as interleaved 16-bit integers:
[ I sample 0: 16 bit int ][ Q sample 0: 16 bit int ][ I sample 1: 16 bit int ][ Q sample 1: 16 bit int ][ I sample 2: 16 bit int ][ Q sample 2: 16 bit int ] ...
Complex samples stored as interleaved 32-bit floats:
[ I sample 0: 32 bit float ][ Q sample 0: 32 bit float ][ I sample 1: 32 bit float ][ Q sample 1: 32 bit float ][ I sample 2: 32 bit float ] [ Q sample 2: 32 bit float ] ...
Endianness
Endianness describes the order of bytes within binary data. Big endian and little endian systems differ on the placement of the most significant byte and least significant byte. Little endian systems place the least significant byte in the smallest memory address and the most significant byte in the largest memory address. Big endian systems store the most significant byte in the smallest memory address and the least significant byte in the largest memory address.
For example, consider the hexadecimal value 0xABCD0123. A big endian system would store the value into memory by:
Data Value: [ 0xAB ] [ 0xCD] [ 0x01 ] [ 0x23 ]
Memory Address: [ 0x00 ] [ 0x01] [ 0x02 ] [ 0x03 ]
A little endian system stores the bytes in the reversed order into memory:
Data Value: [ 0x23 ] [ 0x01] [ 0xCD ] [ 0xAB ] [BR]
Memory Address: [ 0x00 ] [ 0x01] [ 0x02 ] [ 0x03 ]
Converting between endianness is sometimes referred to as a “byte swap” operation. The Endian Swap block performs this endian conversion.