public void MaximumNumberOfReturnedTracksIsLessThanAnalyzedCandidatesResultsTest()
        {
            long[]             buckets                = new long[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            var                queryHash              = new HashData(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 }, buckets);
            const int          DefaultThreshold       = 5;
            const int          FirstTrackId           = 20;
            const int          SecondTrackId          = 21;
            const int          ThirdTrackId           = 22;
            const int          FirstSubFingerprintId  = 10;
            const int          SecondSubFingerprintId = 11;
            var                firstTrackReference    = new ModelReference <int>(FirstTrackId);
            var                thirdTrackReference    = new ModelReference <int>(ThirdTrackId);
            SubFingerprintData firstResult            = new SubFingerprintData(
                new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
                new ModelReference <int>(FirstSubFingerprintId),
                firstTrackReference);
            SubFingerprintData secondResult = new SubFingerprintData(
                new byte[] { 11, 2, 13, 4, 15, 6, 7, 8, 10, 12 },
                new ModelReference <int>(SecondSubFingerprintId),
                new ModelReference <int>(SecondTrackId));
            SubFingerprintData thirdResult = new SubFingerprintData(
                new byte[] { 1, 2, 3, 4, 5, 15, 7, 8, 10, 12 },
                new ModelReference <int>(SecondSubFingerprintId),
                new ModelReference <int>(ThirdTrackId));

            modelService.Setup(
                service => service.ReadSubFingerprintDataByHashBucketsWithThreshold(buckets, DefaultThreshold)).Returns(
                new List <SubFingerprintData> {
                firstResult, secondResult, thirdResult
            });
            modelService.Setup(service => service.ReadTrackByReference(firstTrackReference)).Returns(
                new TrackData {
                ISRC = "isrc", TrackReference = firstTrackReference
            });
            modelService.Setup(service => service.ReadTrackByReference(thirdTrackReference)).Returns(
                new TrackData {
                ISRC = "isrc_2", TrackReference = thirdTrackReference
            });

            var queryResult = queryFingerprintService.Query(
                modelService.Object,
                new List <HashData> {
                queryHash
            },
                new CustomQueryConfiguration
            {
                MaximumNumberOfTracksToReturnAsResult = 2, ThresholdVotes = DefaultThreshold
            });

            Assert.IsTrue(queryResult.IsSuccessful);
            Assert.AreEqual("isrc", queryResult.BestMatch.Track.ISRC);
            Assert.AreEqual(firstTrackReference, queryResult.BestMatch.Track.TrackReference);
            Assert.AreEqual(9, queryResult.BestMatch.Similarity);
            Assert.AreEqual(3, queryResult.AnalyzedCandidatesCount);
            Assert.AreEqual(2, queryResult.ResultEntries.Count);
            Assert.AreEqual(firstTrackReference, queryResult.ResultEntries[0].Track.TrackReference);
            Assert.AreEqual(thirdTrackReference, queryResult.ResultEntries[1].Track.TrackReference);
        }
        public void MaximumNumberOfReturnedTracksIsLessThanAnalyzedCandidatesResultsTest()
        {
            var       queryHash              = new HashedFingerprint(GenericHashBuckets(), 1, 0, Array.Empty <byte>());
            const int defaultThreshold       = 5;
            const int firstTrackId           = 20;
            const int secondTrackId          = 21;
            const int thirdTrackId           = 22;
            const int firstSubFingerprintId  = 10;
            const int secondSubFingerprintId = 11;
            var       firstTrackReference    = new ModelReference <int>(firstTrackId);
            var       secondTrackReference   = new ModelReference <int>(secondTrackId);
            var       firstResult            = new SubFingerprintData(GenericHashBuckets(), 1, 0,
                                                                      new ModelReference <int>(firstSubFingerprintId),
                                                                      firstTrackReference);
            var secondResult = new SubFingerprintData(GenericHashBuckets(), 2, 0.928f,
                                                      new ModelReference <int>(secondSubFingerprintId),
                                                      secondTrackReference);
            var thirdResult = new SubFingerprintData(GenericHashBuckets(), 3, 0.928f * 2,
                                                     new ModelReference <int>(secondSubFingerprintId),
                                                     new ModelReference <int>(thirdTrackId));

            var customQueryConfiguration = new DefaultQueryConfiguration {
                MaxTracksToReturn = 2, ThresholdVotes = defaultThreshold
            };

            modelService
            .Setup(service => service.Query(It.IsAny <Hashes>(), customQueryConfiguration))
            .Returns(new[] { firstResult, secondResult, thirdResult });

            modelService.Setup(service => service.ReadTracksByReferences(new[] { firstTrackReference, secondTrackReference }))
            .Returns(new List <TrackData>
            {
                new TrackData("id", string.Empty, string.Empty, 0d, firstTrackReference),
                new TrackData("id_1", string.Empty, string.Empty, 0d, secondTrackReference)
            });

            var hashes = new Hashes(new List <HashedFingerprint> {
                queryHash
            }, 1.48f, DateTime.Now, Enumerable.Empty <string>());
            var queryResult = queryFingerprintService.Query(hashes, customQueryConfiguration, modelService.Object);

            Assert.IsTrue(queryResult.ContainsMatches);
            Assert.AreEqual("id", queryResult.BestMatch.Track.Id);
            Assert.AreEqual(firstTrackReference, queryResult.BestMatch.Track.TrackReference);
            Assert.AreEqual(100, queryResult.BestMatch.Score);
            Assert.AreEqual(2, queryResult.ResultEntries.Count());
            var results = queryResult.ResultEntries.ToList();

            Assert.AreEqual(firstTrackReference, results[0].Track.TrackReference);
            Assert.AreEqual(secondTrackReference, results[1].Track.TrackReference);
        }
        public void CreateFingerprintsInsertThenQueryAndGetTheRightResult()
        {
            const int SecondsToProcess = 10;
            const int StartAtSecond    = 30;
            var       tagService       = new BassTagService();
            var       info             = tagService.GetTagInfo(PathToMp3);
            var       track            = new TrackData(info.ISRC, info.Artist, info.Title, info.Album, info.Year, info.Duration);
            var       trackReference   = modelService.InsertTrack(track);

            var hashedFingerprints = fingerprintCommandBuilder
                                     .BuildFingerprintCommand()
                                     .From(PathToMp3, SecondsToProcess, StartAtSecond)
                                     .UsingServices(bassAudioService)
                                     .Hash()
                                     .Result;

            modelService.InsertHashDataForTrack(hashedFingerprints, trackReference);

            var queryResult = queryFingerprintService.Query(hashedFingerprints, new DefaultQueryConfiguration(), modelService);

            Assert.IsTrue(queryResult.ContainsMatches);
            Assert.AreEqual(1, queryResult.ResultEntries.Count());
            Assert.AreEqual(trackReference, queryResult.BestMatch.Track.TrackReference);
        }
        public void MaximumNumberOfReturnedTracksIsLessThanAnalyzedCandidatesResultsTest()
        {
            var       queryHash              = new HashedFingerprint(GenericHashBuckets(), 1, 0, Enumerable.Empty <string>());
            const int DefaultThreshold       = 5;
            const int FirstTrackId           = 20;
            const int SecondTrackId          = 21;
            const int ThirdTrackId           = 22;
            const int FirstSubFingerprintId  = 10;
            const int SecondSubFingerprintId = 11;
            var       firstTrackReference    = new ModelReference <int>(FirstTrackId);
            var       secondTrackReference   = new ModelReference <int>(SecondTrackId);
            var       firstResult            = new SubFingerprintData(
                GenericHashBuckets(),
                1,
                0,
                new ModelReference <int>(FirstSubFingerprintId),
                firstTrackReference);
            var secondResult = new SubFingerprintData(
                GenericHashBuckets(),
                2,
                0.928f,
                new ModelReference <int>(SecondSubFingerprintId),
                secondTrackReference);
            var thirdResult = new SubFingerprintData(
                GenericHashBuckets(),
                3,
                0.928f * 2,
                new ModelReference <int>(SecondSubFingerprintId),
                new ModelReference <int>(ThirdTrackId));

            var customQueryConfiguration = new DefaultQueryConfiguration {
                MaxTracksToReturn = 2, ThresholdVotes = DefaultThreshold
            };

            modelService.Setup(service => service.SupportsBatchedSubFingerprintQuery).Returns(false);
            modelService.Setup(
                service => service.ReadSubFingerprints(It.IsAny <int[]>(), customQueryConfiguration)).Returns(
                new List <SubFingerprintData> {
                firstResult, secondResult, thirdResult
            });
            modelService
            .Setup(service => service.ReadTracksByReferences(new[] { firstTrackReference, secondTrackReference }))
            .Returns(new List <TrackData>
            {
                new TrackData {
                    ISRC = "isrc", TrackReference = firstTrackReference
                },
                new TrackData {
                    ISRC = "isrc_1", TrackReference = secondTrackReference
                }
            });

            var queryResult = queryFingerprintService.Query(new List <HashedFingerprint> {
                queryHash
            }, customQueryConfiguration, modelService.Object);

            Assert.IsTrue(queryResult.ContainsMatches);
            Assert.AreEqual("isrc", queryResult.BestMatch.Track.ISRC);
            Assert.AreEqual(firstTrackReference, queryResult.BestMatch.Track.TrackReference);
            Assert.AreEqual(100, queryResult.BestMatch.HammingSimilaritySum);
            Assert.AreEqual(2, queryResult.ResultEntries.Count());
            var results = queryResult.ResultEntries.ToList();

            Assert.AreEqual(firstTrackReference, results[0].Track.TrackReference);
            Assert.AreEqual(secondTrackReference, results[1].Track.TrackReference);
        }
        public void CreateFingerprintsInsertThenQueryAndGetTheRightResult()
        {
            const int StaticStride = 5115;
            const int SecondsToProcess = 10;
            const int StartAtSecond = 30;
            DefaultQueryConfiguration defaultQueryConfiguration = new DefaultQueryConfiguration();
            QueryFingerprintService queryFingerprintService = new QueryFingerprintService(new CombinedHashingAlgorithm(), modelService);
            ITagService tagService = new BassAudioService();
            TagInfo info = tagService.GetTagInfo(PathToMp3);
            int releaseYear = info.Year;
            Track track = new Track(info.ISRC, info.Artist, info.Title, info.Album, releaseYear, (int)info.Duration);

            modelService.InsertTrack(track);

            var fingerprinter = fingerprintUnitBuilderWithBass.BuildAudioFingerprintingUnit()
                                            .From(PathToMp3, SecondsToProcess, StartAtSecond)
                                            .WithCustomAlgorithmConfiguration(config =>
                                            {
                                                config.Stride = new IncrementalStaticStride(StaticStride, config.SamplesPerFingerprint);
                                            })
                                            .FingerprintIt();

            var fingerprints = fingerprinter.AsIs().Result;
            var subFingerprints = fingerprinter.HashIt().ForTrack(track.Id).Result;

            modelService.InsertSubFingerprint(subFingerprints);

            List<HashBinMinHash> hashBins = new List<HashBinMinHash>();
            foreach (SubFingerprint subFingerprint in subFingerprints)
            {
                long[] groupedSubFingerprint = lshService.Hash(subFingerprint.Signature, defaultQueryConfiguration.NumberOfLSHTables, defaultQueryConfiguration.NumberOfMinHashesPerTable);
                for (int i = 0; i < groupedSubFingerprint.Length; i++)
                {
                    int tableNumber = i + 1;
                    hashBins.Add(new HashBinMinHash(groupedSubFingerprint[i], tableNumber, subFingerprint.Id));
                }
            }

            modelService.InsertHashBin(hashBins);

            QueryResult result = queryFingerprintService.Query(fingerprints, defaultQueryConfiguration);

            Assert.IsTrue(result.IsSuccessful);
            Assert.AreEqual(track.Id, result.Results[0].Track.Id);
        }