174 lines
6.3 KiB
Matlab
174 lines
6.3 KiB
Matlab
function test = fr_test_measure(test)
|
|
|
|
%% t = fr_test_measure(t)
|
|
%
|
|
% Measure frequency response from captured frequency sweep created by
|
|
% fr_test_input() that sets most of the input struct fiels. The output
|
|
% is read from file t.fn_out.
|
|
%
|
|
% Input parameters
|
|
% t.f_lo - Measure ripple start frequency
|
|
% t.f_hi - Measure ripple end frequency
|
|
% t.rp_max - Max. ripple +/- dB
|
|
% t.mask_f - Frequencies for mask
|
|
% t.mask_lo - Upper limits of mask
|
|
% t.mask_hi - Lower limits of mask
|
|
%
|
|
% Output parameters
|
|
% t.m - Measured frequency response
|
|
% t.rp - Measured ripple +/- dB
|
|
% t.fr3db_hz - Bandwidth in Hz for -3 dB attenuated response
|
|
% t.fail - Returns zero for passed
|
|
% t.fh - Figure handle
|
|
% t.ph - Plot handle
|
|
%
|
|
% E.g.
|
|
% t.fs=48e3; t.f_max=20e3; t.bits_out=16; t.ch=1; t.nch=2; t=fr_test_input(t);
|
|
% t.fn_out=t.fn_in; t.f_lo=20; t.f_hi=20e3; t.rp_max=[]; t.mask_f=[];
|
|
% t=fr_test_measure(t);
|
|
%
|
|
|
|
%%
|
|
% Copyright (c) 2017, Intel Corporation
|
|
% All rights reserved.
|
|
%
|
|
% Redistribution and use in source and binary forms, with or without
|
|
% modification, are permitted provided that the following conditions are met:
|
|
% * Redistributions of source code must retain the above copyright
|
|
% notice, this list of conditions and the following disclaimer.
|
|
% * Redistributions in binary form must reproduce the above copyright
|
|
% notice, this list of conditions and the following disclaimer in the
|
|
% documentation and/or other materials provided with the distribution.
|
|
% * Neither the name of the Intel Corporation nor the
|
|
% names of its contributors may be used to endorse or promote products
|
|
% derived from this software without specific prior written permission.
|
|
%
|
|
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
% POSSIBILITY OF SUCH DAMAGE.
|
|
%
|
|
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
|
%
|
|
|
|
%% Reference: AES17 6.2.3 Frequency response
|
|
% http://www.aes.org/publications/standards/
|
|
|
|
[x, nx] = load_test_output(test);
|
|
|
|
j = 1;
|
|
for channel = test.ch
|
|
|
|
if nx == 0
|
|
test.rp(j) = NaN;
|
|
test.fr3db_hz(j) = NaN;
|
|
test.fail = 1;
|
|
return
|
|
end
|
|
|
|
%% Find sync
|
|
[d, nt, nt_use, nt_skip] = find_test_signal(x(:,j), test);
|
|
|
|
win = hamming(nt_use);
|
|
m0 = zeros(test.nf,1);
|
|
for n=1:test.nf
|
|
fprintf('Measuring %.0f Hz ...\n', test.f(n));
|
|
i1 = d+(n-1)*nt+nt_skip;
|
|
i2 = i1+nt_use-1;
|
|
m0(n) = level_dbfs(x(i1:i2,j).*win) -test.a_db;
|
|
end
|
|
|
|
%% Scale 997 Hz point as 0 dB
|
|
df = test.f - test.f_ref;
|
|
[~,i997] = min(abs(df));
|
|
m_offs = m0(i997);
|
|
test.m(:,j) = m0 - m_offs;
|
|
|
|
%% Check pass/fail
|
|
idx0 = find(test.f < test.f_hi);
|
|
idx1 = find(test.f(idx0) > test.f_lo);
|
|
range_db = max(test.m(idx1,j))-min(test.m(idx1,j));
|
|
test.rp(j) = range_db/2;
|
|
test.fail = 0;
|
|
if ~isempty(test.rp_max)
|
|
if test.rp > test.rp_max
|
|
fprintf('Failed response +/- %f dBpp (max +/- %f dB)\n', ...
|
|
test.rp, test.rp_max);
|
|
test.fail = 1;
|
|
end
|
|
end
|
|
|
|
%% Find frequency response 3 dB 0-X Hz
|
|
idx3 = find(test.m(:,j) > -3);
|
|
test.fr3db_hz(j) = test.f(idx3(end));
|
|
|
|
%% Interpolate mask in logaritmic frequencies, check
|
|
if ~isempty(test.mask_f)
|
|
f_log = log(test.f);
|
|
mask_hi = interp1(log(test.mask_f), test.mask_hi(:,j), ...
|
|
f_log, 'linear');
|
|
mask_lo = interp1(log(test.mask_f), test.mask_lo(:,j), ...
|
|
f_log, 'linear');
|
|
over_mask = test.m(:,j)-mask_hi';
|
|
under_mask = mask_lo'-test.m(:,j);
|
|
idx = find(isnan(over_mask) == 0);
|
|
[m_over_mask, io] = max(over_mask(idx));
|
|
idx = find(isnan(under_mask) == 0);
|
|
[m_under_mask, iu] = max(under_mask(idx));
|
|
if m_over_mask > 0
|
|
fprintf('Failed upper response mask around %.0f Hz\n', ...
|
|
test.f(io));
|
|
test.fail = 1;
|
|
end
|
|
if m_under_mask > 0
|
|
fprintf('Failed lower response mask around %.0f Hz\n', ...
|
|
test.f(iu));
|
|
test.fail = 1;
|
|
end
|
|
end
|
|
|
|
test.fh(j) = figure('visible', test.visible);
|
|
subplot(1,1,1);
|
|
test.ph(j) = subplot(1,1,1);
|
|
%semilogx(test.f, test.m(:,j));
|
|
plot(test.f, test.m(:,j));
|
|
grid on;
|
|
xlabel('Frequency (Hz)');
|
|
ylabel('Magnitude (dB)');
|
|
if length(test.mask_f) > 0
|
|
hold on;
|
|
plot(test.f, mask_hi, 'r--');
|
|
plot(test.f, mask_lo, 'r--');
|
|
hold off;
|
|
end
|
|
ax = axis();
|
|
axis([ax(1:2) -4 1]);
|
|
if max(max(test.m(idx1,j))-min(test.m(idx1,j))) < 1
|
|
axes('Position', [ 0.2 0.2 0.4 0.2]);
|
|
box on;
|
|
plot(test.f(idx1), test.m(idx1,j));
|
|
if ~isempty(test.rp_max)
|
|
hold on;
|
|
plot([test.f_lo test.f_hi], ...
|
|
[-test.rp_max/2 -test.rp_max/2], 'r--');
|
|
plot([test.f_lo test.f_hi], ...
|
|
[ test.rp_max/2 test.rp_max/2], 'r--');
|
|
hold off;
|
|
end
|
|
grid on;
|
|
axis([0 test.f_hi -0.1 0.1]);
|
|
end
|
|
|
|
%% Next channel to measure
|
|
j=j+1;
|
|
end
|
|
|
|
end
|