beetbox / pyacoustid

Python bindings for Chromaprint acoustic fingerprinting and the Acoustid Web service
MIT License
325 stars 66 forks source link

add fingerprint comparison to acoustid.py #75

Closed bindestriche closed 1 year ago

bindestriche commented 1 year ago

Adding fingerprint comparison function. based on https://github.com/acoustid/pg_acoustid/blob/main/acoustid_compare.c

bindestriche commented 1 year ago

I'll admit that I don't 100% understand the actual comparison algorithm (the offset manipulation is a little foreign to me), but if this seems to work I'm happy to merge it.

Thank you for all your kind feedback. I only ported the comparison logic from the c code by @lalinsky

If I got it right, it goes like this: He made a cool tool to visualize fingerprint matching. Move the track to -4, and you will see a lot more black. The code is doing the same. The shifting is because the fingerprints could be time shifted against each other. Xor is the error count, if two bits are different it is one. The code is shifting from -MAX_ALIGN_OFFSET to +MAX_ALIGN_OFFSET saving the highest count of matches between the comparison windows at a given offset. A match is counted if there is a maximum of MAX_BIT_ERROR difference.

Here is a simplified example: let the * be some kind of noise at the start of one recording that makes the two fingerprints different.

print1 **1011
print2 1011
error  1101 -> 3 errors

-> correct bits 1/ length 4 ->0 .25 similarity

offset print2 by +2 bits

print1 **1011
print2 --1011
error    0000 -> 0 errors

-> correct bits 4/ length 4 ->1 similarity

Instead of comparing bit by bit, we compare 2*120 bits at a time and count them as a match if a max of 2 bits are different.

bindestriche commented 1 year ago

@ sampsyo anything else to do?

sampsyo commented 1 year ago

Just added some documentation, so I think we are good to go!! Thanks again for seeing this through.