10. Анализ записанного сигнала в C++¶
Цель раздела¶
Показать, как офлайн-анализ IQ-файла реализуется на C++ и почему такой подход важен для высокопроизводительных DSP-приложений.
1. Зачем в курсе C++¶
Хотя для первого анализа удобнее MATLAB и Python, C++ остаётся важным инженерным инструментом, потому что позволяет:
- обрабатывать большие файлы;
- создавать быстрые утилиты;
- готовить код для интеграции в реальные проекты;
- строить высокопроизводительные инструменты анализа и управления.
Дальше C++ может стать основой сервисных приложений, серверных компонентов и DSP-утилит.
2. Задачи этапа¶
В первом блоке C++ используется в облегчённом режиме. Студент должен:
- прочитать IQ-файл;
- сформировать комплексный массив;
- выполнить базовый спектральный анализ;
- оценить частоту основного тона;
- понять архитектуру простой консольной DSP-утилиты.
3. Что должна делать программа¶
Минимальная программа должна:
- Открыть файл.
- Прочитать чередующиеся данные I/Q.
- Преобразовать их в комплексный массив.
- Выполнить FFT или эквивалентный спектральный анализ.
- Найти максимум спектра.
- Вывести оценку частоты пика.
4. Что можно использовать¶
На первом этапе возможны два подхода.
Вариант 1. Учебный¶
Реализовать простое ДПФ/FFT вручную или в упрощённом виде.
Вариант 2. Практический¶
Использовать внешнюю библиотеку:
- FFTW
- Intel IPP
- KissFFT
- другую подходящую библиотеку FFT
Для первого блока допустим упрощённый демонстрационный вариант.
5. Пример общей структуры программы¶
#include <iostream>
#include <fstream>
#include <vector>
#include <complex>
#include <cstdint>
int main() {
const char* filename = "tone_capture_iq.bin";
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "Cannot open file\n";
return 1;
}
std::vector<int16_t> raw;
int16_t value;
while (file.read(reinterpret_cast<char*>(&value), sizeof(value))) {
raw.push_back(value);
}
if (raw.size() < 2) {
std::cerr << "Not enough data\n";
return 1;
}
std::vector<std::complex<double>> x;
x.reserve(raw.size() / 2);
for (size_t k = 0; k + 1 < raw.size(); k += 2) {
double i = static_cast<double>(raw[k]);
double q = static_cast<double>(raw[k + 1]);
x.emplace_back(i, q);
}
std::cout << "Loaded complex samples: " << x.size() << "\n";
// Здесь можно добавить FFT и поиск пика
return 0;
}
5a. Версия курса: законченная утилита с ДПФ¶
blocks/block_01_intro_sdr/cpp/iq_reader_example.cpp дополняет эту структуру учебным вариантом: простое ДПФ по 4096 отсчётам и поиск пика с учётом отрицательных частот. На том же тестовом тоне 200 кГц, что и на странице 09:
g++ -std=c++17 -O2 -o iq_reader_example blocks/block_01_intro_sdr/cpp/iq_reader_example.cpp
./iq_reader_example capture.ci16 2400000
Loaded complex samples: 65536
DFT length: 4096, bin width: 585.938 Hz
Peak offset from the tuning frequency: 199805 Hz
Ответ совпадает с Python-скриптом до бина. Простому ДПФ нужно 4096 × 4096 ≈ 16,8 млн комплексных умножений, здесь это заняло около 2,7 с; FFT нужно около 4096 × log2(4096) / 2 ≈ 25 000 бабочек. Этот разрыв: причина, по которой любой реальный инструмент использует библиотеку FFT и по которой курс строит в аппаратуре именно FFT, а не ДПФ (Лабораторная 8.14).
6. Что должен понять студент¶
На этом этапе важно не столько написать идеальную DSP-библиотеку, сколько понять:
- как устроен формат хранения IQ;
- как строится конвейер обработки на C++;
- как комплексные данные представлены в памяти;
- почему C++ полезен для задач, где важна производительность;
- как офлайн-анализ можно оформить в самостоятельную утилиту.
7. Какие результаты нужны в первом блоке¶
Достаточно получить:
- успешное чтение файла;
- формирование комплексного сигнала;
- базовое вычисление спектра;
- оценку частоты основного пика;
- вывод параметров в консоль.
8. Практическая ценность этапа¶
Даже простая программа на C++ важна: она показывает студенту переход от учебного анализа к прикладной разработке.
Так в реальных проектах появляются:
- анализаторы записей;
- сервисные утилиты;
- автономные DSP-модули;
- серверные компоненты SDR-систем.
9. Что включить в отчёт¶
Рекомендуется включить:
- краткое описание структуры программы;
- фрагмент кода чтения IQ-файла;
- способ вычисления спектра;
- оценённую частоту пика;
- вывод о применимости C++ для обработки сигналов.
10. Выводы¶
После этого этапа студент должен:
- понимать, как читать IQ-данные на C++;
- видеть роль C++ в высокопроизводительной обработке сигналов;
- понимать, как из учебного анализа вырастает настоящая инженерная утилита.