public void ShouldMergeLongSequences() { DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo("en-US").DateTimeFormat; var first = new List <HashedFingerprint>(); var second = new List <HashedFingerprint>(); float one = 8192f / 5512; for (int i = 0; i < 100; ++i) { first.Add(new HashedFingerprint(new[] { 1 }, (uint)i, i * one)); second.Add(new HashedFingerprint(new[] { 2 }, (uint)i, i * one)); } var r = new Random(); var a = new TimedHashes(first.OrderBy(x => r.Next()).ToList(), DateTime.Parse("01/15/2019 10:00:00", dtfi)); var b = new TimedHashes(second.OrderBy(x => r.Next()).ToList(), DateTime.Parse("01/15/2019 10:00:01.3", dtfi)); Assert.IsTrue(a.MergeWith(b, out var c)); for (int i = 0; i < 200; ++i) { Assert.AreEqual(i, c.HashedFingerprints[i].SequenceNumber); if (i % 2 == 0) { Assert.AreEqual(one * (i / 2), c.HashedFingerprints[i].StartsAt, 0.0001); CollectionAssert.AreEqual(new[] { 1 }, c.HashedFingerprints[i].HashBins); } else { Assert.AreEqual(1.3f + one * (i / 2), c.HashedFingerprints[i].StartsAt, 0.0001); CollectionAssert.AreEqual(new[] { 2 }, c.HashedFingerprints[i].HashBins); } } }
public void ShouldMerge() { DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo("en-US").DateTimeFormat; float one = 8192f / 5512; var a = new TimedHashes(new List <HashedFingerprint> { new HashedFingerprint(new[] { 1 }, 1, one), new HashedFingerprint(new[] { 1 }, 2, 2 * one), new HashedFingerprint(new[] { 1 }, 0, 0), }, DateTime.Parse("01/15/2019 10:00:00", dtfi)); var b = new TimedHashes(new List <HashedFingerprint> { new HashedFingerprint(new[] { 2 }, 1, one), new HashedFingerprint(new[] { 2 }, 2, 2 * one), new HashedFingerprint(new[] { 2 }, 0, 0) }, DateTime.Parse("01/15/2019 10:00:01", dtfi)); Assert.IsTrue(a.MergeWith(b, out var result)); Assert.AreEqual(0, result.HashedFingerprints[0].StartsAt); Assert.AreEqual(1f, result.HashedFingerprints[1].StartsAt, 0.0001); Assert.AreEqual(one, result.HashedFingerprints[2].StartsAt, 0.0001); Assert.AreEqual(1 + one, result.HashedFingerprints[3].StartsAt, 0.0001); Assert.AreEqual(2 * one, result.HashedFingerprints[4].StartsAt, 0.0001); Assert.AreEqual(1 + 2 * one, result.HashedFingerprints[5].StartsAt, 0.0001); }
private static byte[] Serialize(TimedHashes timed) { byte[] buffer; using (var stream = new MemoryStream()) { Serializer.SerializeWithLengthPrefix(stream, timed, PrefixStyle.Fixed32); stream.Flush(); buffer = stream.GetBuffer(); } return(buffer); }
private TimedHashes StoreDowntimeEntries(List <HashedFingerprint> hashes, DateTime relativeTo) { double length = downtimeHashes.Sum(hash => hash.TotalSeconds); var timedHashes = new TimedHashes(hashes, relativeTo); if (length <= configuration.DowntimeCapturePeriod) { downtimeHashes.Enqueue(timedHashes); return(TimedHashes.Empty); } return(timedHashes); }
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 <TimedHashes>(); 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.HashedFingerprints.Count).Sum()); var merged = TimedHashes.Aggregate(list, 20d).ToList(); Assert.AreEqual(2, merged.Count); Assert.AreEqual(hashes.Count, merged.Select(entry => entry.HashedFingerprints.Count).Sum()); var aggregated = TimedHashes.Aggregate(list, double.MaxValue).ToList(); Assert.AreEqual(1, aggregated.Count); Assert.AreEqual(hashes.Count, aggregated[0].HashedFingerprints.Count); foreach (var zipped in hashes.OrderBy(h => h.SequenceNumber).Zip(aggregated[0].HashedFingerprints, (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); } }
public void ShouldMergeCorrectly() { float acc = 8192 / 5512f; var a = TimedHashes.Empty; var dateTime = DateTime.Now; var b = new TimedHashes(new List <HashedFingerprint>(new[] { new HashedFingerprint(new[] { 1 }, 0, 0) }), dateTime); var c = new TimedHashes(new List <HashedFingerprint>(new[] { new HashedFingerprint(new[] { 2 }, 0, 0f) }), dateTime.AddSeconds(acc)); var d = new TimedHashes(new List <HashedFingerprint>(new[] { new HashedFingerprint(new[] { 3 }, 0, 0f) }), dateTime.AddSeconds(2 * acc)); Assert.IsTrue(a.MergeWith(b, out var x)); Assert.IsTrue(x.MergeWith(c, out var y)); Assert.IsTrue(y.MergeWith(d, out var z)); Assert.AreEqual(dateTime, z.StartsAt); Assert.AreEqual(3, z.HashedFingerprints.Count); Assert.AreEqual(3 * acc, z.TotalSeconds, 0.001); }
public void CantMergeSinceTheGapIsTooBig() { var dtfi = CultureInfo.GetCultureInfo("en-US").DateTimeFormat; var a = new TimedHashes(new List <HashedFingerprint> { new HashedFingerprint(new[] { 1 }, 0, 0) }, DateTime.Parse("01/15/2019 10:00:00", dtfi)); var b = new TimedHashes(new List <HashedFingerprint> { new HashedFingerprint(new[] { 2 }, 0, 0) }, DateTime.Parse("01/15/2019 10:01:00", dtfi)); Assert.IsFalse(a.MergeWith(b, out _)); }
public async Task QueryingWithAggregatedHashesShouldResultInTheSameMatches() { var audioService = new SoundFingerprintingAudioService(); var modelService = new InMemoryModelService(); int count = 20, testWaitTime = 5000; var data = GenerateRandomAudioChunks(count, 1); 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, false, TimeSpan.FromMilliseconds); var cancellationTokenSource = new CancellationTokenSource(testWaitTime); var fingerprints = new List <TimedHashes>(); var entries = new List <ResultEntry>(); await QueryCommandBuilder.Instance.BuildRealtimeQueryCommand() .From(collection) .WithRealtimeQueryConfig(config => { config.QueryFingerprintsCallback += timedHashes => fingerprints.Add(timedHashes); config.SuccessCallback = entry => entries.Add(entry); config.ResultEntryFilter = new CoverageLengthEntryFilter(0.8d); return(config); }) .UsingServices(modelService) .Query(cancellationTokenSource.Token); Assert.IsTrue(entries.Any()); Assert.AreEqual(1, entries.Count); var aggregated = TimedHashes.Aggregate(fingerprints, 60d).ToList(); var result = await QueryCommandBuilder.Instance.BuildQueryCommand() .From(new Hashes(aggregated[0].HashedFingerprints, aggregated[0].TotalSeconds)) .UsingServices(modelService, audioService) .Query(aggregated[0].StartsAt); Assert.IsTrue(result.ContainsMatches); Assert.AreEqual(entries[0].MatchedAt, result.BestMatch.MatchedAt); }
public void CanSerializeAndDeserialize() { var list = GetHashedFingerprints(); var timed = new TimedHashes(list, DateTime.Now); var buffer = Serialize(timed); var deserialized = Deserialize(buffer); Assert.AreEqual(timed.HashedFingerprints.Count, deserialized.HashedFingerprints.Count); Assert.AreEqual(timed.StartsAt, deserialized.StartsAt); for (int i = 0; i < timed.HashedFingerprints.Count; ++i) { HashedFingerprint a = timed.HashedFingerprints[i]; HashedFingerprint b = deserialized.HashedFingerprints[i]; Assert.AreEqual(a.StartsAt, b.StartsAt); Assert.AreEqual(a.SequenceNumber, b.SequenceNumber); CollectionAssert.AreEqual(a.HashBins, b.HashBins); } }
private void InvokeExceptionCallback(Exception e, TimedHashes timedHashes) { configuration?.ErrorCallback(e, timedHashes); }