4
$\begingroup$

I'm new to the field of DSP.

I'm trying to determine the period and shift of the function. I've tried using FFT, but haven't had much luck. Seems like it should be simple.

Signal (pastebin of Octave matrix):

# Created by Octave 3.2.4, Wed Dec 12 00:26:41 2012 PST <jjohnson@jjohnson>
# name: a
# type: matrix
# rows: 1
# columns: 495
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.529411764705882 0.945098039215686 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.415686274509804 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.556862745098039 0.890196078431372 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.72156862745098 0.749019607843137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.862745098039216 0.611764705882353 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.933333333333333 0.470588235294118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Signal drawn with plot(a):

enter image description here

By hand I can tell that the shift is 75, and period is ~56. How do I get that from the results of the FFT?! Is there some other more appropriate algorithm?

FFT drawn with plot(abs(fft(a))):

enter image description here

$\endgroup$
1
  • $\begingroup$ @penelope: Can you post the octave matrix as well? $\endgroup$
    – Naresh
    Commented Dec 12, 2012 at 9:55

3 Answers 3

7
$\begingroup$

This will give you a plot of the autocovariance up to lag 100 samples:

plot(autocov(a,100))

autocovariance

There you can clearly get the period of your signal.

Another approach is to explicitly get the time of each pulse:

pulses = a > 0.1;
leading_edges = diff(pulses) > 0;
times = find(leading_edges > 0);
periods = diff(times)

ans =
    55   56   56   56   56

Explanation: pulses is 1 wherever there is a pulse. leading_edges gets a 1 only on the first sample of a pulse. times gives the sample number of each leading edge.

With this result you can perform your own statistics or estimation. This second method is computationally more efficient than using transforms. Computing time is linear with number of samples.

$\endgroup$
2
  • $\begingroup$ Thanks for the help. I'll give it a try, I think I may have oversimplified it by providing such a clean signal. $\endgroup$
    – Zigner
    Commented Dec 12, 2012 at 16:23
  • $\begingroup$ I'll be using the auto correlation method, thanks! $\endgroup$
    – Zigner
    Commented Dec 13, 2012 at 16:29
2
$\begingroup$

My answer is based on this answer https://dsp.stackexchange.com/a/15117/3573 by https://dsp.stackexchange.com/users/80/peter-k

The following is Octave code:

y=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.529411764705882 0.945098039215686 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.415686274509804 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.556862745098039 0.890196078431372 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.72156862745098 0.749019607843137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.862745098039216 0.611764705882353 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.933333333333333 0.470588235294118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
plot(y);
title("Signal")
print -dpng signal.png

autocorrelation=xcorr(y);
figure
plot(autocorrelation)

[pks loc] = findpeaks(autocorrelation,'DoubleSided');
hold on
plot(loc,pks,'or')
title("Autocorrelation")
print -dpng autocor.png

distance_between_peaks = diff(loc);
printf("Mean distance between peaks: %d\n",mean(diff(loc)))

The following figure is the plot of your signal y:

enter image description here

The following figure is the plot of the auto-correlation xcorr(y) of your signal, the peaks are marked in red:

enter image description here

We then take the distances between the peaks locations (with diff) and compute the mean distance, the script gives this output:

Mean distance between peaks: 55.6667
$\endgroup$
1
$\begingroup$

If you remove the DC offset before the FFT, the FFT result will show the low frequency peak a little more clearly.

$\endgroup$

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.