Документация Engee

Параметрический аудиоэквалайзер

В данной демонстрации мы разберём параметрический аудиоэквалайзер, который поддерживает три настраиваемые полосы. Каждая полоса реализована с использованием различной структуры биквадратного фильтра. image.png

Эквалайзер — радиоэлектронное устройство или компьютерная программа, позволяющия избирательно корректировать амплитуду сигнала в зависимости от частотных характеристик.

Также в этой демонстрации мы сравним работу моделей 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 блока фильтрации с коэффициентами фильтра на верхнем уровне, и оценщик дискретной передаточной функции. На рисунках ниже показана модель и настройки оценщика.

image.png

image_2.png

Если рассматривать каждый из фильтров, то они реализованы однотипно и включают в себя дискретный фильтр блок выборки коэффициентов и биквадратный фильтр.

image_3.png

Теперь перейдем к запуску и сравнению реализации данной модели в 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")

interactive-scripts/images/dsp_Equalizer_demo/bcb237082df407aa7b2b0f95842cbc98b0d39191

Сравним результаты моделирования в 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")

interactive-scripts/images/dsp_Equalizer_demo/e547015c4d636c3a4c6e853301925692d2ba2361

Теперь построим графики разности выходных данных Simulink и Engee, а также рассчитаем среднее значение погрешности.

plot(Sim_data-Eng_data)

interactive-scripts/images/dsp_Equalizer_demo/a00df57c0bacae6331cf2e1dbef479e35ea9246d

print("Погрешность: " * string((sum(abs.(Sim_data-Eng_data)))/length(Eng_data)))
Погрешность: 5.072184154743073

Как мы видим из графиков, представленных выше, и результата подсчета средней погрешности, модели работают практически идентично.

Вывод

В этом примере мы реализовали эквалайзер, а также сравнили возможности Engee относительно моделирования в Simulink и показали опции подключения ядра MATLAB для решения задач внутри среды разработки Engee.

Блоки, использованные в примере