I posted a similar question a while ago here (I'm posting this follow-up since I'd like to focus more on cross-correlation now). I have a setup where I have two software-defined radios connected to different antennas, and a circuit switches the antennas on and off at the same time. I am trying to time-sync the two signals as precisely as possible. The radios are sampling at 2.4 MS/s and I'm sampling about 0.2 seconds of data. Even though I've synced the two clocks of the radios, due to slight hardware differences there will always be a slight delay in one of the signals which is why I need to sync them in software. I have a system that is able to sync the signals most of the time just by getting the signal's envelopes and identifying where the antenna switching happens, but this doesn't work so well when the "silence" part is too noisy / too high amplitude, so I would like to use cross correlation.

Here are two of the signals I'm trying to align: s0, s1. I believe the correct delay of s0 should be approximately 1069.

I'm normalizing both signals to have a max amplitude of 1, and I've also tried downsampling to make it lower detail. I'm just doing signal.correlate(s0, s1) and plotting the result, but I don't even see any local maximum at the correct delay (I know the correct delay from the other method).

Here's the plotted correlation:

enter image description here

And here it is zoomed in to where I'd expect the actual delay to be:

enter image description here

There doesn't seem to be any local max around 1069.

Is anyone able to successfully sync these two signals using cross correlation, or is it just not possible for this kind of data? Everyone doing similar project to me uses cross correlation to do the time synchronization, so I'm not sure why it's not working at all for me (even when I use their code). Any help would be greatly appreciated!

  • $\begingroup$ How can I load these large .txt files in Python? $\endgroup$ Commented Jul 17, 2018 at 8:49
  • $\begingroup$ A quick and easy way: with open('s0.txt', 'r') as f: s0 = eval(f.read()) $\endgroup$
    – jstein123
    Commented Jul 17, 2018 at 12:34

2 Answers 2


It will work when you take the 2nd gradient of the signals:

import numpy as np
from scipy import signal

s0 = np.gradient(np.gradient(s0))
s1 = np.gradient(np.gradient(s1))
np.argmax(signal.correlate(s0, s1)) -> 525358

That corresponds to a shift of 1071 which is close to your expected 1069 Interestingly the minimum (most negative correlation) is close by at 1069

Plotting the cross-correlation of 2nd gradient gives a reasonably sharp peak: cross-correlation of 2nd gradient of the data

Zomming in to the accordingly shifted data shows that this worked:

aligned data using max correlation

Using the most negative correlation results in the almost same picture: aligned data using max negative correlation

What might be surprising is that the min and max are just two samples apart and also that the signal seems to be significantly phase shifted. On the other hand the start is matched perfectly. My interpretation of this is that the sync is not so much done by what we see as signal but by some high frequency parts of noise received in both channels. Since this 2 sample shift between min and max is the typical result when matching two channels that received the same random noise.

I can not explain easily why the correlation of the original data works in some cases. But here is an simple example that gives an idea:

a = np.array([0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0, 0, 0], dtype=float)
b = np.array([0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0, 0, 0], dtype=float)
np.argmax(signal.correlate(a, b)) -> 16

which is correct

but when adding an offset it fails

a += 5
b += 5
np.argmax(signal.correlate(a, b)) -> 20

the correlation of the first gradient still gives the right result but it will fail also if a significant ramp is added. Though for the 2nd gradient the correct result is achieved

a += np.array(range(0,len(a)))*5
b += np.array(range(0,len(b)))*5
np.argmax(signal.correlate(a, b)) -> 20
a = np.gradient(a)
b = np.gradient(b)
np.argmax(signal.correlate(a, b)) -> 20
a = np.gradient(a)
b = np.gradient(b)
np.argmax(signal.correlate(a, b)) -> 16

Let me ask you a question :

If you perform an autocorrelation, where will the maximum be?

The length of an autocorrelation is 2*length(s) - 1 where s is your original signal. Intuitively you can deduce that your maximum will be right in the middle. Thus, for the autocorrelation of a 10000-sample signal the maximum would be at sample 10000 assuming your index starts at 1. It's not going to be at index 1 (or index 0).

The reasoning is the same with a cross-correlation. Assuming 2 signals with the same length, you would get your maximum at the index corresponding to the length of your signals. Since you expect a value of 1069 (positive or negative), you would get your maximum at length(s) ± 1069.

  • $\begingroup$ Thanks! I'm not really familiar with DSP so much though, so I'm not sure I really understand what I'm doing wrong. I don't see any maximum around index 1069. $\endgroup$
    – jstein123
    Commented Jul 16, 2018 at 19:52
  • $\begingroup$ Well assuming both signals have a length of 50000, you should see your maximum at index 50000 ± 1069. Not index 1069 $\endgroup$
    – Ben
    Commented Jul 16, 2018 at 19:58
  • $\begingroup$ I think you have a maximum near 50 000 which would make a lot of sense. $\endgroup$
    – Ben
    Commented Jul 16, 2018 at 19:59
  • $\begingroup$ Oh ok that makes sense! However, I'm getting 2609 though when I do correlation.argmax() - len(s0). I plotted the two signals with this delay, but it's pretty off. Not sure what's wrong: i.imgur.com/AxRtQLA.png $\endgroup$
    – jstein123
    Commented Jul 16, 2018 at 20:07
  • $\begingroup$ There might be other issues. Are you sure your signals have the same length? In Matlab, the cross-correlation function appends zeroes at the end of the shorter signals, but I don't know how it is implemented in Python. $\endgroup$
    – Ben
    Commented Jul 16, 2018 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.