Skip to content

Commit 106f443

Browse files
Audio: Enhancing audio quality tests for device testing
For the purpose of remote device testing, this check-in adds a correction to the scripts that evaluate gain, frequency responsiveness, total harmonic distortion plus noise, and dynamic range. The threshold scale has been defined and the decibel full scale computation has been made easier using new scripts. You require Octave or Matlab. The scripts now operate properly in both Matlab and octave. The user account, audio device, audio format, and capture sound card audio device and audio format for the remote device must be modified in the configuration file sof test perf config.m. Signed-off-by: shastry <malladi.sastry@intel.com>
1 parent 95d6499 commit 106f443

32 files changed

Lines changed: 270 additions & 188 deletions

tools/test/audio/process_test.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@
231231

232232
% Measure
233233
test = thdnf_mask(test, t);
234+
235+
% test = thdnf_mask(test); % correction
234236
test = thdnf_test_measure(test);
235237

236238
% For EQ use the -20dBFS result and ignore possible -1 dBFS fail
@@ -357,8 +359,8 @@
357359
% Test constraints
358360
test.f_start = 20;
359361
test.f_end = test.fs * 0.41667; % 20 kHz @ 48 kHz
360-
test.fu = test.fs * 0.41667; % 20 kHz @ 48 kHz
361-
test.f_max = 0.999*t.fs/2; % Measure up to min. Nyquist frequency
362+
test.fu = test.fs * 0.41667; % 20 kHz @ 48 kHz, duplicate variable/ instead use test.f_end
363+
test.f_max = 0.999*test.fs/2; % Measure up to min. Nyquist frequency
362364
test.fs1 = test.fs;
363365
test.fs2 = test.fs;
364366

tools/test/audio/sof_test_perf.m

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
%% Plotting
3131
test.plot_close_windows = 1; % Workaround for visible windows if Octave hangs
32-
test.plot_visible = 'off'; % Use off for batch tests and on for interactive
32+
% test.plot_visible = 'off'; % Use off for batch tests and on for interactive
33+
test.plot_visible = 'on'; % Use off for batch tests and on for interactive
3334
test.plot_passband_zoom = 1; % Do a small plot box for only passband
3435
test.plot_channels_combine = 1; % Plot channels into same figure
3536

@@ -46,8 +47,6 @@
4647
test = get_config(test);
4748

4849
%% Run tests
49-
fail = 0;
50-
pass = 0;
5150
test.tf = [];
5251

5352
% Check that the configuration has been edited
@@ -68,6 +67,9 @@
6867

6968
%% Total harmonic distortion plus noise
7069
[tf(3), thdnf_low, thdnf_high] = thdnf_test(test);
70+
71+
%% Dynamic range
72+
[tf(4), dynamic_range]= dr_test(test);
7173
end
7274

7375
%% Print results
@@ -81,6 +83,7 @@
8183
print_val(test, tf(2), fr_3db_hz / 1000, 'kHz', '-3 dB frequency');
8284
print_val(test, tf(3), thdnf_low, 'dB', 'THD+N -20 dBFS');
8385
print_val(test, tf(3), thdnf_high, 'dB', 'THD+N -1 dBFS');
86+
print_val(test, tf(4), dynamic_range, 'dB', 'dr_db_min');
8487
else
8588
fprintf(1, '\n');
8689
fprintf(1, 'Warning: The gain test must pass before other tests are executed.\n');
@@ -128,8 +131,8 @@
128131
%% Reference: AES17 6.2.3 Frequency response
129132
c1 = 20/48;
130133
c2 = 23.9/48;
131-
test.f_lo = 20; % Measure start at 20 Hz
132-
test.f_hi = c1 * test.fs; % Measure end e.g. at 20 kHz
134+
test.fr_lo = 20; % Measure start at 20 Hz
135+
test.fr_hi = c1 * test.fs; % Measure end e.g. at 20 kHz
133136
test.f_max = c2 * test.fs; % Sweep max e.g. at 23.9 kHz
134137

135138
%% Create input file
@@ -144,7 +147,7 @@
144147

145148
fail = test.fail;
146149
fr_db = test.rp;
147-
fr_hz = [test.f_lo test.f_hi];
150+
fr_hz = [test.fr_lo test.fr_hi];
148151
fr_3db_hz = test.fr3db_hz;
149152
delete_check(test.files_delete, test.fn_in);
150153
delete_check(test.files_delete, test.fn_out);
@@ -182,6 +185,28 @@
182185

183186
end
184187

