【问题标题】:GNU Radio File Format for the recorded samples录制样本的 GNU Radio 文件格式
【发布时间】:2020-12-12 05:43:33
【问题描述】:

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

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

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

【问题讨论】:

    标签: gnuradio


    【解决方案1】:

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

    有关 gnuradio 文件读写块的实现,请参阅文件 gnuradio/gnuradio-core/src/lib/io/gr_file_sink.ccgr_file_source.cc

    您还可以使用 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()
    

    【讨论】:

      【解决方案2】:

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

      GNU Radio 现在在他们的 wiki 中有相对较多的 block documentation。特别是,File Sink 文档页面有一个关于Handling File Sink data 的部分;不要过度引用:

      // 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"));
      }
      

      【讨论】:

        猜你喜欢
        • 2017-03-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-14
        • 2018-02-27
        • 1970-01-01
        • 2021-10-14
        • 2021-06-12
        相关资源
        最近更新 更多