Engee documentation
Notebook

Parametric Audio Equaliser

In this demonstration we will understand a parametric audio equaliser that supports three adjustable bands. Each band is implemented using a different biquadratic filter structure. image.png

An equaliser is a radio-electronic device or computer program that allows selective correction of signal amplitude depending on frequency characteristics.

Also in this demonstration we will compare the work of Engee and MATLAB models. For this purpose, we will connect the necessary libraries and consider the structure of the implemented model.

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);"

The model consists of two main blocks: the equaliser itself, which includes 3 filtering blocks with filter coefficients at the upper level, and the discrete transfer function estimator. Figures below show the model and the estimator settings.

image.png

image_2.png

If we consider each of the filters, they are implemented in the same way and include a discrete filter coefficient sampling unit and a biquadratic filter.

image_3.png

Now let us proceed to running and comparing the implementation of this model in Engee and Simulink.

Running and analysing the Engee model

Let's take a look at the results of modelling in 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]:
rum_model (generic function with 1 method)
In [ ]:
# Запуск модели
rum_model("Equalizer","/user/start/examples/dsp/equalizer")
Building...
Progress 100%
Out[0]:
Dict{String, DataFrame} with 1 entry:
  "out" => 101×2 DataFrame
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]:
parse_csv_engee (generic function with 1 method)
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]:

Let's compare the simulation results in Engee and Simulink. To do this, let's first run a simulation of the model.

In [ ]:
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"

Let's look at the results in Simulink:

In [ ]:
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                    

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]:

Now plot the difference between the outputs of Simulink and Engee, and calculate the average error.

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

As we can see from the graphs above and the result of the average error calculation, the models work almost identically.

Conclusion

In this example, we have implemented EQ and compared the capabilities of Engee with respect to modelling in Simulink and shown the options for connecting the MATLAB kernel to solve problems within the Engee development environment.