188+
%% Reference: AES17 6.4.1 Dynamic range
189+
function [fail, dr_db] = dr_test(t)
190+
191+
test = test_defaults(t);
192+
193+
% Create input file
194+
test = dr_test_input(test);
195+
196+
% Run test
197+
% test = test_run_process(test, t);
198+
test = remote_test_run(test);
199+
200+
% Measure
201+
test = dr_test_measure(test);
202+
203+
% Get output parameters
204+
fail = test.fail;
205+
dr_db = test.dr_db;
206+
delete_check(test.files_delete, test.fn_in);
207+
delete_check(test.files_delete, test.fn_out);
208+
209+
end
185210
%%
186211
%% Utilities
187212
%%

tools/test/audio/sof_test_perf_config.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
test.fr_rp_max_db = 1.0; % Upper limit for p-p ripple in dB
4242
test.plot_fr_axis = [10 30e3 -4 1]; % Plot xmin, xmax, ymin, ymax
4343

44+
test.fr_mask_flo = [];
45+
test.fr_mask_fhi = [];
46+
test.fr_mask_mlo = [];
47+
test.fr_mask_mhi = [];
4448
%% THD+N test case
4549
test.thdnf_max = -55; % Upper limit for THD+N
4650
test.plot_thdn_axis = [10 30e3 -90 -40]; % Plot xmin xmax ymin ymax
51+
%% dynamic range test case
52+
test.dr_db_min = 70; % Min. DR,80dB

tools/test/audio/std_utils/dr_test_measure.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
level_in = test.a_db;
5858
level_out = level_dbfs(y);
5959
level_final = level_dbfs(y_n);
60-
test.dr_db = level_out-level_final-test.a_db;
60+
test.dr_db = level_out - level_final - test.a_db;
6161
fprintf('DR = %5.1f dB\n', test.dr_db);
6262
if 0
6363
plot(y);

tools/test/audio/std_utils/fr_test_input.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
test.tr = 10e-3; % Gain ramp time for tones
8989
test.sm = 3; % Seek start marker from 3s from start
9090
test.em = 3; % Seek end marker from 3s from end
91-
test.mt = 0.1; % Error if marker positions delta is greater than 0.1s
91+
test.mt = 2; % Error if marker positions delta is greater than 0.1s
9292
test.tc = 10; % Min. 10 cycles of sine wave for a frequency
9393
t_min = 0.1;
9494
% Use t_min or min cycles count as tone length

tools/test/audio/std_utils/fr_test_measure.m

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,17 @@
3333
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
3434

3535
%% Check if upper and lower mask is defined
36-
if length(test.fr_mask_flo) || length(test.fr_mask_fhi)
36+
if ~isempty(test.fr_mask_flo) || ~isempty(test.fr_mask_fhi)
3737
test.fr_lo = 0;
3838
test.fr_hi = 0;
3939
end
4040
if test.fr_lo > 0 || test.fr_hi > 0
41-
test.fr_mask_flo = [];
42-
test.fr_mask_fhi = [];
43-
test.fr_mask_mlo = [];
44-
test.fr_mask_mhi = [];
41+
test.fr_mask_fhi = [20 test.f_max];
42+
test.fr_mask_flo = [200 400 3500 3600 ];
43+
for i = 1:test.nch
44+
test.fr_mask_mhi(:,i) = [ 1 1 ];
45+
test.fr_mask_mlo(:,i) = [-10 -1 -1 -10];
46+
end
4547
end
4648

4749
test.ph = [];
@@ -66,10 +68,10 @@
6668

6769
%% Find sync
6870
[d, nt, nt_use, nt_skip] = find_test_signal(x(:,j), test);
69-
if isempty(d)
70-
test.fail = 1;
71-
return
72-
end
71+
if isempty(d)
72+
test.fail = 1;
73+
return
74+
end
7375

7476
win = hamming(nt_use);
7577
m0 = zeros(test.nf,1);
@@ -87,16 +89,16 @@
8789
test.m(:,j) = m0 - m_offs;
8890

8991
%% Check pass/fail
90-
if test.fr_lo > 0 && test.fr_hi > 0 && ~isempty(test.fr_rp_max_db)
91-
idx0 = find(test.f < test.fr_hi);
92-
idx1 = find(test.f(idx0) > test.fr_lo);
93-
range_db = max(test.m(idx1,j))-min(test.m(idx1,j));
94-
test.rp(j) = range_db/2;
95-
if test.rp(j) > test.fr_rp_max_db
96-
fprintf('Failed response ch%d +/- %f dBpp (max +/- %f dB)\n', ...
97-
test.ch(j), test.rp(j), test.fr_rp_max_db);
98-
test.fail = 1;
99-
end
92+
if test.fr_lo > 0 && test.fr_hi > 0 && ~isempty(test.fr_rp_max_db)
93+
idx0 = find(test.f < test.fr_hi);
94+
idx1 = find(test.f(idx0) > test.fr_lo);
95+
range_db = max(test.m(idx1,j))-min(test.m(idx1,j));
96+
test.rp(j) = range_db/2;
97+
if test.rp(j) > test.fr_rp_max_db
98+
fprintf('Failed response ch%d +/- %f dBpp (max +/- %f dB)\n', ...
99+
test.ch(j), test.rp(j), test.fr_rp_max_db);
100+
test.fail = 1;
101+
end
100102
end
101103

