I’m using cython for a correlation calculation in my python program. I have two audio data sets and I need to know the time difference between them. The second set is cut based on onset times and then slid across the first set. There are two for-loops: one slides the set and the inner loop calculates correlation at that point. This method works very well and it’s accurate enough.
The problem is that with pure python this takes more than one minute. With my cython code, it takes about 17 seconds. This still is too much. Do you have any hints how to speed-up this code:
import numpy as np
cimport numpy as np
cimport cython
FTYPE = np.float
ctypedef np.float_t FTYPE_t
@cython.boundscheck(False)
def delay(np.ndarray[FTYPE_t, ndim=1] f, np.ndarray[FTYPE_t, ndim=1] g):
cdef int size1 = f.shape[0]
cdef int size2 = g.shape[0]
cdef int max_correlation = 0
cdef int delay = 0
cdef int current_correlation, i, j
# Move second data set frame by frame
for i in range(0, size1 - size2):
current_correlation = 0
# Calculate correlation at that point
for j in range(size2):
current_correlation += f[<unsigned int>(i+j)] * g[j]
# Check if current correlation is highest so far
if current_correlation > max_correlation:
max_correlation = current_correlation
delay = i
return delay
Edit:
There’s now
scipy.signal.fftconvolvewhich would be the preferred approach to doing the FFT based convolution approach that I describe below. I’ll leave the original answer to explain the speed issue, but in practice usescipy.signal.fftconvolve.Original answer:
Using FFTs and the convolution theorem will give you dramatic speed gains by converting the problem from O(n^2) to O(n log n). This is particularly useful for long data sets, like yours, and can give speed gains of 1000s or much more, depending on length. It’s also easy to do: just FFT both signals, multiply, and inverse FFT the product.
numpy.correlatedoesn’t use the FFT method in the cross-correlation routine and is better used with very small kernels.Here’s an example
Which gives the running times per cycle (in seconds, for a 10,000 long waveform)
It’s clear the fftxcorr method is much faster.
If you plot out the results, you’ll see that they are very similar near zero time shift. Note, though, as you get further away the xcorr will decrease and the fftxcorr won’t. This is because it’s a bit ambiguous what to do with the parts of the waveform that don’t overlap when the waveforms are shifted. xcorr treats it as zero and the FFT treats the waveforms as periodic, but if it’s an issue it can be fixed by zero padding.