Skip to content
This repository was archived by the owner on Jan 17, 2019. It is now read-only.

Commit 1cbba6c

Browse files
committed
EQ: Add tool for acoustical frequency response measurement
This patch adds into SOFT/tune/eq a script mls_freq_resp.m that can be used as low budget or quick developer tool to measure device frequency response. The configuration files mls_play_config.txt and mls_rec_config.txt configure the audio devices for local or remote ssh aplay/arecord execution. The MLS measurement with a short time window, e.g. less than 10 ms can partially achieve the same as anechoic measurement. However this is not intended to replace usage any professional audio measurement. If using this use with care! Note also that as such this script measures the response of a speaker - microphone system. One response need to be known and under calibration to get reliable results for other. Even ADC and DAC responses may impact. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent e37aa3f commit 1cbba6c

4 files changed

Lines changed: 414 additions & 0 deletions

File tree

test/test_utils/mls_calc_resp.m

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
function [f, m_db, b] = mls_calc_resp(csv_fn, ref_wfn, meas_wfn, t_tot, np, f_lo, f_hi)
2+
3+
%% Calculate frequency response from MLS recordings
4+
%
5+
% [f, m, b] = calc_freq_resp(csv_fn, ref_fn, meas_fn, t_tot, np, f_lo, f_hi)
6+
%
7+
% Inputs parameters:
8+
% csv_fn - File name for CSV format response output
9+
% ref_fn - Reference MLS wave file
10+
% meas_fn - Captured MSL wave file
11+
% t_tot - Time window of MLS analysis in s, e.g. 5 - 10 ms
12+
% np - Number of frequency points
13+
% f_lo - Lower frequency limit for analysis
14+
% f_hi - Upper frequency limit for analysis
15+
16+
%%
17+
% Copyright (c) 2018, Intel Corporation
18+
% All rights reserved.
19+
%
20+
% Redistribution and use in source and binary forms, with or without
21+
% modification, are permitted provided that the following conditions are met:
22+
% * Redistributions of source code must retain the above copyright
23+
% notice, this list of conditions and the following disclaimer.
24+
% * Redistributions in binary form must reproduce the above copyright
25+
% notice, this list of conditions and the following disclaimer in the
26+
% documentation and/or other materials provided with the distribution.
27+
% * Neither the name of the Intel Corporation nor the
28+
% names of its contributors may be used to endorse or promote products
29+
% derived from this software without specific prior written permission.
30+
%
31+
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32+
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33+
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34+
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
35+
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36+
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37+
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38+
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39+
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40+
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41+
% POSSIBILITY OF SUCH DAMAGE.
42+
%
43+
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
44+
%
45+
46+
%% Read audio files
47+
[xr, fs] = audioread(ref_wfn);
48+
[xm, fsm] = audioread(meas_wfn);
49+
sm = size(xm);
50+
nch = sm(2);
51+
52+
if (fs ~= fsm)
53+
error('Reference and measured sample rates do not match.');
54+
end
55+
56+
ind_imp = zeros(1, nch);
57+
for ch=1:nch
58+
[acor(:,ch),lag] = xcorr(xm(:,ch), xr, 'coeff');
59+
[~,I] = max(abs(acor(:,ch)));
60+
timeDiff = lag(I);
61+
% Crosscorrelation maximum points to max of impulse response.
62+
% Use it beginning of impulse response
63+
ind_imp(ch) = find(lag == timeDiff);
64+
end
65+
% Keep the channels time aligned by using average of max as reference
66+
ind_imp_avg = round(sum(ind_imp)/nch);
67+
68+
b = [];
69+
nwin_half = round(t_tot*fs);
70+
nwin_tot = 2*nwin_half;
71+
win = hanning(nwin_tot);
72+
for ch = 1:nch
73+
% All channels are windowed from the same location
74+
p1 = ind_imp_avg-nwin_half;
75+
p2 = p1 + nwin_tot-1;
76+
acor_windowed = acor(p1:p2,ch) .* win;
77+
b(:,ch) = acor_windowed;
78+
end
79+
80+
81+
%% Compute frequency response
82+
f = logspace(log10(f_lo),log10(f_hi),np);
83+
for ch=1:nch
84+
h(:,ch) = freqz(b(:,ch), 1, f, fs);
85+
end
86+
m_db = 20*log10(abs(h));
87+
88+
fh = fopen(csv_fn, 'w');
89+
for i = 1:np
90+
fprintf(fh, '%10.3f', f(i));
91+
for j = 1:nch
92+
fprintf(fh, ', %8.3f', m_db(i, j));
93+
end
94+
fprintf(fh, '\n');
95+
end
96+
fclose(fh);
97+
98+
end

0 commit comments

Comments
 (0)