From 03dbc7ba2c914b9d9b482e02d37e2d2b4c003400 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Fri, 26 Apr 2024 16:50:09 +0300 Subject: [PATCH] Tools: Tune: EQ: Normalize IIR and FIR separately This allows more freedom to scale the equalizers. Common criteria resulted with safe scaling to unnecessarily silent result or risk for audible clipping in the equalizer. Signed-off-by: Seppo Ingalsuo --- tools/tune/eq/cmocka_data_eq_iir.m | 4 ++-- tools/tune/eq/eq_defaults.m | 6 +++-- tools/tune/eq/eq_norm.m | 33 +++++++++++++++------------ tools/tune/eq/example_fir_eq.m | 12 +++++----- tools/tune/eq/example_iir_bandsplit.m | 8 +++---- tools/tune/eq/example_iir_eq.m | 16 ++++++------- tools/tune/eq/example_spk_eq.m | 6 +++-- tools/tune/eq/gui.m | 9 ++++---- 8 files changed, 50 insertions(+), 44 deletions(-) diff --git a/tools/tune/eq/cmocka_data_eq_iir.m b/tools/tune/eq/cmocka_data_eq_iir.m index dcab982dd..622849ba5 100644 --- a/tools/tune/eq/cmocka_data_eq_iir.m +++ b/tools/tune/eq/cmocka_data_eq_iir.m @@ -87,8 +87,8 @@ function eq = test_response(fn, vn, fs) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = 'peak'; -eq.norm_offs_db = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 1; %% Parametric EQ eq.peq = [ ... diff --git a/tools/tune/eq/eq_defaults.m b/tools/tune/eq/eq_defaults.m index 771009dc5..15b8cf90f 100644 --- a/tools/tune/eq/eq_defaults.m +++ b/tools/tune/eq/eq_defaults.m @@ -109,7 +109,9 @@ p.fir_compensate_iir = 1; p.p_fmin = 10; p.p_fmax = 30e3; p.name = ''; -p.norm_type = 'loudness'; % loudness/peak/1k -p.norm_offs_db = 0; +p.iir_norm_type = 'loudness'; % loudness/peak/1k +p.iir_norm_offs_db = 0; +p.fir_norm_type = 'loudness'; % loudness/peak/1k +p.fir_norm_offs_db = 0; end diff --git a/tools/tune/eq/eq_norm.m b/tools/tune/eq/eq_norm.m index 47b40d9a5..ec11046a3 100644 --- a/tools/tune/eq/eq_norm.m +++ b/tools/tune/eq/eq_norm.m @@ -40,34 +40,37 @@ m_max_fir = max(eq.fir_eq_db); m_max_iir = max(eq.iir_eq_db); sens_fir = sum(m_lin_fir.*w_lin)/sum(w_lin); sens_iir = sum(m_lin_iir.*w_lin)/sum(w_lin); -g_offs = 10^(eq.norm_offs_db/20); +g_offs_iir = 10^(eq.iir_norm_offs_db/20); +g_offs_fir = 10^(eq.fir_norm_offs_db/20); %% Determine scaling gain -switch lower(eq.norm_type) +switch lower(eq.iir_norm_type) case 'loudness' - g_fir = 1/sens_fir; g_iir = 1/sens_iir; case '1k' - g_fir = 1/m_lin_fir(i1k); g_iir = 1/m_lin_iir(i1k); - case 'peak' - g_fir = 10^(-m_max_fir/20); g_iir = 10^(-m_max_iir/20); otherwise - error('Requested normalization is not supported'); + error('Requested IIR normalization is not supported'); +end +switch lower(eq.fir_norm_type) + case 'loudness' + g_fir = 1/sens_fir; + case '1k' + g_fir = 1/m_lin_fir(i1k); + case 'peak' + g_fir = 10^(-m_max_fir/20); + otherwise + error('Requested FIR normalization is not supported'); end %% Adjust FIR and IIR gains if enabled -if eq.enable_fir && eq.enable_iir - eq.b_fir = eq.b_fir * g_fir * g_offs; - eq.p_k = eq.p_k * g_iir * g_offs; +if eq.enable_fir + eq.b_fir = eq.b_fir * g_fir * g_offs_fir; end -if eq.enable_fir && eq.enable_iir == 0 - eq.b_fir = eq.b_fir * g_fir * g_offs; -end -if eq.enable_fir == 0 && eq.enable_iir - eq.p_k = eq.p_k * g_iir * g_offs; +if eq.enable_iir + eq.p_k = eq.p_k * g_iir * g_offs_iir; end %% Re-compute response after adjusting gain diff --git a/tools/tune/eq/example_fir_eq.m b/tools/tune/eq/example_fir_eq.m index 8ff092db2..f3a26f5d8 100644 --- a/tools/tune/eq/example_fir_eq.m +++ b/tools/tune/eq/example_fir_eq.m @@ -173,10 +173,10 @@ m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... %% Design EQ eq = eq_defaults(); eq.fs = fs; -eq.target_f = f; % Set EQ frequency response target: frequencies Hz -eq.target_m_db = m; % Set EQ frequency response target: magnitudues dB -eq.norm_type = 'loudness'; % Normalize criteria can be loudness/peak/1k -eq.norm_offs_db = 0; % Offset in dB to normalize +eq.target_f = f; % Set EQ frequency response target: frequencies Hz +eq.target_m_db = m; % Set EQ frequency response target: magnitudues dB +eq.fir_norm_type = 'loudness'; % Normalize criteria can be loudness/peak/1k +eq.fir_norm_offs_db = 0; % Offset in dB to normalize eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one eq.fir_beta = 4.0; % Use with care, low value can corrupt @@ -203,8 +203,8 @@ eq.parametric_target_response = [ ... %% Design EQ eq.fs = fs; -eq.norm_type = 'peak'; % Can be loudness/peak/1k to select normalize criteria -eq.norm_offs_db = 0; % E.g. -1 would leave 1 dB headroom if used with peak +eq.fir_norm_type = 'peak'; % Can be loudness/peak/1k to select normalize criteria +eq.fir_norm_offs_db = 0; % E.g. -1 would leave 1 dB headroom if used with peak eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one eq.fir_beta = 3.5; % Use with care, low value can corrupt diff --git a/tools/tune/eq/example_iir_bandsplit.m b/tools/tune/eq/example_iir_bandsplit.m index 86fec4486..fe1e3e87c 100644 --- a/tools/tune/eq/example_iir_bandsplit.m +++ b/tools/tune/eq/example_iir_bandsplit.m @@ -62,8 +62,8 @@ function eq = lo_band_iir(fs) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = 'peak'; -eq.norm_offs_db = 0; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; %% Manually setup low-shelf and high shelf parametric equalizers % @@ -95,8 +95,8 @@ function eq = hi_band_iir(fs) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = 'peak'; -eq.norm_offs_db = 0; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; %% Manually setup low-shelf and high shelf parametric equalizers % diff --git a/tools/tune/eq/example_iir_eq.m b/tools/tune/eq/example_iir_eq.m index ac2a43b14..94b1e7915 100644 --- a/tools/tune/eq/example_iir_eq.m +++ b/tools/tune/eq/example_iir_eq.m @@ -267,8 +267,8 @@ eq.fs = fs; eq.target_f = f; eq.target_m_db = m; eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; %% Manually setup low-shelf and high shelf parametric equalizers % @@ -300,8 +300,8 @@ function eq = hp_iir_eq(fs, fc, gain_db) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = '1k'; -eq.norm_offs_db = gain_db; +eq.iir_norm_type = '1k'; +eq.iir_norm_offs_db = gain_db; % Design eq.peq = [ eq.PEQ_HP2 fc NaN NaN ]; @@ -316,8 +316,8 @@ function eq = bassboost_iir_eq(fs) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; % Design eq.peq = [ ... @@ -335,8 +335,8 @@ function eq = bandpass_iir_eq(fs) eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; % Design EQ eq.peq = [ ... diff --git a/tools/tune/eq/example_spk_eq.m b/tools/tune/eq/example_spk_eq.m index 291d880af..3a360fcd2 100644 --- a/tools/tune/eq/example_spk_eq.m +++ b/tools/tune/eq/example_spk_eq.m @@ -46,8 +46,10 @@ eq = eq_defaults(); eq.fs = fs; % Default sample rate in SOF eq.enable_fir = 1; % Try enabling and disabling FIR part eq.enable_iir = 1; % Try enabling and disabling IIR part -eq.norm_type = 'peak'; % Scale filters to have peak at 0 dB -eq.norm_offs_db = 0; % Can be used to control gain +eq.iir_norm_type = 'peak'; % Scale filters to have peak at 0 dB +eq.iir_norm_offs_db = 0; % Can be used to control gain +eq.fir_norm_type = 'peak'; % Scale filters to have peak at 0 dB +eq.fir_norm_offs_db = 0; % Can be used to control gain eq.p_fmin = 100; % With this data start plots from 100 Hz eq.p_fmax = 20e3; % and end to 20 kHz. diff --git a/tools/tune/eq/gui.m b/tools/tune/eq/gui.m index 9dbc96454..cf39b984c 100644 --- a/tools/tune/eq/gui.m +++ b/tools/tune/eq/gui.m @@ -464,15 +464,15 @@ function push_config(h, evnt) eq_left = eq_defaults(); eq_left.enable_iir = 1; eq_left.peq = build_peq(1, EQ); - eq_left.norm_type = 'peak'; - eq_left.norm_offs_db = 0; + eq_left.iir_norm_type = 'peak'; + eq_left.iir_norm_offs_db = 0; eq_left.fs = get_config().Fs; eq_right = eq_defaults(); eq_right.enable_iir = 1; eq_right.peq = build_peq(2, EQ); - eq_right.norm_type = 'peak'; - eq_right.norm_offs_db = 0; + eq_right.iir_norm_type = 'peak'; + eq_right.iir_norm_offs_db = 0; eq_right.fs = get_config().Fs; eq_left = eq_compute(eq_left); @@ -504,4 +504,3 @@ function update_control_elements(section, EQ) set_udata_field(section.type.dropdown, "EQ", EQ); set_udata_field(section.enable_switch, "EQ", EQ); end -