Engee 文档
Notebook

FIR滤波器系统对象

系统对象是Engee中的专用软件构造,具有用于建模算法的特定方法和属性。 系统对象对于建模动态系统和处理流数据非常有用。 在本例中,我们将考虑使用来自EngeeDSP库的FIR滤波器系统对象来模拟测试信号的流式数字处理(DSP)。

低通滤波器原型分析

要创建原型FIR滤波器并进一步比较,我们将使用插件库。 DSP.jl:

In [ ]:
using DSP

数字低通滤波器(low-pass filter)的原型是通过加窗方法合成的。 它将以2kHz的采样频率运行,带宽限制为600Hz,数量级为16。 让我们使用函数计算并显示原型滤波器的幅度-频率响应(频率响应 freqresp:

In [ ]:
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 = "АЧХ прототипа ФНЧ")
Out[0]:

作为测试信号,我们将在140和500Hz频率下生成两个正弦曲线的总和,持续时间为0.5秒。 对于采样频率为2kHz的信号,矢量的采样数为 long_signal 这将正好是1000。 我们将显示测试信号通过原型低通滤波器在时域与函数的结果 plot:

In [ ]:
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 = "Прохождение тестового сигнала через прототип ФНЧ")
Out[0]:

我们观察到一个成功滤波的正弦波,频率为140Hz,没有相位不连续性。

在循环中实现流过滤的尝试

用于DSP系统的流数据可以通过标准接口以信息包的形式到达,或者直接从模数转换器(ADC)之后的缓冲器到达。 让我们通过将输入信号表示为一组持续时间较短的单独向量(每个100个样本)来对流输入数据进行建模。 让我们把它们放在矩阵的列中,以便于索引。:

In [ ]:
input_matrix = reshape(long_signal,(100,10))
Out[0]:
100×10 Matrix{Float64}:
  0.0        -7.32312e-16  -1.46462e-15  …  -5.8585e-15  -7.05397e-14
  1.42578     1.42578       1.42578          1.42578      1.42578
  0.770513    0.770513      0.770513         0.770513     0.770513
 -0.0314168  -0.0314168    -0.0314168       -0.0314168   -0.0314168
  0.982287    0.982287      0.982287         0.982287     0.982287
  1.80902     1.80902       1.80902      …   1.80902      1.80902
  0.481754    0.481754      0.481754         0.481754     0.481754
 -0.937209   -0.937209     -0.937209        -0.937209    -0.937209
 -0.368125   -0.368125     -0.368125        -0.368125    -0.368125
  0.271031    0.271031      0.271031         0.271031     0.271031
 -0.951057   -0.951057     -0.951057     …  -0.951057    -0.951057
 -1.99211    -1.99211      -1.99211         -1.99211     -1.99211
 -0.844328   -0.844328     -0.844328        -0.844328    -0.844328
  ⋮                                      ⋱               
  0.844328    0.844328      0.844328         0.844328     0.844328
  1.99211     1.99211       1.99211          1.99211      1.99211
  0.951057    0.951057      0.951057     …   0.951057     0.951057
 -0.271031   -0.271031     -0.271031        -0.271031    -0.271031
  0.368125    0.368125      0.368125         0.368125     0.368125
  0.937209    0.937209      0.937209         0.937209     0.937209
 -0.481754   -0.481754     -0.481754        -0.481754    -0.481754
 -1.80902    -1.80902      -1.80902      …  -1.80902     -1.80902
 -0.982287   -0.982287     -0.982287        -0.982287    -0.982287
  0.0314168   0.0314168     0.0314168        0.0314168    0.0314168
 -0.770513   -0.770513     -0.770513        -0.770513    -0.770513
 -1.42578    -1.42578      -1.42578         -1.42578     -1.42578

现在让我们看看如果调用该函数会发生什么 filt 在循环中使用原型滤波器,将其顺序应用于输入矩阵的每列。 我们还将过滤的中间结果写入变量。 output_matrix,其与输入矩阵的大小相同。 并且我们将对输出向量"在一行中展开"进行视觉比较。 out_vector:

In [ ]:
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 = "Потоковая обработка прототипом ФНЧ")
Out[0]:

正如我们所看到的,输出信号的形状被扭曲了。 这是因为功能 filt 和filter对象本身 filter_prototype 它们不提供数字滤波器的中间状态的存储,当在一个周期中处理时,这会导致特征性的不希望的相位不连续性。

创建、初始化和应用系统筛选器对象

系统对象专为具有随时间变化的输入的动态系统的实现和建模而设计。 许多信号处理、通信和控制系统都是动态的。 在动态系统中,输出信号的值既取决于输入信号的瞬时值,也取决于系统过去的行为。 系统对象使用内部状态来保留过去的此行为,用于下一阶段的计算。 结果,系统对象被优化用于跨段处理大数据流的迭代计算,例如,在视频和音频处理系统中。 这种处理流数据的能力提供了一个优势-您不需要在内存中存储大量数据,并且动态场景建模在相当简单的循环中进行。

创建离散FIR滤波器系统对象(来自EngeeDSP库):

In [ ]:
fir_SO = EngeeDSP.DescretFIRFilter()
Out[0]:
DescretFIRFilter:
    CoefSource=Dialog parameters
    FilterStructure=Direct form
    Coefficients=[0.5 0.5]
    InputProcessing=Elemets as channels
    InitialStates=0
    ShowEnablePort=false
    ExternalReset=None
    PreEmphasis_states=[0.0]

我们将保留所有参数为默认值,但滤波器系数除外。 我们将直接从过滤器的原型中获取它们,即从向量中获取它们 b:

In [ ]:
fir_SO.Coefficients = b;
plot(fir_SO.Coefficients, line=:stem, marker=:circle, linewidth = 3, 
        xlabel = "Номер отсчёта", 
        ylabel = "Импульсная характеристика")
Out[0]:

实现处理的代码类似于我们上面尝试的代码,除了在启动主循环之前初始化filter对象的初始状态。:

In [ ]:
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 = "Потоковая обработка системным объектом")       
Out[0]:

让我们以编程方式比较矢量,并显示原型滤波器在长输入信号上的输出与使用系统对象的流过滤周期的输出之间的最大差异。:

In [ ]:
maximum(out_vector - out_signal)
Out[0]:
3.3306690738754696e-16