function delay=delayest_3point(u2,u1,method,estimator,parameter);
%delay=delayest_3point(u2,u1,method,estimator,parameter);
%Estimates delay of u2 wrt u1 by interpolating the peak of the cross correlatio
%using a three-point peak interpolation
%method may be 'parabola','Gaussian','modGaussian','cosine'.
%estimator may be 'xcorr','ASDF','AMDF' (AMDF is very slow).
%if using modGaussian, parameter is a bias (always used if >=0, only used
%for xc<0 for parameter < 0)

if nargin<3
    method='parabola';
end

if nargin<4
    estimator='xcorr';
end

if nargin<5
    switch method
        case {'modGaussian','modgaussian'}
            parameter=1;
    end
end


N_p=numel(u2);%number of elements



switch estimator
    case {'xcorr','xc','xcorr_fft'}%cross correlation
        U1=fft(u1);
        U2=fft(u2);
        xc=ifft(U2.*conj(U1));%circular xcorr
        [tmp idx]=max(xc);
    case {'ASDF'}%average squared difference function
         xc = (-2*ifft(fft(u2).*conj(fft(u1))) + sum(u1.^2) + sum(u2.^2))/N_p;%ADSF
        [tmp idx]=min(xc);
    case {'AMDF'}%average magnitude difference function (this is a lot slower for large N_p)
        xc=sum(abs(repmat(u1',1,N_p)-hankel(u2',[u2(end)'; u2(1:(end-1))'])))/N_p;%AMDF
        [tmp idx]=min(xc);
end


R=zeros(1,3);%three points to use for interpolation
R(2)=xc(idx);%peak

%find neighbors, assuming periodic
if idx==1
    R(1)=xc(end);
    R(3)=xc(2);
elseif idx==numel(xc)
    R(1)=xc(end-1);
    R(3)=xc(1);
else
    R(1)=xc(idx-1);
    R(3)=xc(idx+1);
end


switch method
    case {'Gaussian','gaussian'}
        %a=exp(log(R(2))+(log(R(3))-log(R(1)))^2/(16*log(R(2))-8*log(R(1))-8*log(R(3))));%peak value
        %b=(2*log(R(2))-log(R(1))-log(R(3)))/2;%width
        c=(log(R(3))-log(R(1)))/(4*log(R(2))-2*log(R(1))-2*log(R(3)));
    case {'parabola','parabolic'}
    	%A=inv([1 -1 1;0 0 1;1 1 1])*R';
        %c=-A(2)/(2*A(1));
        %a=-1/4*A(2)^2/A(1)+A(3);%peak value
        c=(R(3)-R(1))/(2*(2*R(2)-R(1)-R(3)));
    case {'modGaussian','modgaussian'}
        if parameter>=0%always add bias
            R=R-min(R)+parameter*R(2);
        else%only add bias if R has a negative value
            if any(R<=0)
                R=R-min(R)-parameter*R(2);
            end
        end
        %a=exp(log(R(2))+(log(R(3))-log(R(1)))^2/(16*log(R(2))-8*log(R(1))-8*log(R(3))));
        %b=(2*log(R(2))-log(R(1))-log(R(3)))/2;
        c=(log(R(3))-log(R(1)))/(4*log(R(2))-2*log(R(1))-2*log(R(3)));
    case {'cosine'}
        omega=acos((R(1)+R(3))/(2*R(2)));
        theta=atan((R(1)-R(3))/(2*R(2)*sin(omega)));
        %A=R(2)/cos(theta);
        c=-theta/omega;
    otherwise
        error('unknown method')
end

lag=mod(idx-1+floor(N_p/2),N_p)-floor(N_p/2);%integer part
delay=lag+c;%delay estimate
