function [REM,ETM,h_echo,sort_ix,P_k] = jonsson_3cy_01a_03_23_21(f,s11,N_bins,N_seg,N_discard,df_nonstandard)
%Evaluate micro-reflections
%Usage:
%  jonsson_3cy_01a_03_23_21(f,s11,N_bins,N_seg,N_discard,df_nonstandard)
%where <f> is frequency, <s11> is S11 parameters, <N_bins> is the number
%of time domain bins used in the calculation, <N_seg> is the number
%of samples in each time domain bin, and <N_discard> is the number of 
%segments to discard when computing REM and ETM.
%The parameter <df_nonstandard> can be used if the
%frequency sampling of s11 is not according to specification. 
%The function returns the metric values and intermediate values.
%Version 1.1 -- March 23, 2021
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
% DEALINGS IN THE SOFTWARE.

%%% check input arguments %%%
if(nargin < 6)
  df_nonstandard = 0; %% non-standard frequency support off by default
end

%%% number of samples to use %%%
K_N = N_bins * N_seg;
N_samples = K_N*2;  %even number of samples

%%% experimental code to convert non-standard frequency sampling to standard %%%
if(df_nonstandard)
  fq = df_nonstandard*[0:K_N];
  sq = cr_spline(f,s11,fq);
else
  fq = f;
  sq = s11;
end

%%% calculate echo impulse response and power %%%
h_echo = jonsson_3cy_01_03_23_21_f2t(sq,fq,N_samples);

%%% find power in each time bin %%%
h2 = h_echo.^2;
P_k = zeros(1,N_bins);
m1 = 0;
for n=1:N_bins,
  m0 = m1 + 1;
  m1 = round(n*N_seg);
  P_k(n) = mean(h2(m0:m1))*(N_seg);
end

%%% find residual echo metric %%%
[p_sort,sort_ix] = sort(P_k);
sort_ix = sort_ix(end:-1:1);
p_sum = cumsum(p_sort);
REM = 10*log10(p_sum(end:-1:1));

%%% find residual echo RE_k %%%
RE_k = P_k;
RE_k(sort_ix(1:N_discard)) = 0;

%%% calculate echo tail metric %%%
tmp = cumsum(RE_k(end:-1:1));
ETM = 10*log10(tmp(end:-1:1));

end %%% End of jonsson_3cy_01a_03_23_21

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function h_n = jonsson_3cy_01_03_23_21_f2t(H,f,N)

%RJf2t - Impulse (time) response for a given frequency response.
%Usage:
%  h = jonsson_3cy_01_03_23_21_f2t(H,f,N)
% where <H> is the frequency response given at frequencies <f>,
% <T> is the sampling interval, and <N> is the number of output
% samples (must be even).

%%% test arguments %%%
N_H = prod(size(H));
N_good = prod(size(find(H == H)));
if(N_H ~= N_good)
  error('Signal has invalid samples')
end

nonuniform_spacing = sum(abs(diff(abs(diff(f)))));
if(nonuniform_spacing)
  error('spacing of frequency points is not uniform')
end

if(f(1) ~= 0)
  error('frequency does not start at DC')
end

%%% re-shape arguments %%%
E_k = H(:);

%%% adjust phase of frequency response %%%
K_N = ceil(N/2);
ang_N = angle(E_k(K_N+1));
x0 = ang_N/(pi);
E_k = E_k.*exp(-j*2*pi*x0*[0:K_N]'/K_N/2);
E_k(1) = real(E_k(1));
H_k = [E_k(1:K_N); real(E_k(K_N+1)); conj(E_k(K_N:-1:2))];

%%% find impulse response from IDFT %%%
h_n = real(ifft(H_k));

end %%% End of jonsson_3cy_01_03_23_21_f2t

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function s = cr_spline(x,y,xq)
% Catmull-Rom spline
%   s = cr_ spline(x,y,xq);
% See more at https://en.wikipedia.org/wiki/Cubic_Hermite_spline

%%% initialize %%%
N_x = length(x);
[M_xq,N_xq] = size(xq);

%%% reshape arguments %%%
x = x(:);
y = y(:);
xq = xq(:);

%%% Catmull-Rom spline coefficients %%%
cr0 = [0 0 1 0];
cr1 = [0 1 0 -1]/2;
cr2 = [-1 4 -5 2]/2;
cr3 = [1 -3 3 -1]/2;

%%% find closest points for x-values %%%
xm = (x(1:end-1) + x(2:end) - 1e-10)/2; %% midpoint in interval 
[d,m]=min(abs(reshape(xm,N_x-1,1) - reshape(xq,1,N_xq*M_xq)));
u = (xq - x(m))./(x(m+1) - x(m));

%%% Use Farrow Structure to implement spline %%%
y0 = conv(y, cr0);
y1 = conv(y, cr1);
y2 = conv(y, cr2);
y3 = conv(y, cr3);

s = y3(m+2).*(u.^3)+y2(m+2).*(u.^2) + y1(m+2).*u + y0(m+2);
s = reshape(s,M_xq,N_xq);

end %%% End of cr_spline

