您知道 GNU Radio(GNU Radio Companion 中的 File Sink)在二进制文件中存储样本的格式吗?
我需要在 Matlab 中阅读这些示例,但问题是文件太大而无法在 Matlab 中阅读。
我正在用 C++ 编写程序来读取这个二进制文件。
您知道 GNU Radio(GNU Radio Companion 中的 File Sink)在二进制文件中存储样本的格式吗?
我需要在 Matlab 中阅读这些示例,但问题是文件太大而无法在 Matlab 中阅读。
我正在用 C++ 编写程序来读取这个二进制文件。
文件接收器只是数据流的转储。如果数据流内容是简单的字节,那么文件的内容就很简单了。如果数据流包含复数,则文件将包含复数列表,其中每个复数由两个浮点数给出,每个浮点数由(通常)4 个字节给出。
请参阅文件gnuradio/gnuradio-core/src/lib/io/gr_file_sink.cc
以及gr_file_source.cc
gnuradio 文件读写块的实现。
您还可以使用 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()
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"));
}