# How to find delay of signal sample

24 views (last 30 days)

Show older comments

I have two signals that I am trying to align. When I perform the xcorr, the index of the peak does not match with the offset I introduced.

%Generate true signal and time

trT = 10:0.1:1500;

trPos = sin(trT*pi/200).*sin(trT*pi/50)+3*sin(trT*pi/300)+((trT-200)/200).^2;

%use part of tr data for ms

msPos = trPos(2401:5901);

%correlate signals

[r,lags] = xcorr((msPos),(trPos));

[~,idx] = max(abs(r));

figure(42)

plot(abs(r),'b.')

figure(43)

plot(trPos,'.')

hold on

plot(msPos,'.')

%zero-pad to shift the msPos to the correct position

msPos = [zeros(1,2400) msPos];

plot(msPos,'.-')

hold off

legend('True', 'Meas', 'Meas offset','location', 'northwest')

When I run the code, idx is 2520 when I would expect it to be closer to 2400. What am I missing?

##### 2 Comments

### Accepted Answer

Jon
on 16 Apr 2024

Your problems are coming from the fact that your signal is not zero mean. The peak correlation will only correspond to the best alignment in time if the signals have no offset (zero mean). Below I have modified your code, eliminating the last term in you expression for trPos so that it is a zero mean signal. Now I think the rest of your code acts as you expect.

By the way, you can use the code button on the toolbar to insert code and have it nicely formatted.

%Generate true signal and time

trT = 10:0.1:1500;

% use zero mean signal instead (eliminate last term that isn't zero mean)

trPos = sin(trT*pi/200).*sin(trT*pi/50)+3*sin(trT*pi/300);% +((trT-200)/200).^2;

%use part of tr data for ms

msPos = trPos(2401:3401); % use shorter segment so they don't overlap

% % msPos = trPos(2401:5901);

%correlate signals

[r,lags] = xcorr((msPos),(trPos));

[~,idx] = max(abs(r));

figure(42)

plot(abs(r),'b')

figure(43)

plot(trPos,'-')

hold on

plot(msPos,'-')

%zero-pad to shift the msPos to the correct position

msPos = [zeros(1,2400) msPos];

plot(msPos,'.-')

hold off

legend('True', 'Meas', 'Meas offset','location', 'northwest')

##### 5 Comments

Jon
on 16 Apr 2024

In case it is helpful I have written the attached function to locate a subsequence, x, in a longer sequence y. If the subsequence, x, does not occur exactly in x, the location where it has the closest fit (min sum square error) is found.

Here I have used it instead of xcorr in your original code

%Generate true signal and time

trT = 10:0.1:1500;

trPos = sin(trT*pi/200).*sin(trT*pi/50)+3*sin(trT*pi/300)+((trT-200)/200).^2;

%use part of tr data for ms

msPos = trPos(2401:5901);

% find the shift

idx = locsubseq(msPos,trPos);

figure(43)

plot(trPos,'.')

hold on

plot(msPos,'.')

%zero-pad to shift the msPos to the correct position

msPos = [zeros(1,idx-1) msPos];

plot(msPos,'.-')

hold off

legend('True', 'Meas', 'Meas offset','location', 'northwest')

Here's the function (also attached)

function idx = locsubseq(x,y)

%locsubseq Locates subsequence x in longer sequence y

% Given a length m vector x, and a length n vector y, with n>=m

% iStrt = locsubseq(x,y), provides index, iStrt, in y such that

% y(iStrt:iStrt + m -1) is the best fit (Euclidean distance) to y

% Get some dimensions

m = numel(x);

n = numel(y);

% Make sure x and y are column vectors

x = x(:);

y = y(:);

% zero pad x so it has same length as y

xpad = [x;zeros(n-m,1)];

% Make a toeplitz matrix where each column shifts x by one step (index)

X = toeplitz(xpad,[xpad(1) zeros(1,n-m)]);

% Find the sum square error from x to each subsequence in y

%

e = (X - y).*X; % .*X multiplies unwanted values by zero

sse = sum(e.^2);

% Find index that provides best match

[~,idx] = min(sse);

Jon
on 16 Apr 2024

### More Answers (4)

Taylor
on 16 Apr 2024

I think it has to do with the fact that your original signal is just multiple permutations of a sine wave. If you closely inspect the original signal, you can actually see some morphological similarities in at different time points. So xcorr is determining that spot to be lcoation of maximum correlation. If you use random data as your original signal, you don't experience this issue.

% Define the signals

signal = randn(1, 1000); % Original signal

offset = 200; % Actual offset for demonstration

segmentLength = 25; % Length of the segment

segment = signal(offset:(offset+segmentLength-1)); % Extracted segment

% Compute cross-correlation to find the offset

[correlation, lags] = xcorr(signal, segment);

[~, idx] = max(correlation);

offsetEstimate = lags(idx);

figure;

plot(signal, 'b', 'DisplayName', 'Original Signal');

hold on;

plot(segment, 'r', 'DisplayName', 'Segment');

xlabel('Sample Index');

ylabel('Amplitude');

title('Original Signal and Segment');

legend;

hold off;

% Correct the segment's position

correctedPosition = (1:length(segment)) + offsetEstimate;

figure;

plot(signal, 'b', 'DisplayName', 'Original Signal');

hold on;

plot(correctedPosition, segment, 'r', 'DisplayName', 'Corrected Segment');

xlabel('Sample Index');

ylabel('Amplitude');

title('Original Signal and Corrected Segment');

legend;

hold off;

##### 2 Comments

Jon
on 16 Apr 2024

Jon
on 16 Apr 2024

Alexander
on 16 Apr 2024

Maybe this would be helpful:

@Manikanta Aditya used xcov but at least it is a very similar problem.

##### 0 Comments

AH
on 18 Apr 2024

As an alternative solution, you may want to use the function findsignal in Signal Processing Toolbox that finds the location of the measured signal in the true signal as below

%Generate true signal and time

trT = 10:0.1:1500;

trPos = sin(trT*pi/200).*sin(trT*pi/50)+3*sin(trT*pi/300)+((trT-200)/200).^2;

%use part of tr data for ms

msPos = trPos(2401:5901);

Let's first examine how the function works

findsignal(trPos,msPos,'NormalizationLength',length(msPos))

Upon querying the beginning and end indexes as the ouput arguments, the findsignal returns

[istart,istop,dist] = findsignal(trPos,msPos,'NormalizationLength',length(msPos))

The dist argument indeed indicates that the found match in trPos is really close to the measured signal.

##### 0 Comments

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!