public async Task QueryingWithAggregatedHashesShouldResultInTheSameMatches() { var audioService = new SoundFingerprintingAudioService(); var modelService = new InMemoryModelService(); int count = 20, testWaitTime = 5000; var data = GenerateRandomAudioChunks(count, 1, DateTime.UtcNow); var concatenated = Concatenate(data); var hashes = await FingerprintCommandBuilder.Instance .BuildFingerprintCommand() .From(concatenated) .WithFingerprintConfig(config => config) .UsingServices(audioService) .Hash(); modelService.Insert(new TrackInfo("312", "Bohemian Rhapsody", "Queen"), hashes); var collection = SimulateRealtimeQueryData(data, jitterLength: 0); var cancellationTokenSource = new CancellationTokenSource(testWaitTime); var fingerprints = new List <Hashes>(); var entries = new List <ResultEntry>(); await QueryCommandBuilder.Instance.BuildRealtimeQueryCommand() .From(collection) .WithRealtimeQueryConfig(config => { config.SuccessCallback = entry => entries.Add(entry); config.ResultEntryFilter = new TrackRelativeCoverageLengthEntryFilter(0.8d); config.Stride = new IncrementalStaticStride(2048); return(config); }) .Intercept(queryHashes => { fingerprints.Add(queryHashes); return(queryHashes); }) .UsingServices(modelService) .Query(cancellationTokenSource.Token); Assert.IsTrue(entries.Any()); Assert.AreEqual(1, entries.Count); var realtimeResult = entries.First(); var aggregatedHashes = Hashes.Aggregate(fingerprints, 60d).First(); var nonRealtimeResult = await QueryCommandBuilder.Instance .BuildQueryCommand() .From(aggregatedHashes) .UsingServices(modelService, audioService) .Query(); Assert.IsTrue(nonRealtimeResult.ContainsMatches); Assert.AreEqual(1, nonRealtimeResult.ResultEntries.Count()); Assert.AreEqual(realtimeResult.MatchedAt, aggregatedHashes.RelativeTo); Assert.AreEqual(realtimeResult.MatchedAt, nonRealtimeResult.BestMatch.MatchedAt, $"Realtime vs NonRealtime {nonRealtimeResult.BestMatch.Coverage.BestPath.Count()} match time does not match"); }
public async Task HashesShouldMatchExactlyWhenAggregated() { var audioService = new SoundFingerprintingAudioService(); var modelService = new InMemoryModelService(); int count = 20; var data = GenerateRandomAudioChunks(count, seed: 1, DateTime.UtcNow); var concatenated = Concatenate(data); var hashes = await FingerprintCommandBuilder.Instance .BuildFingerprintCommand() .From(concatenated) .WithFingerprintConfig(config => { config.Stride = new IncrementalStaticStride(512); return(config); }) .UsingServices(audioService) .Hash(); var collection = SimulateRealtimeQueryData(data, jitterLength: 0); var list = new List <Hashes>(); await QueryCommandBuilder.Instance.BuildRealtimeQueryCommand() .From(collection) .WithRealtimeQueryConfig(config => { config.Stride = new IncrementalStaticStride(512); return(config); }) .Intercept(timedHashes => { list.Add(timedHashes); return(timedHashes); }) .UsingServices(modelService) .Query(CancellationToken.None); Assert.AreEqual(hashes.Count, list.Select(entry => entry.Count).Sum()); var merged = Hashes.Aggregate(list, concatenated.Duration).ToList(); Assert.AreEqual(1, merged.Count, $"Hashes:{string.Join(",", merged.Select(_ => $"{_.RelativeTo},{_.DurationInSeconds:0.00}"))}"); Assert.AreEqual(hashes.Count, merged.Select(entry => entry.Count).Sum()); var aggregated = Hashes.Aggregate(list, double.MaxValue).ToList(); Assert.AreEqual(1, aggregated.Count); Assert.AreEqual(hashes.Count, aggregated[0].Count); foreach (var zipped in hashes.OrderBy(h => h.SequenceNumber).Zip(aggregated[0], (a, b) => new { a, b })) { Assert.AreEqual(zipped.a.StartsAt, zipped.b.StartsAt, 1d); Assert.AreEqual(zipped.a.SequenceNumber, zipped.b.SequenceNumber); CollectionAssert.AreEqual(zipped.a.HashBins, zipped.b.HashBins); } }
public async Task HashesShouldMatchExactlyWhenAggregated() { var audioService = new SoundFingerprintingAudioService(); var modelService = new InMemoryModelService(); int count = 20, testWaitTime = 40000; var data = GenerateRandomAudioChunks(count, 1); var concatenated = Concatenate(data); var hashes = await FingerprintCommandBuilder.Instance .BuildFingerprintCommand() .From(concatenated) .WithFingerprintConfig(config => { config.Stride = new IncrementalStaticStride(512); return config; }) .UsingServices(audioService) .Hash(); var collection = SimulateRealtimeQueryData(data, false, TimeSpan.FromSeconds); var cancellationTokenSource = new CancellationTokenSource(testWaitTime); var list = new List<Hashes>(); await QueryCommandBuilder.Instance.BuildRealtimeQueryCommand() .From(collection) .WithRealtimeQueryConfig(config => { config.QueryFingerprintsCallback += timedHashes => list.Add(timedHashes); config.Stride = new IncrementalStaticStride(512); return config; }) .UsingServices(modelService) .Query(cancellationTokenSource.Token); Assert.AreEqual(hashes.Count, list.Select(entry => entry.Count).Sum()); var merged = Hashes.Aggregate(list, 20d).ToList(); Assert.AreEqual(2, merged.Count); Assert.AreEqual(hashes.Count, merged.Select(entry => entry.Count).Sum()); var aggregated = Hashes.Aggregate(list, double.MaxValue).ToList(); Assert.AreEqual(1, aggregated.Count); Assert.AreEqual(hashes.Count, aggregated[0].Count); foreach (var zipped in hashes.OrderBy(h => h.SequenceNumber).Zip(aggregated[0], (a, b) => new { a, b })) { Assert.AreEqual(zipped.a.StartsAt, zipped.b.StartsAt, 0.5d); Assert.AreEqual(zipped.a.SequenceNumber, zipped.b.SequenceNumber); CollectionAssert.AreEqual(zipped.a.HashBins, zipped.b.HashBins); } }