Системные объекты EngeeDSP
Системный объект — это специализированная программная конструкция в среде технических расчётов Engee. Объекты используются для реализации и моделирования динамических систем с входами, изменяющимися во времени. Они упрощают построение систем потоковой обработки в скриптах Engee.
В качестве примера динамической системы можно рассмотреть чтение "кадра" из нескольких отсчётов сигнала, записанного в длинный файл, последующей обработки этого кадра цифровым фильтром, или же спектрального анализа методом БПФ или банка фильтров. Все звенья этой цепи можно представить последовательностью соответствующих системных объектов.
В этом примере мы рассмотрим возможность реализации схемы потоковой обработки и визуализации, аналогичной эталонной модели Engee, которую собрали из параметризуемых блоков. Модель reference_FFT.engee является вариацией рассмотренной ранее модели из данного примера.
Модифицированная модель обрабатывает действительный сигнал с линейной частотной модуляцией (ЛЧМ) фильтром нижних частот (ФНЧ) с конечной импльсной характеристикой (КИХ), а затем буферизует кадр данных и вычисляет результат оконного быстрого преобразования Фурье (БПФ) с последующей визуализацией действительной части спектра..png)
Ожидаемое поведение алгоритмов ЦОС можно наблюдать при запуске модели в окне "Визуализация сигналов". Данную цепь обработки мы реализуем в скрипте формата *.ngscript на основе системных объектов библиотеки EngeeDSP.
Укажем используемые библиотеки системных объектов и функций ЦОС:
using EngeeDSP
using EngeeDSP.Functions
Зададим основные параметры цифровой системы, такие как частота дискретизации и размер обрабатываемого кадра:
fs = 8000;
framesize = 512;
Источник потокового сигнала
В качестве источника сигнала с линейно изменяющейся частотой дискретизации будем использовать системный объект SineWaveDSP. Он генерирует синусоидальное колебание, частоту которого мы можем изменять в цикле, тем самым аппроксимируя поведение источника ЛЧМ-сигнала. Передадим ему параметры частоты дискретизации и размера кадра:
source = SineWaveDSP();
source.SampleTime = 1//fs;
source.SamplesPerFrame = framesize;
source
Рассмотрим поведение объекта при его вызове и сбросе состояний:
release!(source)
x = source();
plot(x, leg=false)
Фильтр нижних частот
Начнём с создания прототипа подходящего фильтра нижних частот. Для этого используем функции синтеза и анализа из библиотеки EngeeDSP.Functions:
n = 15;
firwin = window("hamming", n+1)
b = fir1(n, 2000/(fs/2), firwin, "low");
freqz(b, 1, 512, fs, out=:plot)
Коэффициенты числителя передаточной функции прототипа фильтра передадим системному объекту DiscreteFIRFilter. О влиянии состояний фильтра на форму обрабатываемого сигнала более подробно рассказывается в этом примере сообщества:
FIR = DiscreteFIRFilter();
FIR.Coefficients = b;
setup!(FIR, zeros(framesize));
plot(b, l=:stem, m=:c)
Оконная функция
Для оконной функции необязательно использовать системный объект, так как её математика не меняется в зависимости от предыдущих значений сигнала и состояний. Достаточно просто сформировать вектор значений окна Хэмминга размером с кадр данных во временной области:
hamwin = window("hamming", framesize);
plot(hamwin,l=:stem,label="Hamming window")
БПФ
Системный объект EngeeFFT будет наследовать размер входного кадра, но численные значения комплексных отсчётов мы будем делить на длину БПФ:
FFT = EngeeFFT();
FFT.DivideOutputFFTLength = true;
FFT
Преобразование в дБм
Объект dbConverion позволяет устанавливать параметры входного и выходного сигналов. В нашем случае мы преобразуем амплитуду в дБм:
dbconv = dBConversion()
dbconv.ConvertTo = "dBm";
dbconv
Основной цикл обращения к системным объектам
Зададим численные вектора изменяющегося значения частоты повторений источника синусоидального сигнала freq_range. Частота будет изменяться в пределах от 50 Гц до 4000 Гц с шагом 50 Гц.
Также инициализируем вектор частотной сетки freqvec для последующего отображения спектра.
Количество итераций основного цикла будет соответствовать длине вектора нарастающих значений частоты синусоиды. Результат обработки будем помещать покадрово в матрицу spectrum:
freq_range = 50:50:Int(fs/2);
freqvec = LinRange(0.0,fs/2,Int(framesize/2));
count = length(freq_range);
spectrum = zeros(Int(framesize/2),count);
На каждом шаге цикла происходит изменение параметра частоты системного объекта генератора синусоиды, запись отрезка синуса в переменную sine_chunk, обработка этого кадра КИХ-фильтром, применение оконной функции, вычисление комплексного вектора БПФ, обрезка его до "середины", вычисление модуля и перевод из амплитуды в дБм:
for k = 1:count
source.Frequency = freq_range[k];
sine_chunk = source();
LPF = FIR(sine_chunk);
complexFFT = FFT(LPF .* hamwin);
absFFT = abs(complexFFT[1:Int(framesize/2)]);
spectrum[:,k] = dbconv(absFFT);
end
Визуализация
Отобразим изменение спектра в динамике за всё время "динамической симуляции" при помощи трёхмерной поверхности:
surface(1:count, freqvec, spectrum)
А также визуализируем анимацию изменения спектра:
anim = @animate for i = 1:count
plot(freqvec, spectrum[:,i],
lw=2,
ylim = (-120,30),
leg = false,
title = "Спектр ЛЧМ-сигнала",
yguide = "dBm",
xguide = "Частота (Гц)",
size = (800,200))
end
gif(anim, "dynamic_spectrum.gif", fps = 10)
Заключение
Мы рассмотрели возможность построения полноценной динамической модели потоковой обработки и визуализации сигналов на базе системных объектов EngeeDSP. Модель включает в себя функциональные узлы:
- источника синусоиды с изменяющейся частотой повторений
- КИХ-фильтра нижних частот
- оконной функции
- быстрого преобразования Фурье
- вычисления спектра сигнала в дБм
- визуализации
.gif)