FIR Filter System Object
A system object is a specialized software construct in Engee with specific methods and properties for modeling an algorithm. System objects are useful for modeling dynamic systems and processing streaming data. In this example, we will consider using the FIR filter system object from the EngeeDSP library to simulate streaming digital processing (DSP) of a test signal.
Low-pass filter prototype analysis
To create a prototype FIR filter and further compare it, we will use the plug-in library. DSP.jl:
using DSP
The prototype of the digital low-pass filter (low-pass filter) is synthesized by the windowed method. It will operate at a sampling frequency of 2 kHz, have a bandwidth limit of 600 Hz and an order of 16. Let's calculate and display the amplitude-frequency response (frequency response) of the prototype filter using the function freqresp:
fs = 2000;
b = digitalfilter(Lowpass(600/fs), FIRWindow(hanning(16)));
filter_prototype = PolynomialRatio(b,[1]);
H, w = freqresp(filter_prototype);
freq_vec = fs*w/(2*pi);
plot(freq_vec, pow2db.(abs.(H))*2, ylim = [-120, 10], legend = false, linewidth = 3,
xlabel = "Частота, Гц",
ylabel = "Усиление, дБ",
title = "АЧХ прототипа ФНЧ")
As a test signal, we will generate the sum of two sinusoids at frequencies of 140 and 500 Hz with a duration of 0.5 seconds. For a signal with a sampling frequency of 2 kHz, the number of samples of the vector is long_signal it will be exactly 1000. We will display the result of passing the test signal through the prototype low-pass filter in the time domain with the function plot:
t = 0:1/fs:0.5 - 1/fs;
long_signal = sum(sin.(2*pi*t*[140 500]), dims = 2);
out_signal = filt(filter_prototype, long_signal);
plot(t, long_signal)
plot!(t, out_signal, legend = false, xlim = [0,0.1], linewidth = 3,
xlabel = "Время, сек",
ylabel = "Амплитуда",
title = "Прохождение тестового сигнала через прототип ФНЧ")
We observe a successfully filtered sinusoid with a frequency of 140 Hz without phase discontinuities.
An attempt to implement stream filtering in a loop
Streaming data for the DSP system can arrive via a standard interface in the form of information packets, or directly from the buffer after the analog-to-digital converter (ADC). Let's model the streaming input data by representing the input signal as a set of separate vectors of shorter duration (100 samples each). Let's put them in the columns of the matrix for easy indexing.:
input_matrix = reshape(long_signal,(100,10))
Now let's see what happens if you call the function filt with a prototype filter in a loop, applying it sequentially to each of the columns of the input matrix. We will also write the intermediate result of filtering to a variable. output_matrix, which is the same size as the input matrix. And we will carry out a visual comparison on the output vector "expanded in a line". out_vector:
output_matrix = zeros(size(input_matrix));
for i = 1:10
output_matrix[:,i] = filt(filter_prototype, input_matrix[:,i])
end
out_vector = reshape(output_matrix,(1000));
plot(t, long_signal)
plot!(t, out_vector, legend = false, xlim = [0,0.1], linewidth = 3,
xlabel = "Время, сек",
ylabel = "Амплитуда",
title = "Потоковая обработка прототипом ФНЧ")
As we can see, the shape of the output signal was distorted. This is because the function filt and the filter object itself filter_prototype They do not provide for the storage of intermediate states of the digital filter, which, when processed in a cycle, leads to characteristic undesirable phase discontinuities.
Creating, initializing, and applying a system filter object
System objects are designed specifically for the implementation and modeling of dynamic systems with inputs that change over time. Many signal processing, communication, and control systems are dynamic. In a dynamic system, the values of the output signals depend both on the instantaneous values of the input signals and on the behavior of the system in the past. System objects use internal states to preserve this behavior in the past, which is used in the next stage of calculations. As a result, system objects are optimized for iterative calculations that process large data streams across segments, for example, in video and audio processing systems. This ability to process streaming data provides an advantage - you do not need to store large amounts of data in memory, and dynamic scenario modeling is carried out in a fairly simple cycle.
Creating a discrete FIR filter system object (from the EngeeDSP library):
fir_SO = EngeeDSP.DescretFIRFilter()
We will leave all its parameters as default, with the exception of the filter coefficients. We will take them directly from the prototype of the filter, that is, from the vector b:
fir_SO.Coefficients = b;
plot(fir_SO.Coefficients, line=:stem, marker=:circle, linewidth = 3,
xlabel = "Номер отсчёта",
ylabel = "Импульсная характеристика")
The code for implementing the processing is similar to the one we tried above, except for initializing the initial states of the filter object before starting the main loop.:
output_matrix = zeros(size(input_matrix));
EngeeDSP.setup!(fir_SO, input_matrix[1,:])
for i = 1:10
output_matrix[:,i] = EngeeDSP.step!(fir_SO, input_matrix[:,i])
end
out_vector = reshape(output_matrix,(1000));
plot(t, long_signal)
plot!(t, out_vector, legend = false, xlim = [0,0.1], linewidth = 3,
xlabel = "Время, сек",
ylabel = "Амплитуда",
title = "Потоковая обработка системным объектом")
Let's compare the vectors programmatically and display the maximum discrepancy between the output of the prototype filter on a long input signal and the output of a stream filtering cycle using a system object.:
maximum(out_vector - out_signal)
Conclusion
In the example, we looked at the basics of using the EngeeDSP library system object for the task of streaming input signal processing in a loop. You can also get acquainted with examples of using the EngeePhased library system objects for modeling radar station , and with the EngeeComms library objects for designing wireless communication systems связи.