1%% Design demo EQs and bundle them to parameter block 2 3% SPDX-License-Identifier: BSD-3-Clause 4% 5% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. 6% 7% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> 8 9function example_fir_eq() 10 11%% Common definitions 12fs = 48e3; 13tpath = '../../topology/topology1/m4'; 14cpath = '../../ctl'; 15priv = 'DEF_EQFIR_PRIV'; 16 17%% ------------------- 18%% Example 1: Loudness 19%% ------------------- 20blob_fn = fullfile(cpath, 'eq_fir_loudness.bin'); 21alsa_fn = fullfile(cpath, 'eq_fir_loudness.txt'); 22tplg_fn = fullfile(tpath, 'eq_fir_coef_loudness.m4'); 23comment = 'Loudness effect, created with example_fir_eq.m'; 24 25%% Design FIR loudness equalizer 26eq_loud = loudness_fir_eq(fs); 27 28%% Define a passthru EQ with one tap 29b_pass = 1; 30 31%% Quantize filter coefficients for both equalizers 32bq_pass = eq_fir_blob_quant(b_pass); 33bq_loud = eq_fir_blob_quant(eq_loud.b_fir); 34 35%% Build blob 36channels_in_config = 4; % Setup max 4 channels EQ 37assign_response = [1 1 1 1]; % Switch to response #1 38num_responses = 2; % Two responses pass, loud 39bm = eq_fir_blob_merge(channels_in_config, ... 40 num_responses, ... 41 assign_response, ... 42 [ bq_pass bq_loud ]); 43 44%% Pack and write file 45eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, priv, comment); 46 47%% ------------------- 48%% Example 2: Mid boost 49%% ------------------- 50blob_fn = fullfile(cpath, 'eq_fir_mid.bin'); 51alsa_fn = fullfile(cpath, 'eq_fir_mid.txt'); 52tplg_fn = fullfile(tpath, 'eq_fir_coef_mid.m4'); 53comment = 'Mid boost, created with example_fir_eq.m'; 54 55%% Define mid frequencies boost EQ 56eq_mid = midboost_fir_eq(fs); 57 58%% Quantize filter coefficients for both equalizers 59bq_pass = eq_fir_blob_quant(eq_mid.b_fir); 60 61%% Build blob 62channels_in_config = 2; % Setup max 2 channels EQ 63assign_response = [0 0]; % Switch to response #0 64num_responses = 1; % One response: pass 65bm = eq_fir_blob_merge(channels_in_config, ... 66 num_responses, ... 67 assign_response, ... 68 bq_pass); 69 70%% Pack and write file 71eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, priv, comment); 72 73%% ------------------- 74%% Example 3: Flat EQ 75%% ------------------- 76blob_fn = fullfile(cpath, 'eq_fir_flat.bin'); 77alsa_fn = fullfile(cpath, 'eq_fir_flat.txt'); 78tplg_fn = fullfile(tpath, 'eq_fir_coef_flat.m4'); 79comment = 'Flat response, created with example_fir_eq.m'; 80 81%% Define a passthru EQ with one tap 82b_pass = 1; 83 84%% Quantize filter coefficients for both equalizers 85bq_pass = eq_fir_blob_quant(b_pass); 86 87%% Build blob 88channels_in_config = 2; % Setup max 2 channels EQ 89assign_response = [0 0]; % Switch to response #0 90num_responses = 1; % One response: pass 91bm = eq_fir_blob_merge(channels_in_config, ... 92 num_responses, ... 93 assign_response, ... 94 bq_pass); 95 96%% Pack and write file 97eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, priv, comment); 98 99%% -------------------------- 100%% Example 4: Pass-through EQ 101%% -------------------------- 102blob_fn = fullfile(cpath, 'eq_fir_pass.bin'); 103alsa_fn = fullfile(cpath, 'eq_fir_pass.txt'); 104tplg_fn = fullfile(tpath, 'eq_fir_coef_pass.m4'); 105comment = 'Pass-through response, created with example_fir_eq.m'; 106 107%% Define a passthru EQ with one tap 108b_pass = 1; 109 110%% Quantize filter coefficients for both equalizers 111bq_pass = eq_fir_blob_quant(b_pass); 112 113%% Build blob 114channels_in_config = 2; % Setup max 2 channels EQ 115assign_response = [-1 -1]; % Switch to response #0 116num_responses = 1; % One response: pass 117bm = eq_fir_blob_merge(channels_in_config, ... 118 num_responses, ... 119 assign_response, ... 120 bq_pass); 121 122%% Pack and write file 123eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, priv, comment); 124 125 126%% -------------------------- 127%% Done. 128%% -------------------------- 129 130end 131 132%% ------------------- 133%% EQ design functions 134%% ------------------- 135 136function eq = loudness_fir_eq(fs) 137 138%% Derived from Fletcher-Munson curves for 80 and 60 phon 139f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ... 140 68,72,76,81,85,90,96,102,108,114,121,128,136,144,153,162,171, ... 141 182,192,204,216,229,243,257,273,289,306,324,344,364,386,409, ... 142 434,460,487,516,547,580,614,651,690,731,775,821,870,922,977, ... 143 1036,1098,1163,1233,1307,1385,1467,1555,1648,1747,1851,1962, ... 144 2079,2203,2335,2474,2622,2779,2945,3121,3308,3505,3715,3937, ... 145 4172,4421,4686,4966,5263,5577,5910,6264,6638,7035,7455,7901, ... 146 8373,8873,9404,9966,10561,11193,11861,12570,13322,14118,14962, ... 147 15856,16803,17808,18872,20000]; 148 149m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... 150 -1.31,-1.46,-1.61,-1.76,-1.91,-2.07,-2.24,-2.43,-2.64,-2.85, ... 151 -3.04,-3.21,-3.35,-3.48,-3.62,-3.78,-3.96,-4.16,-4.35,-4.54, ... 152 -4.72,-4.90,-5.08,-5.26,-5.45,-5.64,-5.83,-6.02,-6.19,-6.37, ... 153 -6.57,-6.77,-6.98,-7.19,-7.40,-7.58,-7.76,-7.92,-8.08,-8.25, ... 154 -8.43,-8.60,-8.76,-8.92,-9.08,-9.23,-9.38,-9.54,-9.69,-9.84, ... 155 -9.97,-10.09,-10.18,-10.26,-10.33,-10.38,-10.43,-10.48,-10.54, ... 156 -10.61,-10.70,-10.78,-10.85,-10.91,-10.95,-10.98,-11.02, ... 157 -11.05,-11.07,-11.10,-11.11,-11.11,-11.10,-11.10,-11.11, ... 158 -11.14,-11.17,-11.20,-11.21,-11.22,-11.21,-11.20,-11.20, ... 159 -11.21,-11.21,-11.20,-11.17,-11.11,-11.02,-10.91,-10.78, ... 160 -10.63,-10.46,-10.25,-10.00,-9.72,-9.39,-9.02,-8.62,-8.19, ... 161 -7.73,-7.25,-6.75,-6.25,-5.75,-5.28,-4.87,-4.54,-4.33,-4.30]; 162 163%% Design EQ 164eq = eq_defaults(); 165eq.fs = fs; 166eq.target_f = f; % Set EQ frequency response target: frequencies Hz 167eq.target_m_db = m; % Set EQ frequency response target: magnitudues dB 168eq.norm_type = 'loudness'; % Normalize criteria can be loudness/peak/1k 169eq.norm_offs_db = 0; % Offset in dB to normalize 170 171eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one 172eq.fir_beta = 4.0; % Use with care, low value can corrupt 173eq.fir_length = 86; % Gives just < 292 bytes 174eq.fir_autoband = 0; % Select manually frequency limits 175eq.fmin_fir = 100; % Equalization starts from 100 Hz 176eq.fmax_fir = 20e3; % Equalization ends at 20 kHz 177eq.fir_minph = 1; % Check result carefully if 1 is used, 0 is safe 178eq = eq_compute(eq); 179 180%% Plot 181eq_plot(eq); 182 183end 184 185function eq = midboost_fir_eq(fs) 186 187eq = eq_defaults(); 188 189eq.parametric_target_response = [ ... 190 eq.PEQ_LS2 1200 -12 NaN ; ... 191 eq.PEQ_HS2 7000 -12 NaN ; ... 192 ]; 193 194%% Design EQ 195eq.fs = fs; 196eq.norm_type = 'peak'; % Can be loudness/peak/1k to select normalize criteria 197eq.norm_offs_db = 0; % E.g. -1 would leave 1 dB headroom if used with peak 198 199eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one 200eq.fir_beta = 3.5; % Use with care, low value can corrupt 201eq.fir_length = 39; % At limit of xtensa-gcc build speed 202eq.fir_autoband = 0; % Select manually frequency limits 203eq.fmin_fir = 100; % Equalization starts from 100 Hz 204eq.fmax_fir = 20e3; % Equalization ends at 20 kHz 205eq.fir_minph = 1; % If no linear phase required can test with 1 206eq = eq_compute(eq); 207 208%% Plot 209eq_plot(eq); 210 211end 212 213% Pack and write file common function for all exports 214function eq_pack_export(bm, bin_fn, ascii_fn, tplg_fn, priv, note) 215 216bp = eq_fir_blob_pack(bm); 217 218if ~isempty(bin_fn) 219 eq_blob_write(bin_fn, bp); 220end 221 222if ~isempty(ascii_fn) 223 eq_alsactl_write(ascii_fn, bp); 224end 225 226if ~isempty(tplg_fn) 227 eq_tplg_write(tplg_fn, bp, priv, note); 228end 229 230end 231