参数音频均衡器
在本演示中,我们将了解一个支持三个可调频段的参数音频均衡器。每个频段都使用不同的二次滤波器结构实现。
均衡器是一种无线电电子设备或计算机程序,可根据频率特性有选择地修正信号幅度。
在本演示中,我们还将比较Engee和MATLAB模型的工作情况。
为此,我们将连接必要的库,并考虑实施模型的结构。
In [ ]:
Pkg.add(["Statistics", "CSV"])
In [ ]:
using Plots
using MATLAB
using CSV
using DataFrames
using Statistics
In [ ]:
plotlyjs();
In [ ]:
mat"start_simulink"
mat"p = genpath('/user/start/examples'); addpath(p);"
模型由两大块组成:均衡器本身(包括 3 个滤波器块,滤波器系数位于上层)和离散传递函数估计器。下图显示了模型和估计器的设置。


如果我们考虑每个滤波器,它们的实现方式都是一样的,都包括一个离散滤波器系数采样单元和一个二次滤波器。

现在,让我们继续运行并比较该模型在Engee和Simulink中的实现情况。
运行和分析Engee模型
让我们来看看Engee建模的结果:
In [ ]:
function rum_model(NemeModel,Path_to_folder)
Path = Path_to_folder * "/" * NemeModel * ".engee"
if NemeModel in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
model = engee.open(NemeModel) # Открыть модель
engee.run(model, verbose=true); # Запустить модель
else
model = engee.load(Path, force=true) # Загрузить модель
engee.run(model, verbose=true); # Запустить модель
engee.close(NemeModel, force=true); # Закрыть модель
end
end
Out[0]:
In [ ]:
# Запуск модели
rum_model("Equalizer","/user/start/examples/dsp/equalizer")
In [ ]:
function parse_csv_engee(filename :: String)
file = open(filename)
line = readline(file)
name_idx = vcat(0,findall(',', line), length(line)+1)
names = collect([line[(name_idx[it-1]+1):(name_idx[it]-1)] for it ∈ 2:length(name_idx)])
data = collect([it for it ∈ (line -> eval(Meta.parse(line)))(readline(file))])
while !eof(file)
data = ((a, b) -> [a;;;b]).(data, collect([it for it ∈ (line -> eval(Meta.parse(line)))(readline(file))]))
end
close(file)
return Dict(names .=> data)
end
Out[0]:
In [ ]:
# Чтение CSV
out = parse_csv_engee("/user/start/examples/dsp/equalizer/out.csv");
out_t = out["time"];
out_data = out["1"];
In [ ]:
# Построение графиков
Eng_data = reshape(out_data,808)
plot(Eng_data[1:8:end])
plot!(Eng_data[2:8:end])
plot!(Eng_data[3:8:end])
plot!(Eng_data[4:8:end])
plot!(Eng_data[5:8:end])
plot!(Eng_data[6:8:end])
plot!(Eng_data[7:8:end])
plot!(Eng_data[8:8:end])
plot!(title = "Результаты моделирования в Engee", ylabel = "Данные", xlabel="Время, c")
Out[0]:
运行并分析Simulink模型
让我们比较一下Engee和Simulink的模拟结果。为此,我们首先对模型进行仿真。
In [ ]:
mat"run_test_model('Equalizer')";
让我们看看Simulink中的结果:
In [ ]:
mat"whos" # Вывести все переменные, хранящиеся в рабочей области
In [ ]:
# Чтение выхода модели
sim = mat"SysOutput.Data";
In [ ]:
# Построение графиков
Sim_data = reshape(sim,808)
plot(Sim_data[1:8:end])
plot!(Sim_data[2:8:end])
plot!(Sim_data[3:8:end])
plot!(Sim_data[4:8:end])
plot!(Sim_data[5:8:end])
plot!(Sim_data[6:8:end])
plot!(Sim_data[7:8:end])
plot!(Sim_data[8:8:end])
plot!(title = "Результаты моделирования в Simulink", ylabel = "Отклик", xlabel="Время, c")
Out[0]:
现在绘制Simulink和Engee的输出差值,并计算平均误差。
In [ ]:
plot(Sim_data-Eng_data)
Out[0]:
In [ ]:
print("Погрешность: " * string((sum(abs.(Sim_data-Eng_data)))/length(Eng_data)))
从上图和平均误差计算结果可以看出,这两个模型的工作原理几乎完全相同。
结论
在本示例中,我们实现了 EQ,并比较了Engee与Simulink建模的功能,还展示了连接MATLAB内核的选项,以便在Engee开发环境中解决问题。