EQ: Improve example equalizer design scripts

This patch cleans up the scripts and improves the accuracy of speaker
case with more carefully set manual equalizer design parameters.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This commit is contained in:
Seppo Ingalsuo 2018-08-09 17:04:09 +03:00
parent 684737cf5d
commit 085b68058b
3 changed files with 42 additions and 48 deletions

View File

@ -36,17 +36,16 @@ ascii_blob_fn = 'example_fir_eq.txt';
binary_blob_fn = 'example_fir_eq.blob';
endian = 'little';
fs = 48e3;
bits = 16;
%% Design FIR loudness equalizer
eq_loud = loudness_fir_eq(fs, 1);
eq_loud = loudness_fir_eq(fs);
%% Define a passthru EQ with one tap
b_pass = 1;
%% Quantize filter coefficients for both equalizers
bq_pass = eq_fir_blob_quant(b_pass, bits);
bq_loud = eq_fir_blob_quant(eq_loud.b_fir, bits);
bq_pass = eq_fir_blob_quant(b_pass);
bq_loud = eq_fir_blob_quant(eq_loud.b_fir);
%% Build blob
platform_max_channels = 4; % Setup max 4 channels EQ
@ -64,14 +63,7 @@ eq_blob_write(binary_blob_fn, bp);
end
function eq = loudness_fir_eq(fs, fn)
if nargin < 2
fn = 1;
end
if nargin < 1
fs = 48e3;
end
function eq = loudness_fir_eq(fs)
%% Derived from Fletcher-Munson curves for 80 and 60 phon
f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ...
@ -103,17 +95,19 @@ eq = eq_defaults();
eq.fs = fs;
eq.target_f = f; % Set EQ frequency response target: frequency vector
eq.target_m_db = m; % Set EQ frequency response target: magnitude
eq.norm_type = 'loudness'; % 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.enable_fir = 1; % By default both FIR and IIR disabled, enable one
eq.fir_beta = 3.5; % Use with care, low value can corrupt
eq.fir_length = 107; % Gives just < 255 bytes
eq.fir_autoband = 0; % Select manually frequency limits
eq.fmin_fir = 100; % Equalization starts from 100 Hz
eq.fmax_fir = 20e3; % Equalization ends at 20 kHz
eq.fir_minph = 1; % If no linear phase required, check result carefully if 1
eq.norm_type = 'loudness'; % 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 = eq_compute(eq);
%% Plot
eq_plot(eq, fn);
eq_plot(eq);
end

View File

@ -38,7 +38,7 @@ endian = 'little';
fs = 48e3;
%% Design IIR loudness equalizer
eq_loud = loudness_iir_eq(fs, 2);
eq_loud = loudness_iir_eq(fs);
%% Define a passthru IIR EQ equalizer
b_pass = [1 0 0];
@ -66,14 +66,7 @@ end
%%
function eq = loudness_iir_eq(fs, fn)
if nargin < 2
fn = 1;
end
if nargin < 1
fs = 48e3;
end
function eq = loudness_iir_eq(fs)
%% Derived from Fletcher-Munson curves for 80 and 60 phon
f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ...
@ -105,12 +98,10 @@ eq = eq_defaults();
eq.fs = fs;
eq.target_f = f;
eq.target_m_db = m;
eq.enable_fir = 0;
eq.enable_iir = 1;
eq.norm_type = 'loudness';
eq.norm_offs_db = 0;
%% Manually setup low-shelf and high shelf parametric equalizers
%
% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1,
@ -131,6 +122,6 @@ eq.peq = [ ...
eq = eq_compute(eq);
%% Plot
eq_plot(eq, fn);
eq_plot(eq);
end

View File

@ -1,3 +1,5 @@
function example_spk_eq()
%% Design an example speaker equalizer with the provided sample data
% This equalizer by default uses a FIR and IIR components those should be
% both in the speaker pipeline.
@ -42,7 +44,7 @@ eq = eq_defaults();
eq.fs = 48e3; % 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 = 'loudness'; % Preserve loudness approximately
eq.norm_type = 'peak'; % Scale filters to have peak at 0 dB
eq.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.
@ -98,8 +100,8 @@ eq.raw_m_db = [ ...
if eq.enable_iir;
eq.peq = [ ...
eq.PEQ_HP2 100 NaN NaN; ...
eq.PEQ_PN2 1480 -6 2.0; ...
eq.PEQ_PN2 7600 -12 1.3; ...
eq.PEQ_PN2 1480 -7 2.0; ...
eq.PEQ_PN2 7600 -11 1.3; ...
eq.PEQ_LP2 14500 NaN NaN; ...
];
end
@ -111,8 +113,8 @@ if eq.enable_fir
eq.fir_beta = 4;
eq.fir_length = 63;
eq.fir_autoband = 0;
eq.fmin_fir = 1000;
eq.fmax_fir = 13e3;
eq.fmin_fir = 900;
eq.fmax_fir = 10700;
end
%% Design EQ
@ -125,21 +127,28 @@ eq_plot(eq, 1);
platform_max_channels = 2; % Identical two speakers
assign_response = [0 0]; % Switch to response #0
num_responses = 1; % Single response
bq_fir = eq_fir_blob_quant(eq.b_fir);
bm_fir = eq_fir_blob_merge(platform_max_channels, ...
num_responses, ...
assign_response, ...
[ bq_fir ]);
bp_fir = eq_fir_blob_pack(bm_fir);
eq_alsactl_write('example_spk_eq_fir.txt', bp_fir);
eq_blob_write('example_spk_eq_fir.blob', bp_fir);
if eq.enable_fir
bq_fir = eq_fir_blob_quant(eq.b_fir);
bm_fir = eq_fir_blob_merge(platform_max_channels, ...
num_responses, ...
assign_response, ...
[ bq_fir ]);
bp_fir = eq_fir_blob_pack(bm_fir);
eq_alsactl_write('example_spk_eq_fir.txt', bp_fir);
eq_blob_write('example_spk_eq_fir.blob', bp_fir);
end
%% Export IIR part
bq_iir = eq_iir_blob_quant(eq.b_p, eq.a_p);
bm_iir = eq_iir_blob_merge(platform_max_channels, ...
num_responses, ...
assign_response, ...
[ bq_iir ]);
bp_iir = eq_iir_blob_pack(bm_iir);
eq_alsactl_write('example_spk_eq_iir.txt', bp_iir);
eq_blob_write('example_spk_eq_iir.blob', bp_iir);
if eq.enable_iir
bq_iir = eq_iir_blob_quant(eq.b_p, eq.a_p);
bm_iir = eq_iir_blob_merge(platform_max_channels, ...
num_responses, ...
assign_response, ...
[ bq_iir ]);
bp_iir = eq_iir_blob_pack(bm_iir);
eq_alsactl_write('example_spk_eq_iir.txt', bp_iir);
eq_blob_write('example_spk_eq_iir.blob', bp_iir);
end
end