Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  Version bump. Adding release notes.
  More logging messages.
  Fixing realtime query source failures to generate audio samples should not result in double AV result entry registration because of a purge operation that is followed by query source continuation.
  Wording.
  • Loading branch information
AddictedCS committed Dec 28, 2023
2 parents a0ba5b4 + f369f3a commit 34edba8
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Read [Supported Media Formats][audio-services-wiki-page] page for details about
Since `v8.0.0` video fingerprinting support has been added. Similarly to audio fingerprinting, video fingerprints are generated from video frames, and used to insert and later query the datastore for exact and similar matches. You can use `SoundFingerprinting` to fingerprint either audio or video content or both at the same time. More details about video fingerprinting are available [here][video-fingerprinting-wiki-page].

### Version 9
Version 9 was released to accomodate `SoundFingerprinting.Emy` v9.0.0, which upgrades to FFmpeg v5.x (breaking change as prior versions are using FFmpeg v4.x.
Version 9 was released to accomodate `SoundFingerprinting.Emy` v9.0.0, which upgrades to FFmpeg v5.x (breaking change as v8.x is using FFmpeg v4.x).
If you are not using `SoundFingerprinting.Emy` you can safely upgrade to v9.


Expand Down
4 changes: 2 additions & 2 deletions src/SoundFingerprinting.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("4cac962e-ebc5-4006-a1e0-7ffb3e2483c2")]
[assembly: AssemblyVersion("9.0.0.101")]
[assembly: AssemblyInformationalVersion("9.0.0.101")]
[assembly: AssemblyVersion("9.1.0.100")]
[assembly: AssemblyInformationalVersion("9.1.0.100")]
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,57 @@ await QueryCommandBuilder.Instance
Assert.IsTrue(errored);
}

[Test]
public async Task ShouldHandleExceptionInRealtimeSource()
{
var modelService = new InMemoryModelService();

int count = 20;
var data = GenerateRandomAudioChunks(count, 1, DateTime.UtcNow);
var concatenated = Concatenate(data);
var hashes = await FingerprintCommandBuilder.Instance
.BuildFingerprintCommand()
.From(concatenated)
.WithFingerprintConfig(config => config)
.Hash();

modelService.Insert(new TrackInfo("312", "Bohemian Rhapsody", "Queen"), hashes);

var collection = SimulateRealtimeAudioQueryData(data, jitterLength: 0);
var withFailure = SimulateFailure(collection, throwExceptionAfter: 15);

var success = new List<AVResultEntry>();
var didNotPass = new List<AVResultEntry>();
await QueryCommandBuilder.Instance.BuildRealtimeQueryCommand()
.From(withFailure)
.WithRealtimeQueryConfig(config =>
{
config.ResultEntryFilter = new TrackRelativeCoverageLengthEntryFilter(coverage: 0.2, waitTillCompletion: true);
config.SuccessCallback = _ => success.AddRange(_.ResultEntries);
config.DidNotPassFilterCallback = _ => didNotPass.AddRange(_.ResultEntries);
config.ErrorCallback = (Action<Exception, AVHashes>)((exception, _) => logger.LogError(exception, "An error occured while querying stream"));
return config;
})
.UsingServices(modelService)
.Query(CancellationToken.None);

Assert.That(success.Count, Is.EqualTo(1));
Assert.That(didNotPass.Count, Is.Zero);
}

private static async IAsyncEnumerable<AudioSamples> SimulateFailure(IAsyncEnumerable<AudioSamples> collection, int throwExceptionAfter)
{
await foreach (var audioSamples in collection)
{
if (throwExceptionAfter-- == 0)
{
throw new Exception("Error while reading samples from the source.");
}

yield return audioSamples;
}
}

