public void ShouldMergeResults() { var aggregator = new StatefulRealtimeResultEntryAggregator(new QueryMatchLengthFilter(5d), 1.48d); var success = new List <ResultEntry>(); var filtered = new List <ResultEntry>(); SimulateEmptyResults(aggregator, success, filtered); Assert.IsTrue(!success.Any()); for (int i = 0; i < 10; ++i) { var entry = new ResultEntry(GetTrack(), 0.01233, 0, DateTime.Now, 1.48d, 0d, 1.48d, 1.48d, 10d + i * 1.48d, -10d - i * 1.48d); var aggregated = aggregator.Consume(new[] { entry }, 1.48d); AddAll(aggregated.SuccessEntries, success); AddAll(aggregated.DidNotPassThresholdEntries, filtered); } SimulateEmptyResults(aggregator, success, filtered); Assert.AreEqual(2, success.Count); Assert.AreEqual(1, filtered.Count); Assert.IsTrue(success[0].CoverageWithPermittedGapsLength > 5d); Assert.IsTrue(success[1].CoverageWithPermittedGapsLength > 5d); Assert.IsTrue(filtered[0].CoverageWithPermittedGapsLength < 5d); }
public void ShouldMergeResults() { double permittedGap = 1d; var aggregator = new StatefulRealtimeResultEntryAggregator(new QueryMatchLengthFilter(5d), permittedGap); var success = new List <ResultEntry>(); var filtered = new List <ResultEntry>(); SimulateEmptyResults(aggregator, success, filtered); Assert.IsTrue(!success.Any()); for (int i = 0; i < 10; ++i) { var entry = new ResultEntry(GetTrack(), 0, DateTime.Now, TestUtilities.GetMatchedWith(new[] { i }, new[] { i }).EstimateCoverage(1, 10, 1, permittedGap)); var aggregated = aggregator.Consume(new[] { entry }, 1); AddAll(aggregated.SuccessEntries, success); AddAll(aggregated.DidNotPassThresholdEntries, filtered); } SimulateEmptyResults(aggregator, success, filtered); Assert.AreEqual(1, success.Count); Assert.AreEqual(1, filtered.Count); Assert.IsTrue(success[0].TrackCoverageWithPermittedGapsLength > 5d); Assert.IsTrue(filtered[0].TrackCoverageWithPermittedGapsLength < 5d); }
public void ShouldMergeResults() { double permittedGap = 2d; var aggregator = new StatefulRealtimeResultEntryAggregator(new TrackMatchLengthEntryFilter(5d), GetConfigWithPermittedGap(permittedGap)); var success = new List<ResultEntry>(); var filtered = new List<ResultEntry>(); SimulateEmptyResults(aggregator, success, filtered); Assert.IsEmpty(success); Assert.IsEmpty(filtered); const int queryLength = 1; const int trackLength = 10; const int fingerprintLength = 1; for (int i = 0; i < 10; ++i) { var entry = new ResultEntry(GetTrack(trackLength), 0, DateTime.Now, TestUtilities.GetMatchedWith(new[] { 0 }, new[] { i }).EstimateCoverage(queryLength, trackLength, fingerprintLength, permittedGap)); var aggregated = aggregator.Consume(new[] { entry }, queryLength, 0); AddAll(aggregated.SuccessEntries, success); AddAll(aggregated.DidNotPassThresholdEntries, filtered); } SimulateEmptyResults(aggregator, success, filtered); Assert.AreEqual(1, success.Count); Assert.AreEqual(1, filtered.Count); Assert.IsTrue(success[0].TrackCoverageWithPermittedGapsLength > 5d); Assert.IsTrue(filtered[0].TrackCoverageWithPermittedGapsLength < 5d); }
public void ShouldWaitAsGapPermits() { double permittedGap = 5d; var aggregator = new StatefulRealtimeResultEntryAggregator(new TrackMatchLengthEntryFilter(10d), GetConfigWithPermittedGap(permittedGap)); int firstQueryLength = 5; int trackLength = 5; var first = aggregator.Consume(new[] { new ResultEntry(GetTrack(trackLength), 100, DateTime.Now, TestUtilities.GetMatchedWith(new[] {0, 1, 2, 3, 4}, new[] {0, 1, 2, 3, 4}).EstimateCoverage(firstQueryLength, trackLength, 1, permittedGap)) }, firstQueryLength, 0); Assert.IsFalse(first.SuccessEntries.Any()); Assert.IsFalse(first.DidNotPassThresholdEntries.Any()); for (int i = 0; i < 5; ++i) { var second = aggregator.Consume(new ResultEntry[0], 1, 0); Assert.IsFalse(second.SuccessEntries.Any(), $"Iteration {i}"); Assert.IsFalse(second.DidNotPassThresholdEntries.Any(), $"Iteration {i}"); } var third = aggregator.Consume(new ResultEntry[0], 1, 0); Assert.IsFalse(third.SuccessEntries.Any()); Assert.IsTrue(third.DidNotPassThresholdEntries.Any()); }
private static void SimulateEmptyResults(StatefulRealtimeResultEntryAggregator aggregator, ICollection <ResultEntry> success, ICollection <ResultEntry> filtered) { for (int i = 0; i < 10; ++i) { var aggregated = aggregator.Consume(new ResultEntry[0], 1.48d); AddAll(aggregated.SuccessEntries, success); AddAll(aggregated.DidNotPassThresholdEntries, filtered); } }
public void ShouldNotFailWithNullObjectPass() { var aggregator = new StatefulRealtimeResultEntryAggregator(new QueryMatchLengthFilter(5d), 2d); var result = aggregator.Consume(null, 0d); Assert.IsFalse(result.SuccessEntries.Any()); Assert.IsFalse(result.DidNotPassThresholdEntries.Any()); }
public void ShouldNotFailWithNullObjectPass() { var aggregator = new StatefulRealtimeResultEntryAggregator(new TrackMatchLengthEntryFilter(5d), GetConfigWithPermittedGap(2d)); var result = aggregator.Consume(null, 0, 0); Assert.IsFalse(result.SuccessEntries.Any()); Assert.IsFalse(result.DidNotPassThresholdEntries.Any()); }
private async Task <double> QueryAndHash(CancellationToken cancellationToken, IQueryFingerprintService service) { var realtimeSamplesAggregator = new RealtimeAudioSamplesAggregator(configuration.Stride, MinSamplesForOneFingerprint); var resultsAggregator = new StatefulRealtimeResultEntryAggregator(configuration.ResultEntryFilter, configuration.PermittedGap); double queryLength = 0d; while (!realtimeCollection.IsFinished && !cancellationToken.IsCancellationRequested) { AudioSamples audioSamples; try { if (!realtimeCollection.TryTake(out audioSamples, configuration.MillisecondsDelay, cancellationToken)) { continue; } } catch (OperationCanceledException) { return(queryLength); } if (audioSamples.SampleRate != SupportedFrequency) { throw new ArgumentException($"{nameof(audioSamples)} should be provided down sampled to {SupportedFrequency}Hz"); } queryLength += audioSamples.Duration; var prefixed = realtimeSamplesAggregator.Aggregate(audioSamples); var hashes = await CreateQueryFingerprints(fingerprintCommandBuilder, prefixed); InvokeHashedFingerprintsCallback(hashes); if (!TryQuery(service, hashes, out var queryResults)) { continue; } foreach (var queryResult in queryResults) { var aggregatedResult = resultsAggregator.Consume(queryResult.ResultEntries, prefixed.Duration); InvokeSuccessHandler(aggregatedResult); InvokeDidNotPassFilterHandler(aggregatedResult); } } return(queryLength); }
private async Task <double> QueryAndHash(CancellationToken cancellationToken, IQueryFingerprintService service) { var realtimeSamplesAggregator = new RealtimeAudioSamplesAggregator(configuration.Stride, MinSamplesForOneFingerprint); var resultsAggregator = new StatefulRealtimeResultEntryAggregator(configuration.ResultEntryFilter, configuration.QueryConfiguration); double queryLength = 0d; AudioSamples?audioSamples; while ((audioSamples = await realtimeCollection.TryReadAsync(cancellationToken)) != null) { if (audioSamples.SampleRate != SupportedFrequency) { throw new ArgumentException($"{nameof(audioSamples)} should be provided down sampled to {SupportedFrequency}Hz"); } queryLength += audioSamples.Duration; var prefixed = realtimeSamplesAggregator.Aggregate(audioSamples); var hashes = await CreateQueryFingerprints(fingerprintCommandBuilder, prefixed); InvokeHashedFingerprintsCallback(hashes); if (!TryQuery(service, hashes, out var queryResults)) { continue; } foreach (var queryResult in queryResults) { var aggregatedResult = resultsAggregator.Consume(queryResult.ResultEntries, hashes.DurationInSeconds, audioSamples.Duration - prefixed.Duration); InvokeSuccessHandler(aggregatedResult); InvokeDidNotPassFilterHandler(aggregatedResult); } } var purged = resultsAggregator.Consume(Enumerable.Empty <ResultEntry>(), 0, 0); InvokeSuccessHandler(purged); InvokeDidNotPassFilterHandler(purged); return(queryLength); }
public void ShouldWaitAsGapPermits() { var aggregator = new StatefulRealtimeResultEntryAggregator(new QueryMatchLengthFilter(10d), 2d); var first = aggregator.Consume(new[] { new ResultEntry(GetTrack(), .95d, 120, DateTime.Now, 5d, 0d, 2d, 2d, 10d, -10d) }, 5d); Assert.IsFalse(first.SuccessEntries.Any()); Assert.IsFalse(first.DidNotPassThresholdEntries.Any()); for (int i = 0; i < 10; ++i) { var second = aggregator.Consume(new ResultEntry[0], 0.2d); Assert.IsFalse(second.SuccessEntries.Any()); Assert.IsFalse(second.DidNotPassThresholdEntries.Any()); } var third = aggregator.Consume(new ResultEntry[0], 0.2d); Assert.IsFalse(third.SuccessEntries.Any()); Assert.IsTrue(third.DidNotPassThresholdEntries.Any()); }
public void ShouldWaitAsGapPermits() { double permittedGap = 2d; var aggregator = new StatefulRealtimeResultEntryAggregator(new QueryMatchLengthFilter(10d), permittedGap); var first = aggregator.Consume(new[] { new ResultEntry(GetTrack(), 100, DateTime.Now, TestUtilities.GetMatchedWith(new[] { 1, 2, 3 }, new[] { 1, 2, 3 }).EstimateCoverage(5, 3, 1, permittedGap)) }, 5d); Assert.IsFalse(first.SuccessEntries.Any()); Assert.IsFalse(first.DidNotPassThresholdEntries.Any()); for (int i = 0; i < 10; ++i) { var second = aggregator.Consume(new ResultEntry[0], 0.2d); Assert.IsFalse(second.SuccessEntries.Any()); Assert.IsFalse(second.DidNotPassThresholdEntries.Any()); } var third = aggregator.Consume(new ResultEntry[0], 0.2d); Assert.IsFalse(third.SuccessEntries.Any()); Assert.IsTrue(third.DidNotPassThresholdEntries.Any()); }
private async Task <double> QueryAndHash(CancellationToken cancellationToken, IQueryFingerprintService service) { var realtimeSamplesAggregator = new RealtimeAudioSamplesAggregator(configuration.Stride, MinSamplesForOneFingerprint); var resultsAggregator = new StatefulRealtimeResultEntryAggregator(configuration.ResultEntryFilter, configuration.QueryConfiguration); double queryLength = 0d; await foreach (var audioSamples in realtimeCollection.WithCancellation(cancellationToken)) { if (audioSamples.SampleRate != SupportedFrequency) { throw new ArgumentException($"{nameof(audioSamples)} should be provided down sampled to {SupportedFrequency}Hz"); } queryLength += audioSamples.Duration; var prefixed = realtimeSamplesAggregator.Aggregate(audioSamples); var hashes = (await CreateQueryFingerprints(fingerprintCommandBuilder, prefixed)).WithStreamId(streamId); hashes = hashesInterceptor(hashes).WithTimeOffset(audioSamples.Duration - hashes.DurationInSeconds); if (!TryQuery(service, hashes, out var queryResults)) { continue; } foreach (var queryResult in queryResults) { var aggregatedResult = resultsAggregator.Consume(queryResult.ResultEntries, queryResult.QueryHashes.DurationInSeconds, queryResult.QueryHashes.TimeOffset); InvokeSuccessHandler(aggregatedResult); InvokeDidNotPassFilterHandler(aggregatedResult); } } var purged = resultsAggregator.Purge(); InvokeSuccessHandler(purged); InvokeDidNotPassFilterHandler(purged); return(queryLength); }