New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Autocorrelation feature extractor #302
base: main
Are you sure you want to change the base?
Conversation
Hey @hughrawlinson, really sorry for getting round to this so late. I had a look at your impl and compared it with Matlab's But the zeroes definitely shouldn't be there - I'm testing with a 128-sample sine wave, whose positive xcorr should be gradually approaching zero until the last sample. Also, I think usually developers will expect a full xcorr with both negative and positive lags - that way it can be used for linear prediction and other things. I have an implementation of the IFFT method we could potentially use, unless we're worried about the performance implications. Happy to chat about this privately if that's easier :) |
thanks a lot for doing this btw :) |
I'd love to use your implementation! Will review a PR any time :) As long as the performance is fine for realtime, I'm sold. I had trouble implementing this in realtime, there was a v8 issue where a deop was triggered so I had to get around that to make it run fast enough. |
It didn't even occur to me to do negative lags! Will get on it :) |
f47684a
to
1551851
Compare
@jakubfiala this passes tests now. Accurate to The one remaining mystery I have is in the source formula: There were lots of equations and implementations all over the internet that I looked for - I initially wanted to implement a generic 'correlation of two signals' function, but couldn't find a formula that I could understand. There were some generic implementations that seemed parameterizable, and I didn't particularly want to let users configure which correlation equation was to be used under the hood, nor configure further lower level stuff. I found the above formula in these lecture notes at the very end. I implemented the extractor based on that, and I understand it all except the term |
Sorry I didn't join the conversation earlier. The term In any case, regarding the benchmarking Jakub did (comparing time-domain and freq-domain autocorrelation): Even if there isn't big difference in computation speed (although there should be - O(N^2) vs Nlog(N)) I still believe doing that it in the frequency domain makes more sense as we already computed all of the components needed for it. The way I understand it, we only need to perform an IFFT on the power spectrum (magnitude spectrum ^ 2) to get the autocorrelation result. This is just an optimisation so it shouldn't block the PR - thanks a lot for working on this @hughrawlinson !! |
Hey, I tried implementing it based on IFFT like you suggested, using fftjs. I didn't quite get the result I expected. Forgetting about the normalization errors - the second one is upside down, and cropped. I can fix the fact that the length is off by zero padding I would guess. Any ideas? |
Oh. I think fftjs always return half of the FFT result to be more efficient, and that might not be good for this use case... I'll check it out. |
@hughrawlinson What are you comparing the result to? Autocorrelation output from librosa? |
@nevosegal I'm comparing against an autocorrelation result that @jakubfiala gave me from an implementation of autocorrelation that he did. |
Our long nightmare is over, GitHub Copilot implemented autocorrelation for us lol function mean(x) {
var sum = 0;
for (var i = 0; i < x.length; i++) {
sum += x[i];
}
return sum / x.length;
}
function autocorrelation(x, y) {
var n = x.length;
var meanX = mean(x);
var meanY = mean(y);
var sum = 0;
for (var i = 0; i < n; i++) {
sum += (x[i] - meanX) * (y[i] - meanY);
}
return sum / (n - 1);
} |
Would require a minor bump.
There's a weird performance thing for v8, the code looks bad but actually it's there to trigger a compiler optimization. Happy to explain if someone's interested.
It includes tests, but the tests make me nervous, would love to try on more signals.
Someone should definitely have a look at the output and compare it with other implementations. It looks v suspicious to me, particularly seeing as the last half are zeroes.