102104
%% Find frequency response 3 dB 0-X Hz
@@ -109,7 +111,7 @@
109111
mask_hi = interp1(log(test.fr_mask_fhi), ...
110112
test.fr_mask_mhi(:,j), f_log, 'linear');
111113
over_mask = test.m(:,j)-mask_hi';
112-
idx = find(isnan(over_mask) == 0);
114+
idx = ~isnan(over_mask);
113115
[m_over_mask, io] = max(over_mask(idx));
114116
if m_over_mask > 0
115117
fprintf('Failed upper response mask around %.0f Hz\n', ...
@@ -122,7 +124,7 @@
122124
mask_lo = interp1(log(test.fr_mask_flo), ...
123125
test.fr_mask_mlo(:,j), f_log, 'linear');
124126
under_mask = mask_lo'-test.m(:,j);
125-
idx = find(isnan(under_mask) == 0);
127+
idx = ~isnan(under_mask);
126128
[m_under_mask, iu] = max(under_mask(idx));
127129
if m_under_mask > 0
128130
fprintf('Failed lower response mask around %.0f Hz\n', ...

tools/test/audio/std_utils/level_dbfs.m

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
% x - signal
77
%
88
% Output
9-
% dbfs - sigmal level in dBFS
9+
% dbfs - signal level in dBFS
1010
%
1111

1212
% SPDX-License-Identifier: BSD-3-Clause
1313
% Copyright(c) 2017 Intel Corporation. All rights reserved.
1414
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1515

1616
%% Reference AES 17 3.12.3
17-
level_ms = mean(x.^2);
18-
dbfs = 10*log10(level_ms + 1e-20) + 20*log10(sqrt(2));
17+
dbfs = 20*log10(rms(x) * sqrt(2));
1918

2019
end

tools/test/audio/std_utils/thdnf_test_input.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
test.tr = 10e-3; % Gain ramp time for tones
6060
test.sm = 3; % Seek start marker from 3s from start
6161
test.em = 3; % Seek end marker from 3s from end
62-
test.mt = 0.1; % Error if marker positions delta is greater than 0.1s
62+
test.mt = 2; % Error if marker positions delta is greater than 0.1s
6363
test.a_db = [-1 -20]; % -1 and -20 dBFS levels
6464
test.a = 10.^(test.a_db/20);
6565
test.tl = 4; % 3 seconds tone

tools/test/audio/std_utils/thdnf_test_measure.m

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,14 @@
77
test.ph = [];
88
test.fh = [];
99

10-
if isempty(test.thdnf_mask_f)
11-
if ~isempty(test.thdnf_max)
12-
test.thdnf_mask_f = [1 test.fs/2]; % Start from 1 due to log()
13-
test.thdnf_mask_hi = test.thdnf_max * [1 1];
14-
end
15-
else
16-
if ~isempty(test.thdnf_max)
17-
error('Set either thdnf_max or thdnf_mask_f & thdnf_mask_hi but not both');
18-
end
19-
if isempty(test.thdnf_mask_hi)
20-
error('thdnf_mask_hi must be set when thdnf_mask_f is defined');
21-
end
10+
if ~isempty(test.thdnf_max)
11+
test.thdnf_mask_f = [1 test.fs/2]; % Start from 1 due to log()
12+
test.thdnf_mask_hi = test.thdnf_max * [1 1];
13+
end
14+
if isempty(test.thdnf_max)
15+
error('Set either thdnf_max or thdnf_mask_f & thdnf_mask_hi but not both');
16+
elseif isempty(test.thdnf_mask_hi)
17+
error('thdnf_mask_hi must be set when thdnf_mask_f is defined');
2218
end
2319

2420
%% Reference: AES17 6.3.2 THD+N ratio vs frequency
@@ -76,16 +72,16 @@
7672
test.thdnf_high(:,i) = test.thdnf(:,1);
7773
test.thdnf_low(:,i) = test.thdnf(:,2);
7874

79-
fidx = find(test.thdnf(idx, 1) > mask_hi);
80-
if length(fidx) > 0
75+
fidx = find(test.thdnf(idx, 1) > mask_hi, 1);
76+
if ~isempty(fidx)
8177
fail_hi = 1;
8278
fprintf('Failed THD+N mask with high input.\n');
8379
else
8480
fail_hi = 0;
8581
end
8682

87-
fidx = find(test.thdnf(idx, 2) > mask_hi);
88-
if length(fidx) > 0
83+
fidx = find(test.thdnf(idx, 2) > mask_hi, 1);
84+
if ~isempty(fidx)
8985
fail_lo = 1;
9086
fprintf('Failed THD+N mask with low input.\n');
9187
else

tools/test/audio/test_utils/find_test_signal.m

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
nt = [];
2222
nt_use = [];
2323
nt_skip = [];
24-
24+
trace_en = false; % Enable to trace algirithm -analysis
2525
%% Use channel with strongest signal
2626
ch = select_channel(x0);
2727
x = x0(:, ch);
@@ -35,37 +35,66 @@
3535
y = x(1:n);
3636
[r, lags] = xcorr(y, s);
3737
r2 = r.^2;
38-
r2_thr = 0.1 * max(r2);
38+
r2_thr = mean(abs(r2)) + std(abs(r2))*3; %1/3rd of Max value
3939
idx = find(r2 > r2_thr);
4040
d_start = lags(idx(1));
4141

42+
fprintf('Finding test start marker.up\n');
43+
44+
if isequal(trace_en,true)
45+
fprintf(['%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|\n--------------------+--------------------+--------------------+----' ...
46+
'----------------+--------------------+--------------------+--------------------+--------------------+\n'], ...
47+
'nx', 'n_seek', 'test.fs', 'test.idle_t', 'test.mark_t', 'test.sm', 'n','d_start');
48+
49+
fprintf('%20d|%20d|%20d|%20.6f|%20.6f|%20d|%20d|%20d|\n',nx, n_seek, test.fs, test.idle_t, test.mark_t, test.sm, n,d_start);
50+
end
51+
52+
4253
%% Find end marker
4354
fprintf('Finding test end marker...\n');
4455
s = sync_chirp(test.fs, 'down');
56+
57+
nx = length(x);
4558
n_seek = round(test.fs*(test.idle_t + test.mark_t));
4659
n = min(max(round(test.fs*test.em),n_seek), nx);
4760
y = x(end-n+1:end);
4861
[r, lags] = xcorr(y, s);
4962
r2 = r.^2;
50-
r2_thr = 0.1 * max(r2);
63+
64+
r2_thr = mean(abs(r2)) + std(abs(r2))*3; %1/3rd of Max value
5165
idx = find(r2 > r2_thr);
5266
d_end = nx-n+lags(idx(end));
5367

68+
fprintf('Finding test start marker.down\n');
69+
if isequal(trace_en,true)
70+
fprintf(['%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|\n--------------------+--------------------+--------------------+----' ...
71+
'----------------+--------------------+--------------------+--------------------+--------------------+--------------------+\n'], ...
72+
'nx', 'n_seek', 'test.fs', 'test.idle_t', 'test.mark_t', 'test.sm', 'n','d_start','d_end');
73+
fprintf('%20d|%20d|%20d|%20.6f|%20.6f|%20d|%20d|%20d|%20d|\n',nx, n_seek, test.fs, test.idle_t, test.mark_t, test.sm, n,d_start,d_end);
74+
75+
end
76+
77+
5478
%% Check correct length of signal
5579
len = d_end-d_start;
5680
len_s = len/test.fs;
5781
ref_s = test.mark_t+test.nf*test.na*test.tl;
58-
if abs(len_s-ref_s) > test.mt
59-
fprintf(1, 'Start and end markers were not found. Signal quality may be poor.\n');
60-
return
82+
83+
if isequal(trace_en,true)
84+
fprintf(['%20s|%20s|%20s|%20s|\n--------------------+--------------------+' ...
85+
'--------------------+--------------------+\n'],'len_s', 'ref_s', 'test.mt','abs(len_s - ref_s)');
86+
fprintf('%20f|%20f|%20f|%20f|\n', len_s, ref_s, test.mt,abs(len_s - ref_s));
87+
end
88+
if abs(len_s - ref_s) > test.mt %FR , THD, DR,Relaxation may be required.
89+
fprintf(1, 'Start and end markers were not found. Signal quality may be poor.\n');
90+
return
6191
end
6292

6393
%% Delay to first tone, length of tone in samples
6494
d = d_start + round(test.mark_t*test.fs);
6595
if (d < 0)
6696
fprintf(1, 'Invalid delay value. Signal quality may be poor.\n');
6797
return
68-
d = [];
6998
end
7099
nt = round(test.tl*test.fs);
71100
nt_use = nt -round(test.is*test.fs) -round(test.ie*test.fs);
@@ -92,6 +121,6 @@
92121
nch = s(2);
93122
rms_db = zeros(1, nch);
94123
for i = 1:nch
95-
rms_db(i) = 20*log10(sqrt(mean(x(:,i).^2)));
124+
rms_db(i) = 20*log10(rms(x(:,i)));% very small data
96125
end
97126
end

0 commit comments

Comments
 (0)