示例#1
0
        private void ShowFingerprints(SubFingerprintLookupEntry sfp1, SubFingerprintLookupEntry sfp2)
        {
            Fingerprint fp1          = store.GetFingerprint(sfp1);
            Fingerprint fp2          = store.GetFingerprint(sfp2);
            Fingerprint fpDifference = fp1.Difference(fp2);

            fingerprintView1.Fingerprint = fp1;
            fingerprintView2.Fingerprint = fp2;
            fingerprintView3.Fingerprint = fpDifference;
            berLabel.Content             = Fingerprint.CalculateBER(fp1, fp2);
        }
示例#2
0
        public List <Match> FindMatchesFromExternalSubFingerprints(AudioTrack audioTrack, List <SubFingerprintHash> hashes)
        {
            if (hashes.Count < this.fingerprintSize)
            {
                throw new ArgumentException(String.Format(
                                                "Hash list is too short, cannot build fingerprints (given {0}, required at least {1})",
                                                hashes.Count, this.fingerprintSize));
            }

            var matches        = new List <Match>();
            int collisionCount = 0;

            for (int i = 0; i < hashes.Count; i++)
            {
                List <SubFingerprintLookupEntry> collisions = this.collisionMap.GetValues(hashes[i]);

                foreach (var collision in collisions)
                {
                    collisionCount++;

                    // The indices at which the fingerprints begin within the hash lists
                    int externalIndex = i;
                    int internalIndex = collision.Index;

                    // The hash lists
                    var externalHashes = hashes;
                    var internalHashes = store[collision.AudioTrack];

                    // The lengths of the hash lists (the number of subfingerprints/hashes)
                    int externalHashCount = externalHashes.Count;
                    int internalHashCount = internalHashes.Count;

                    // The overflow if directly taken at the indices
                    int externalOverflow = this.fingerprintSize - (externalHashCount - externalIndex);
                    int internalOverflow = this.fingerprintSize - (internalHashCount - internalIndex);

                    // The bigger of both overflows is the value by which we need to shift the sampling to the left
                    int leftShift = Math.Max(externalOverflow, internalOverflow);

                    // Check if we need to do a shift
                    // If the left shift is > 0, we need to shift the fingerprints to the left
                    // if the shift is <= 0, the fingerprints can be directly sampled from the hash lists
                    // (the negative value is their distance to the right border)
                    if (leftShift > 0)
                    {
                        // We need to shift the fingerprints to the left because one or both would otherwise overflow the right border
                        externalIndex -= leftShift;
                        internalIndex -= leftShift;

                        // Before we take the fingerprints, we need to check if that is even possible or if a fingerprint
                        // would then overflow the left border
                        if (externalIndex < 0 || internalIndex < 0)
                        {
                            // A fingerprint would now overflow the left border, so for this collision it is not possible
                            // to take fingerprints that we can compare
                            // Skip to the next collision
                            continue;
                        }
                    }

                    // TODO detect duplicate matching attempts and skip them to minimize matching cost
                    // A matching attempt can be described as the tuple (internalAudioTrack, externalIndex, internalIndex)

                    // Take the fingerprints that we want to compare
                    Fingerprint externalFingerprint = new Fingerprint(externalHashes, externalIndex, this.fingerprintSize);
                    // We don't use GetFingerprint here because that function shifts the fingerprint left for an unknown offset
                    // if taken at the right border
                    Fingerprint internalFingerprint = new Fingerprint(internalHashes, internalIndex, this.fingerprintSize);

                    // Calculate the bit error rate between both fingerprints
                    float bitErrorRate = Fingerprint.CalculateBER(externalFingerprint, internalFingerprint);

                    Console.WriteLine(String.Format("{0} <> {1} => {2}", externalIndex, internalIndex, bitErrorRate));

                    if (bitErrorRate < threshold)
                    {
                        matches.Add(new Match {
                            Similarity = 1 - bitErrorRate,
                            Track1     = collision.AudioTrack,
                            Track1Time = SubFingerprintIndexToTimeSpan(internalIndex),
                            Track2     = audioTrack,
                            Track2Time = SubFingerprintIndexToTimeSpan(externalIndex),
                            Source     = matchSourceName,
                        });
                    }
                }
            }

            Console.WriteLine(String.Format("{0} collisions, {1} matches", collisionCount, matches.Count));

            return(matches);
        }