5

您知道 GNU Radio(GNU Radio Companion 中的 File Sink)在二进制文件中存储样本的格式吗?

我需要在 Matlab 中阅读这些示例,但问题是文件太大而无法在 Matlab 中阅读。

我正在用 C++ 编写程序来读取这个二进制文件。

4

2 回答 2

5

文件接收器只是数据流的转储。如果数据流内容是简单的字节,那么文件的内容就很简单了。如果数据流包含复数,则文件将包含复数列表,其中每个复数由两个浮点数给出,每个浮点数由(通常)4 个字节给出。

请参阅文件gnuradio/gnuradio-core/src/lib/io/gr_file_sink.cc以及gr_file_source.ccgnuradio 文件读写块的实现。

您还可以使用 python 和 gnuradio 将文件转换为其他格式。

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()
于 2011-02-20T05:25:02.660 回答
1

Ben 的回答仍然有效——但这是很久以前的事了(我认为模块组织指向 GNU Radio 3.6)。在组织上,现在情况不同了。数据方面,文件接收器保持不变。

GNU Radio 现在在他们的 wiki 中有相对多的块文档。特别是,文件接收器文档页面有一个关于处理文件接收器数据的部分;不要过度引用:

// 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"));
}
于 2022-02-08T12:10:05.017 回答