/// <summary> /// Creates a lookup dictionary from the fingerprintsignature. Key is the hash an value is an array of int /// pointing (index) to where the hash can be found using "SubFingerprint(int index)" /// </summary> public static Dictionary <int, int[]> CreateLookupDictionary(FingerprintAcoustID fs) { int[] hashes = fs.SignatureInt32; Dictionary <int, int[]> subFingerLookup = new Dictionary <int, int[]>(hashes.Length); for (int index = 0; index < hashes.Length; index++) { int h = hashes[index] & unchecked ((int)0xfffffff0); int[] data = new int[1] { index }; if (subFingerLookup.ContainsKey(h)) { subFingerLookup[h] = CombineArrays(subFingerLookup[h], data); } else { subFingerLookup.Add(h, data); } } //foreach return(subFingerLookup); }
public static float MatchFingerprint(FingerprintAcoustID finger1, FingerprintAcoustID finger2, int maxoffset = 0) { float score = 0.0f; int[] f1 = finger1.SignatureInt32; int f1size = f1.Length; int[] f2 = finger2.SignatureInt32; int f2size = f2.Length; int numcounts = f1size + f2size + 1; ushort[] aoffsets = new ushort[MATCH_MASK + 1]; ushort[] boffsets = new ushort[MATCH_MASK + 1]; // Zorg dat er een limiet is if (f1size > aoffsets.Length) { f1size = aoffsets.Length; } if (f2size > boffsets.Length) { f2size = boffsets.Length; } // ------------------------------------------------------------ // YN aanpassing 2015-11-02 gedaan (zoeken duurt anders te lang // zie titelnummer_id=944086 // Lookup tabel aanmaken ???? for (ushort i = 0; i < f1size; i++) { aoffsets[MatchStrip(f1[i])] = i; } for (ushort i = 0; i < f2size; i++) { boffsets[MatchStrip(f2[i])] = i; } // ------------------------------------------------------------ int topcount = 0; int topoffset = 0; ushort[] counts = new ushort[numcounts]; for (int i = 0; i < MATCH_MASK; i++) { if (aoffsets[i] != 0 && boffsets[i] != 0) { int offset = aoffsets[i] - boffsets[i]; if (maxoffset == 0 || (-maxoffset <= offset && offset <= maxoffset)) { offset += f2size; counts[offset]++; if (counts[offset] > topcount) { topcount = counts[offset]; topoffset = offset; } } } } //for i topoffset -= f2size; int f1Offset = 0; int f2Offset = 0; int minsize = Math.Min(f1size, f2size) & ~1; if (topoffset < 0) { f2Offset -= topoffset; f2size = Math.Max(0, f2size + topoffset); } else { f1Offset += topoffset; f1size = Math.Max(0, f1size - topoffset); } int size = Math.Min(f1size, f2size) / 2; if (size == 0 || minsize == 0) { System.Diagnostics.Trace.WriteLine("acoustid_compare2: empty matching subfingerprint"); return(0.0f); } ushort[] seen = aoffsets; int f1unique = 0; // clear for (int i = 0; i < UNIQ_MASK; i++) { seen[i] = 0; } for (int i = 0; i < f1size; i++) { int key = UniqueStrip(f1[i]); if (seen[key] == 0) { f1unique++; seen[key] = 1; } } int f2unique = 0; // clear for (int i = 0; i < UNIQ_MASK; i++) { seen[i] = 0; } for (int i = 0; i < f2size; i++) { int key = UniqueStrip(f2[i]); if (seen[key] == 0) { f2unique++; seen[key] = 1; } } float diversity = (float)Math.Min(Math.Min(1.0f, (float)(f1unique + 10) / f1size + 0.5f), Math.Min(1.0, (float)(f2unique + 10) / f2size + 0.5f)); int BER = 0; for (int i = 0; i < size; i++) { int bits = AudioFingerprint.Math.SimilarityUtility.HammingDistance(unchecked ((uint)f1[i]), unchecked ((uint)f2[i])); if (bits > 0) { BER += bits; } } //for i score = (size * 2.0f / minsize) * (1.0f - 2.0f * (float)BER / (64 * size)); if (score < 0.0f) { score = 0.0f; } if (diversity < 1.0) { float newscore = (float)Math.Pow(score, 8.0f - 7.0f * diversity); System.Diagnostics.Trace.WriteLine(string.Format("acoustid_compare2: scaling score because of duplicate items, {0:#0:00} => {1:#0:00}", score, newscore)); score = newscore; } return(score); }