-
Notifications
You must be signed in to change notification settings - Fork 349
Audio: Enhancing audio quality tests for device testing #6056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0343001
f890366
4060f44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,18 +139,15 @@ | |
| fprintf('Number of skipped tests = %d\n', r.n_skipped); | ||
| fprintf('============================================================\n'); | ||
|
|
||
| n_fail = r.n_fail; | ||
| n_pass = r.n_pass; | ||
| n_na = r.n_na; | ||
| if r.n_fail < 1 && r.n_pass < 1 | ||
| fprintf('\nERROR: No test results.\n'); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to keep the error message about no tests executed. What problem did this cause?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe there is a problem . |
||
| n_fail = 1; | ||
| elseif r.n_fail > 0 | ||
| if r.n_fail > 0 || r.n_pass < 1 | ||
| fprintf('\nERROR: TEST FAILED!!!\n'); | ||
| else | ||
| fprintf('\nTest passed.\n'); | ||
| end | ||
|
|
||
| n_fail = r.n_fail; | ||
| n_pass = r.n_pass; | ||
| n_na = r.n_na; | ||
| end | ||
|
|
||
| %% ------------------------------------------------------------ | ||
|
|
@@ -350,7 +347,7 @@ | |
| test.f_start = 20; | ||
| test.f_end = test.fs * 0.41667; % 20 kHz @ 48 kHz | ||
| test.fu = test.fs * 0.41667; % 20 kHz @ 48 kHz | ||
| test.f_max = 0.999*t.fs/2; % Measure up to min. Nyquist frequency | ||
| test.f_max = 0.999*test.fs/2; % Measure up to min. Nyquist frequency | ||
| test.fs1 = test.fs; | ||
| test.fs2 = test.fs; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,8 +46,6 @@ | |
| test = get_config(test); | ||
|
|
||
| %% Run tests | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The topic of this commit is too generic, this looks like "Add dynamic range test to sof_test_perf.m". |
||
| fail = 0; | ||
| pass = 0; | ||
| test.tf = []; | ||
|
|
||
| % Check that the configuration has been edited | ||
|
|
@@ -68,6 +66,9 @@ | |
|
|
||
| %% Total harmonic distortion plus noise | ||
| [tf(3), thdnf_low, thdnf_high] = thdnf_test(test); | ||
|
|
||
| %% Dynamic range | ||
| [tf(4), dynamic_range]= dr_test(test); | ||
| end | ||
|
|
||
| %% Print results | ||
|
|
@@ -81,6 +82,7 @@ | |
| print_val(test, tf(2), fr_3db_hz / 1000, 'kHz', '-3 dB frequency'); | ||
| print_val(test, tf(3), thdnf_low, 'dB', 'THD+N -20 dBFS'); | ||
| print_val(test, tf(3), thdnf_high, 'dB', 'THD+N -1 dBFS'); | ||
| print_val(test, tf(4), dynamic_range, 'dB', 'dr_db_min'); | ||
| else | ||
| fprintf(1, '\n'); | ||
| fprintf(1, 'Warning: The gain test must pass before other tests are executed.\n'); | ||
|
|
@@ -128,8 +130,8 @@ | |
| %% Reference: AES17 6.2.3 Frequency response | ||
| c1 = 20/48; | ||
| c2 = 23.9/48; | ||
| test.f_lo = 20; % Measure start at 20 Hz | ||
| test.f_hi = c1 * test.fs; % Measure end e.g. at 20 kHz | ||
| test.fr_lo = 20; % Measure start at 20 Hz | ||
| test.fr_hi = c1 * test.fs; % Measure end e.g. at 20 kHz | ||
| test.f_max = c2 * test.fs; % Sweep max e.g. at 23.9 kHz | ||
|
|
||
| %% Create input file | ||
|
|
@@ -144,7 +146,7 @@ | |
|
|
||
| fail = test.fail; | ||
| fr_db = test.rp; | ||
| fr_hz = [test.f_lo test.f_hi]; | ||
| fr_hz = [test.fr_lo test.fr_hi]; | ||
| fr_3db_hz = test.fr3db_hz; | ||
| delete_check(test.files_delete, test.fn_in); | ||
| delete_check(test.files_delete, test.fn_out); | ||
|
|
@@ -182,6 +184,28 @@ | |
|
|
||
| end | ||
|
|
||
| %% Reference: AES17 6.4.1 Dynamic range | ||
| function [fail, dr_db] = dr_test(t) | ||
|
|
||
| test = test_defaults(t); | ||
|
|
||
| % Create input file | ||
| test = dr_test_input(test); | ||
|
|
||
| % Run test | ||
| % test = test_run_process(test, t); | ||
| test = remote_test_run(test); | ||
|
|
||
| % Measure | ||
| test = dr_test_measure(test); | ||
|
||
|
|
||
| % Get output parameters | ||
| fail = test.fail; | ||
| dr_db = test.dr_db; | ||
| delete_check(test.files_delete, test.fn_in); | ||
| delete_check(test.files_delete, test.fn_out); | ||
|
|
||
| end | ||
| %% | ||
| %% Utilities | ||
| %% | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ | |
| %% | ||
|
|
||
| %% Set user@domain for ssh, need to be set for playback test | ||
| play.user = 'user@host.domain'; | ||
| play.user = 'localhost'; % username@ip-address | ||
|
|
||
| %% Other playback settings | ||
| play.ssh = 1; % Set to 1 for for remote play | ||
|
|
@@ -41,6 +41,12 @@ | |
| test.fr_rp_max_db = 1.0; % Upper limit for p-p ripple in dB | ||
| test.plot_fr_axis = [10 30e3 -4 1]; % Plot xmin, xmax, ymin, ymax | ||
|
|
||
| test.fr_mask_flo = []; | ||
|
||
| test.fr_mask_fhi = []; | ||
| test.fr_mask_mlo = []; | ||
| test.fr_mask_mhi = []; | ||
| %% THD+N test case | ||
| test.thdnf_max = -55; % Upper limit for THD+N | ||
| test.plot_thdn_axis = [10 30e3 -90 -40]; % Plot xmin xmax ymin ymax | ||
| %% dynamic range test case | ||
| test.dr_db_min = 70; % Min. DR,80dB | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,7 +57,7 @@ | |
| level_in = test.a_db; | ||
| level_out = level_dbfs(y); | ||
| level_final = level_dbfs(y_n); | ||
| test.dr_db = level_out-level_final-test.a_db; | ||
| test.dr_db = level_out - level_final - test.a_db; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not compatibility but a code cleanup, goes to first commit. |
||
| fprintf('DR = %5.1f dB\n', test.dr_db); | ||
| if 0 | ||
| plot(y); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,7 +88,7 @@ | |
| test.tr = 10e-3; % Gain ramp time for tones | ||
| test.sm = 3; % Seek start marker from 3s from start | ||
| test.em = 3; % Seek end marker from 3s from end | ||
| test.mt = 0.1; % Error if marker positions delta is greater than 0.1s | ||
| test.mt = 2; % Error if marker positions delta is greater than 2s | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put this to own commit and describe (add robustness for real-device test?). |
||
| test.tc = 10; % Min. 10 cycles of sine wave for a frequency | ||
| t_min = 0.1; | ||
| % Use t_min or min cycles count as tone length | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,15 +33,17 @@ | |
| % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> | ||
|
|
||
| %% Check if upper and lower mask is defined | ||
| if length(test.fr_mask_flo) || length(test.fr_mask_fhi) | ||
| if ~isempty(test.fr_mask_flo) || ~isempty(test.fr_mask_fhi) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This to first cleanup patch if this is not fixing anything, does it? Personally I find length() easier to understand than "not is empty?" |
||
| test.fr_lo = 0; | ||
| test.fr_hi = 0; | ||
| end | ||
| if test.fr_lo > 0 || test.fr_hi > 0 | ||
| test.fr_mask_flo = []; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This to separate commit, e.g. use default frequency response mask. |
||
| test.fr_mask_fhi = []; | ||
| test.fr_mask_mlo = []; | ||
| test.fr_mask_mhi = []; | ||
| test.fr_mask_fhi = [20 test.f_max]; | ||
| test.fr_mask_flo = [200 400 3500 3600 ]; | ||
| for i = 1:test.nch | ||
| test.fr_mask_mhi(:,i) = [ 1 1 ]; | ||
| test.fr_mask_mlo(:,i) = [-10 -1 -1 -10]; | ||
| end | ||
| end | ||
|
|
||
| test.ph = []; | ||
|
|
@@ -109,7 +111,7 @@ | |
| mask_hi = interp1(log(test.fr_mask_fhi), ... | ||
| test.fr_mask_mhi(:,j), f_log, 'linear'); | ||
| over_mask = test.m(:,j)-mask_hi'; | ||
| idx = find(isnan(over_mask) == 0); | ||
| idx = ~isnan(over_mask); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this and next to cleanup commit |
||
| [m_over_mask, io] = max(over_mask(idx)); | ||
| if m_over_mask > 0 | ||
| fprintf('Failed upper response mask around %.0f Hz\n', ... | ||
|
|
@@ -122,7 +124,7 @@ | |
| mask_lo = interp1(log(test.fr_mask_flo), ... | ||
| test.fr_mask_mlo(:,j), f_log, 'linear'); | ||
| under_mask = mask_lo'-test.m(:,j); | ||
| idx = find(isnan(under_mask) == 0); | ||
| idx = ~isnan(under_mask); | ||
| [m_under_mask, iu] = max(under_mask(idx)); | ||
| if m_under_mask > 0 | ||
| fprintf('Failed lower response mask around %.0f Hz\n', ... | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,15 +6,14 @@ | |
| % x - signal | ||
| % | ||
| % Output | ||
| % dbfs - sigmal level in dBFS | ||
| % dbfs - signal level in dBFS | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to cleanup commit |
||
| % | ||
|
|
||
| % SPDX-License-Identifier: BSD-3-Clause | ||
| % Copyright(c) 2017 Intel Corporation. All rights reserved. | ||
| % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> | ||
|
|
||
| %% Reference AES 17 3.12.3 | ||
| level_ms = mean(x.^2); | ||
| dbfs = 10*log10(level_ms + 1e-20) + 20*log10(sqrt(2)); | ||
| dbfs = 20*log10(rms(x) * sqrt(2)); | ||
ShriramShastry marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cleanup |
||
|
|
||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ | |
| test.tr = 10e-3; % Gain ramp time for tones | ||
| test.sm = 3; % Seek start marker from 3s from start | ||
| test.em = 3; % Seek end marker from 3s from end | ||
| test.mt = 0.1; % Error if marker positions delta is greater than 0.1s | ||
| test.mt = 2; % Error if marker positions delta is greater than 2s | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is 2nd for "improve real device tests robustness"? |
||
| test.a_db = [-1 -20]; % -1 and -20 dBFS levels | ||
| test.a = 10.^(test.a_db/20); | ||
| test.tl = 4; % 3 seconds tone | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,18 +7,14 @@ | |
| test.ph = []; | ||
| test.fh = []; | ||
|
|
||
| if isempty(test.thdnf_mask_f) | ||
| if ~isempty(test.thdnf_max) | ||
| test.thdnf_mask_f = [1 test.fs/2]; % Start from 1 due to log() | ||
| test.thdnf_mask_hi = test.thdnf_max * [1 1]; | ||
| end | ||
| else | ||
| if ~isempty(test.thdnf_max) | ||
| error('Set either thdnf_max or thdnf_mask_f & thdnf_mask_hi but not both'); | ||
| end | ||
| if isempty(test.thdnf_mask_hi) | ||
| error('thdnf_mask_hi must be set when thdnf_mask_f is defined'); | ||
| end | ||
| if ~isempty(test.thdnf_max) | ||
| test.thdnf_mask_f = [1 test.fs/2]; % Start from 1 due to log() | ||
| test.thdnf_mask_hi = test.thdnf_max * [1 1]; | ||
| end | ||
| if isempty(test.thdnf_max) | ||
| error('Set either thdnf_max or thdnf_mask_f & thdnf_mask_hi but not both'); | ||
| elseif isempty(test.thdnf_mask_hi) | ||
| error('thdnf_mask_hi must be set when thdnf_mask_f is defined'); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's many different changes in this commit "Audio: BugFix : Enhancing audio quality tests for device testing". I'd split this further to topics (process_test, perf_test, thd+n, ...) and explain in commit message why it's done. This change needs an own commit and explanation. To me it looks like 2nd if is wrong. What is the problem that is being fixed here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me it looks like 2nd if is wrong. |
||
| end | ||
|
|
||
| %% Reference: AES17 6.3.2 THD+N ratio vs frequency | ||
|
|
@@ -76,16 +72,16 @@ | |
| test.thdnf_high(:,i) = test.thdnf(:,1); | ||
| test.thdnf_low(:,i) = test.thdnf(:,2); | ||
|
|
||
| fidx = find(test.thdnf(idx, 1) > mask_hi); | ||
| if length(fidx) > 0 | ||
| fidx = find(test.thdnf(idx, 1) > mask_hi, 1); | ||
| if ~isempty(fidx) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this for Matlab compatibility? Looks more like cleanup, though I'm not 100% sure. Please check.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| fail_hi = 1; | ||
| fprintf('Failed THD+N mask with high input.\n'); | ||
| else | ||
| fail_hi = 0; | ||
| end | ||
|
|
||
| fidx = find(test.thdnf(idx, 2) > mask_hi); | ||
| if length(fidx) > 0 | ||
| fidx = find(test.thdnf(idx, 2) > mask_hi, 1); | ||
| if ~isempty(fidx) | ||
| fail_lo = 1; | ||
| fprintf('Failed THD+N mask with low input.\n'); | ||
| else | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,7 +21,7 @@ | |
| nt = []; | ||
| nt_use = []; | ||
| nt_skip = []; | ||
|
|
||
| trace_en = false; % Enable to trace algorithm -analysis | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Find_test_signal() change to own commit and describe what the changes do. |
||
| %% Use channel with strongest signal | ||
| ch = select_channel(x0); | ||
| x = x0(:, ch); | ||
|
|
@@ -35,37 +35,66 @@ | |
| y = x(1:n); | ||
| [r, lags] = xcorr(y, s); | ||
| r2 = r.^2; | ||
| r2_thr = 0.1 * max(r2); | ||
| r2_thr = mean(abs(r2)) + std(abs(r2))*3; %1/3rd of Max value | ||
| idx = find(r2 > r2_thr); | ||
| d_start = lags(idx(1)); | ||
|
|
||
| fprintf('Finding test start marker.up\n'); | ||
|
|
||
| if isequal(trace_en,true) | ||
| fprintf(['%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|\n--------------------+--------------------+--------------------+----' ... | ||
| '----------------+--------------------+--------------------+--------------------+--------------------+\n'], ... | ||
| 'nx', 'n_seek', 'test.fs', 'test.idle_t', 'test.mark_t', 'test.sm', 'n','d_start'); | ||
|
|
||
| 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); | ||
| end | ||
|
|
||
|
|
||
| %% Find end marker | ||
| fprintf('Finding test end marker...\n'); | ||
| s = sync_chirp(test.fs, 'down'); | ||
|
|
||
| nx = length(x); | ||
| n_seek = round(test.fs*(test.idle_t + test.mark_t)); | ||
| n = min(max(round(test.fs*test.em),n_seek), nx); | ||
| y = x(end-n+1:end); | ||
| [r, lags] = xcorr(y, s); | ||
| r2 = r.^2; | ||
| r2_thr = 0.1 * max(r2); | ||
|
|
||
| r2_thr = mean(abs(r2)) + std(abs(r2))*3; %1/3rd of Max value | ||
| idx = find(r2 > r2_thr); | ||
| d_end = nx-n+lags(idx(end)); | ||
|
|
||
| fprintf('Finding test start marker.down\n'); | ||
| if isequal(trace_en,true) | ||
| fprintf(['%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|%20s|\n--------------------+--------------------+--------------------+----' ... | ||
| '----------------+--------------------+--------------------+--------------------+--------------------+--------------------+\n'], ... | ||
| 'nx', 'n_seek', 'test.fs', 'test.idle_t', 'test.mark_t', 'test.sm', 'n','d_start','d_end'); | ||
| 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); | ||
|
|
||
| end | ||
|
|
||
|
|
||
| %% Check correct length of signal | ||
| len = d_end-d_start; | ||
| len_s = len/test.fs; | ||
| ref_s = test.mark_t+test.nf*test.na*test.tl; | ||
| if abs(len_s-ref_s) > test.mt | ||
| fprintf(1, 'Start and end markers were not found. Signal quality may be poor.\n'); | ||
| return | ||
|
|
||
| if isequal(trace_en,true) | ||
| fprintf(['%20s|%20s|%20s|%20s|\n--------------------+--------------------+' ... | ||
| '--------------------+--------------------+\n'],'len_s', 'ref_s', 'test.mt','abs(len_s - ref_s)'); | ||
| fprintf('%20f|%20f|%20f|%20f|\n', len_s, ref_s, test.mt,abs(len_s - ref_s)); | ||
| end | ||
| if abs(len_s - ref_s) > test.mt %FR , THD, DR,Relaxation may be required. | ||
| fprintf(1, 'Start and end markers were not found. Signal quality may be poor.\n'); | ||
| return | ||
| end | ||
|
|
||
| %% Delay to first tone, length of tone in samples | ||
| d = d_start + round(test.mark_t*test.fs); | ||
| if (d < 0) | ||
| fprintf(1, 'Invalid delay value. Signal quality may be poor.\n'); | ||
| return | ||
| d = []; | ||
| end | ||
| nt = round(test.tl*test.fs); | ||
| nt_use = nt -round(test.is*test.fs) -round(test.ie*test.fs); | ||
|
|
@@ -92,6 +121,6 @@ | |
| nch = s(2); | ||
| rms_db = zeros(1, nch); | ||
| for i = 1:nch | ||
| rms_db(i) = 20*log10(sqrt(mean(x(:,i).^2))); | ||
| rms_db(i) = 20*log10(rms(x(:,i)));% very small data | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ | |
| % Copyright(c) 2017 Intel Corporation. All rights reserved. | ||
| % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> | ||
|
|
||
| %% Adjust tone lengt to integer number of samples | ||
| %% Adjust tone length to integer number of samples | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To cleanup |
||
| test.nt = round(test.tl*test.fs); % Make number of samples per tone | ||
| test.tl = test.nt/test.fs; % an integer by adjusting tl. | ||
| test.nf = length(test.f); % Number of frequencies | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,4 +21,4 @@ function alsactl_write(fn, blob8) | |
| end | ||
| fprintf(fh, '%ld,\n', blob32(end)); | ||
| fclose(fh); | ||
| endfunction | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please prefix all your commit titles with Tools: Test: So that reviewers and and other git log viewers know what these are about. These do not contain changes for audio components.