Параметрический аудиоэквалайзер
В данной демонстрации мы разберём параметрический аудиоэквалайзер, который поддерживает три настраиваемые полосы. Каждая полоса реализована с использованием различной структуры биквадратного фильтра.
Эквалайзер — радиоэлектронное устройство или компьютерная программа, позволяющия избирательно корректировать амплитуду сигнала в зависимости от частотных характеристик.
Также в этой демонстрации мы сравним работу моделей Engee и MATLAB. Для этого подключим необходимые библиотеки и рассмотрим устройство реализованной модели.
using Plots
using MATLAB
using CSV
using DataFrames
using Statistics
plotlyjs();
mat"start_simulink"
mat"p = genpath('/user/start/examples'); addpath(p);"
Модель состоит из двух основных блоков: сам эквалайзер, включающий в себя 3 блока фильтрации с коэффициентами фильтра на верхнем уровне, и оценщик дискретной передаточной функции. На рисунках ниже показана модель и настройки оценщика.
Если рассматривать каждый из фильтров, то они реализованы однотипно и включают в себя дискретный фильтр блок выборки коэффициентов и биквадратный фильтр.
Теперь перейдем к запуску и сравнению реализации данной модели в Engee и Simulink.
Запуск и анализ модели Engee
Посмотрим на результаты моделирования в Engee:
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
rum_model (generic function with 1 method)
# Запуск модели
rum_model("Equalizer","/user/start/examples/dsp/equalizer")
Building...
Progress 100%
Dict{String, DataFrame} with 1 entry:
"out" => 101×2 DataFrame…
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
parse_csv_engee (generic function with 1 method)
# Чтение CSV
out = parse_csv_engee("/user/start/examples/dsp/equalizer/out.csv");
out_t = out["time"];
out_data = out["1"];
# Построение графиков
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")
Запуск и анализ модели Simulink
Сравним результаты моделирования в Engee и Simulink. Для этого сначала запустим симуляцию модели.
mat"run_test_model('Equalizer')";
>> >> >> [Warning: MATLAB has disabled some advanced graphics rendering features by
switching to software OpenGL. For more information, click <a
href="matlab:opengl('problems')">here</a>.]
Fontconfig warning: "/usr/share/fontconfig/conf.avail/05-reset-dirs-sample.conf", line 6: unknown element "reset-dirs"
Fontconfig warning: "/usr/share/fontconfig/conf.avail/05-reset-dirs-sample.conf", line 6: unknown element "reset-dirs"
Посмотрим на результаты в Simulink:
mat"whos" # Вывести все переменные, хранящиеся в рабочей области
>> >> >> Name Size Bytes Class Attributes
SimulationSteps 101x1 808 double
SysOutput 1x1 6800 timeseries
matlab_jl_has_ans 1x1 8 double
p 1x141147 282294 char
# Чтение выхода модели
sim = mat"SysOutput.Data";
# Построение графиков
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")
Теперь построим графики разности выходных данных Simulink и Engee, а также рассчитаем среднее значение погрешности.
plot(Sim_data-Eng_data)
print("Погрешность: " * string((sum(abs.(Sim_data-Eng_data)))/length(Eng_data)))
Погрешность: 5.072184154743073
Как мы видим из графиков, представленных выше, и результата подсчета средней погрешности, модели работают практически идентично.
Вывод
В этом примере мы реализовали эквалайзер, а также сравнили возможности Engee относительно моделирования в Simulink и показали опции подключения ядра MATLAB для решения задач внутри среды разработки Engee.