private static async IAsyncEnumerable<AVTrack> GetSamples(int count, int seconds, [EnumeratorCancellation] CancellationToken cancellationToken, int sampleRate = 5512, int delay = 0)
{
foreach (var track in Enumerable.Range(0, count).Select(_ => new AVTrack(new AudioTrack(TestUtilities.GenerateRandomAudioSamples(seconds * sampleRate, sampleRate: sampleRate)), null)))
Expand Down
30 changes: 21 additions & 9 deletions src/SoundFingerprinting/Command/RealtimeQueryCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,28 +285,40 @@ private async Task<double> QueryRealtimeSource(CancellationToken cancellationTok
{
await QueryFromRealtimeAndOffline(resultsAggregator, cancellationToken);
logger.LogInformation("Stopped querying realtime source after {QueryLength:00} seconds", queryLength);
PurgeResultEntryAggregator(resultsAggregator);
return queryLength;
}
catch (Exception e) when (e is OperationCanceledException or ObjectDisposedException)
{
PurgeResultEntryAggregator(resultsAggregator);
throw;
}
catch (Exception e)
{
// here we catch exceptions that occur while reading from the realtime source
HandleQueryFailure(null, e);
try
{
// here we catch exceptions that occur while reading from the realtime source
HandleQueryFailure(null, e);
}
catch (Exception e2)
{
logger.LogWarning(e2, "Failed to handle query failure. Purging realtime aggregator, exiting query loop");
PurgeResultEntryAggregator(resultsAggregator);
throw;
}

await Task.Delay(configuration.ErrorBackoffPolicy.RemainingDelay, cancellationToken);
}
finally
{
// let's purge stateful results aggregator to safe-guard ourselves from memory issues when certain tracks get stuck in the aggregator
var purged = resultsAggregator.Purge();
InvokeCallbackHandler(purged.SuccessEntries, configuration?.SuccessCallback);
InvokeCallbackHandler(purged.DidNotPassThresholdEntries, configuration?.DidNotPassFilterCallback);
}
}
}

private void PurgeResultEntryAggregator(IRealtimeResultEntryAggregator resultsAggregator)
{
var purged = resultsAggregator.Purge();
InvokeCallbackHandler(purged.SuccessEntries, configuration?.SuccessCallback);
InvokeCallbackHandler(purged.DidNotPassThresholdEntries, configuration?.DidNotPassFilterCallback);
}

/// <summary>
/// Query from realtime and offline sources.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/SoundFingerprinting/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
[assembly: InternalsVisibleTo("SoundFingerprinting.FFT.FFTW")]
[assembly: InternalsVisibleTo("SoundFingerprinting.FFT.FFTW.Tests")]

[assembly: AssemblyVersion("9.0.0.101")]
[assembly: AssemblyInformationalVersion("9.0.0.101")]
[assembly: AssemblyVersion("9.1.0.100")]
[assembly: AssemblyInformationalVersion("9.1.0.100")]
7 changes: 3 additions & 4 deletions src/SoundFingerprinting/SoundFingerprinting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>enable</Nullable>
<PackageVersion>9.0.0</PackageVersion>
<PackageVersion>9.1.0</PackageVersion>
<Authors>Sergiu Ciumac</Authors>
<PackageDescription>SoundFingerprinting is a C# framework that implements an efficient algorithm of audio fingerprinting and identification. Designed for developers, enthusiasts, researchers in the fields of audio processing, data mining, digital signal processing.</PackageDescription>
<PackageProjectUrl>https://github.com/addictedcs/soundfingerprinting</PackageProjectUrl>
<RepositoryUrl>https://github.com/AddictedCS/soundfingerprinting</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageReleaseNotes>
Version bump to v9.0.0 accomodating SoundFingerprinting.Emy version upgrade.
If you are using SoundFingerprinting.Emy, please upgrade your FFmpeg library to v5. FFmpeg v4 will not be working with SoundFingerprinting.Emy v9.0.0.
If you are not using SoundFingerprinting.Emy, you can safely ignore this message.
Version bump to v9.1.0.
Realtime result entry aggregator may have been registering duplicate matches, during an error that happened while reading from realtime media service. This is now fixed.
</PackageReleaseNotes>
<PackageTags>Audio Video Identification Fingerprinting Digital Signal Processing Music Recognition Data Mining Content Sound Shazam</PackageTags>
<LangVersion>latest</LangVersion>
Expand Down

0 comments on commit 34edba8

Please sign in to comment.