# Matlab: xcorr: Having trouble when I try to calculate delay between two sinusoids

I have a problem when I try to use Matlab built-in function for cross-correlation 'xcorr'.

Background: I created two sinusoids, one of them delayed in time. I choose center frequencies of these signals slightly different than another. In this way, I am trying to analyze the effects of frequency mismatch on cross-correlation results. Problem: The problem is when I try to calculate delay using xcorr function in MatLab, I could not find the exact lag. The result is quite far away from my offset-time. I try to increase my signal length or sampling frequency. But nothing changes.

Do you have any idea? Here is my simple code, below.

clc
clear all
close all

Fs=48e3;
dt=1/Fs;
t=0:dt:(4*Fs-1)*dt;
CarrierFreq=5e3;
Dev=50;
CarrierFreqDev=CarrierFreq +Dev*(2*randi(2,1)-3);

Offset=10000;
OffsetTime=Offset*dt;
NoisePower=-95
DesiredSNR=20;

% Signal Power
NoisePowerWatt=10^(NoisePower/10);

% Generate Noise @ specified power
Noise1 = wgn(1,length(t),NoisePowerWatt,'linear');
Noise2 = wgn(1, length(t),NoisePowerWatt,'linear');

% Generate Signal1 @ specified power
Signal1=cos(2*pi*CarrierFreq*t);
pSignal1 = sum(Signal1.^2) / length(Signal1);
Signal1 =  Signal1/sqrt(pSignal1);
Signal1=Signal1_Norm+Noise1;

% Generate Delayed Signal @ specified power
Signal2=cos(2*pi*CarrierFreqDev*t);
pSignal2=sum(Signal2.^2) / length(Signal2);
Signal_Delay=circshift(Signal2_Norm, -Offset);
Signal2=Signal_Delay+Noise2;

[Coeff, Delay_Time] = xcorr(Signal1,Signal2); %% with dev.
[ ~,Indx]  = max(abs(Coeff));
Delay_Time = Delay_Time(Indx)*dt;



A sine wave is cyclo-stationary so is not the best waveform to use for estimating delay between transmit and received signals. It will correlate whenever the delay causes the signal to be an additional $$2\pi$$ in phase offset. Consider using waveforms with better autocorrelation properties for this purpose such as pseudo-random noise sequences or other generated white noise sources.

Regardless, the effect of frequency offset on cross-correlation is that the magnitude rolls-off as a Sinc function with frequency offset with the first null at $$1/T$$ where $$T$$ is the total time duration of the signal, and the phase decreases linearly from $$0$$ at $$f=0$$ to $$-\pi$$ at $$f=1/T$$. At a fixed frequency offset between the signals, a fixed phase offset would result, and for a narrow band signal this can be approximated as a fixed delay according to the carrier frequency of the signal.

Consider that correlation is the sum of the element by element product between two signals (the dot product), and observe how the product of two signals will be at the frequency difference between them (the beat note). Thus if your total time duration is exactly 1 complete cycle off in frequency, the result will average to zero (showing how the first null is at $$1/T$$).

The following code demonstrates this experimentally with a random white noise waveform of total time duration 0.1 seconds:

T = .1;
fs = 10e3;
N = T*fs;
t = [0:N-1]/fs;
x = randn(1,N);

index = 0;
foffset = 0:.01:20;
for f = foffset
index++;
y = x.*exp(j*2*pi*f.*t);
# dot product is the correlation, and normalized
corr(index) = x*y'/(N*std(x).*std(y));
end

figure
plot(foffset,abs(corr))
figure
plot(corr)


This creates the two plots shown below with the first plot of the magnitude of the normalized correlation versus the static frequency offset between the two signals, and the second plot as a polar plot showing both magnitude and phase components.  