View Raw SPL
/*****************************************************************************
* *
* FXCORR.SPL Copyright (C) 2000 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Cross-correlation using FFT's *
* *
* Revisions: 2 May 2000 RRR Creation - from FREQ.MAC *
* *
*****************************************************************************/
#include
#if @HELP_FXCORR
FXCORR
Purpose: Cross correlation using the FFT method
Syntax: FXCORR(s1, s2, norm)
s1 - input series
s2 - input series
norm - optional integer, normalization method,
0: None,
1: Unity (-1 to 1)
2: Biased
3: Unbiased
defaults to 0: None
Returns: A series
Example:
W1: gsin(1000, .001, 4)
W2: gsin(1000, .001, 4)
W3: fxcorr(w1, w2)
Performs the cross correlation of two sinewaves. The
peaks of the result indicate the two waveforms are
very similar at the time intervals where the peaks
occur.
Example:
W1: gsin(1000, .001, 4)
W2: gnorm(1000, .001)
W3: fxcorr(w1, w1, 1)
W4: fxcorr(w1, w2, 1)
W3 displays the cross correlation of a sinewave normalized
to -1 and 1. W4 shows the cross correlation between a sinewave
and random noise. The normalized maximum of W3 is 1.0, indicating
perfect correlation at time t == 0. Although the waveform of
W4 displays some peaks, the normalized maximum is roughly 0.04
indicating little correlation between W1 and W2. For
a graphical representation, overplot W4 in W3.
Remarks:
The cross-correlation is used to determine how similar two
series are to each other. FXCORR performs correlation by
computing the FFT's of the input series.
The output length L is:
L = length(s1) + length(s2) - 1
For series of equal lengths and offsets, the zeroth lag
component is the mid point of the series.
The BIASED normalization divides the result by M, the
maximum length of the input series.
The UNBIASED normalization divides the result by
M - abs(M - i - 1) + 1
where i is the index of the result.
See XCORR for the time domain implementation.
See Also:
Acorr
Conv
Facorr
Fconv
Xcorr
#endif
/* frequency domain cross correlation */
fxcorr(s1, s2, norm)
{
local len, maxlen, f, xoff1, xoff2, dx;
if (argc < 3)
{
if (argc < 2)
{
if (argc < 1)
{
error("fxcorr - input series required");
}
s2 = refseries(s1);
}
if (isarray(s2))
{
norm = 0;
}
else
{
norm = s2;
s2 = refseries(s1);
}
}
/* get best fft length */
maxlen = maxval(max(collength(s1)), max(collength(s2)));
len = bestpow2(maxlen * 2);
/* perform correlation in the frequency domain */
f = ifft(fft(s1, len) * fft(conj(rev(s2)), len));
if (isreal(s1) && isreal(s2))
{
f = real(f);
}
/* extract proper output length */
f = extract(f, 1, length(s1) + length(s2) - 1);
/* normalization */
switch (norm)
{
case 0: /* none */
default:
break;
case 1: /* -1 to +1 */
f /= sqrt(colsum(s1 * s1) * colsum(s2 * s2));
break;
case 2: /* biased */
maxlen = maxval(collength(s1), collength(s2));
f /= maxlen;
break;
case 3: /* unbiased */
dx = deltax(f);
f /= ( {1..maxlen, (maxlen - 1)..-1..1});
/* preserve original deltax */
setdeltax(f, dx);
break;
}
/* set proper xoffset */
xoff1 = xoffset(s1);
/* reversed offset */
xoff2 = -xoffset(s2) - deltax(s2) * (length(s2) - 1);
setxoffset(f, xoff1 + xoff2);
return(f);
}