Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Radio File Format for the recorded samples

Tags:

gnuradio

Do you know the format in which GNU Radio ( File Sink in GNU Radio Companion) stores the samples in the Binary File?

I need to read these samples in Matlab, but the problem is the file is too big to be read in Matlab.

I am writing the program in C++ to read this binary file.

like image 465
Kiran Avatar asked Feb 18 '11 13:02

Kiran


People also ask

What is a file sink?

A writer file sink object controls the flow of data from the writer object to a single file. You can create your own file sinks to get more control over how the sink writes the file. You can also access the default writer file sink created by the writer in response to a call to SetOutputFilename.

Where are GNU Radio blocks stored?

As mentioned, the blocks can be found in the GNU Radio top-level components and any OOT modules you've installed alongside GNU Radio.

What are GNU Radio blocks?

Main Page. GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment.

What is throttle in GNU Radio?

The Throttle Block is typically attached directly to the output of a non-hardware source block (e.g. Signal Source), in order to limit the rate at which that source block creates samples.


2 Answers

The file sink is just a dump of the data stream. If the data stream content was simple bytes then the content of the file is straightforward. If the data stream contained complex numbers then the file will contain a list of complex numbers where each complex number is given by two floats and each float by (usually) 4 bytes.

See the files gnuradio/gnuradio-core/src/lib/io/gr_file_sink.cc and gr_file_source.cc for the implementations of the gnuradio file reading and writing blocks.

You could also use python and gnuradio to convert the files into some other format.

from gnuradio import gr
# Assuming the data stream was complex numbers.
src = gr.file_source(gr.sizeof_gr_complex, "the_file_name")
snk = gr.vector_sink_c()
tb = gr.top_block()
tb.connect(src, snk)
tb.run()
# The complex numbers are then accessible as a python list.
data = snk.data()
like image 88
Ben Reynwar Avatar answered Oct 12 '22 09:10

Ben Reynwar


Ben's answer still stands – but it's from a time long past (the module organization points at GNU Radio 3.6, I think). Organizationally, things are different now; data-wise, the File Sink remained the same.

GNU Radio now has relatively much block documentation in their wiki. In particular, the File Sink documentation page has a section on Handling File Sink data; not to overquote that:

// This is C++17
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstddef>
#include <filesystem>
#include <fstream>
#include <string_view>
#include <vector>

#include <fmt/format.h>
#include <fmt/ranges.h>

using sample_t = std::complex<float>;
using power_t = float;
constexpr std::size_t read_block_size = 1 << 16;

int main(int argc, char *argv[]) {
  // expect exactly one argument, a file name
  if (argc != 2) {
    fmt::print(stderr, "Usage: {} FILE_NAME", argv[0]);
    return -1;
  }
  // just for convenience; we could as well just use `argv[1]` throughout the
  // code
  std::string_view filename(argv[1]);

  // check whether file exists
  if (!std::filesystem::exists(filename.data())) {
    fmt::print(stderr, "file '{:s}' not found\n", filename);
    return -2;
  }

  // calculate how many samples to read
  auto file_size = std::filesystem::file_size(std::filesystem::path(filename));
  auto samples_to_read = file_size / sizeof(sample_t);

  // construct and reserve container for resulting powers
  std::vector<power_t> powers;
  powers.reserve(samples_to_read);

  std::ifstream input_file(filename.data(), std::ios_base::binary);
  if (!input_file) {
    fmt::print(stderr, "error opening '{:s}'\n", filename);
    return -3;
  }

  // construct and reserve container for read samples
  // if read_block_size == 0, then read the whole file at once
  std::vector<sample_t> samples;
  if (read_block_size)
    samples.resize(read_block_size);
  else
    samples.resize(samples_to_read);

  fmt::print(stderr, "Reading {:d} samples…\n", samples_to_read);
  while (samples_to_read) {
    auto read_now = std::min(samples_to_read, samples.size());
    input_file.read(reinterpret_cast<char *>(samples.data()),
                    read_now * sizeof(sample_t));
    for (size_t idx = 0; idx < read_now; ++idx) {
      auto magnitude = std::abs(samples[idx]);
      powers.push_back(magnitude * magnitude);
    }
    samples_to_read -= read_now;
  }

  // we're not actually doing anything with the data. Let's print it!
  fmt::print("Power\n{}\n", fmt::join(powers, "\n"));
}
like image 21
Marcus Müller Avatar answered Oct 12 '22 08:10

Marcus Müller