Update comments and add CountBits unit test

This commit is contained in:
ConfusedPolarBear 2022-05-10 02:10:39 -05:00
parent 96333f5f9e
commit 2a94a9f103
3 changed files with 33 additions and 15 deletions

View File

@ -11,6 +11,18 @@ public class TestFPCalc
Assert.True(FPCalc.CheckFPCalcInstalled()); Assert.True(FPCalc.CheckFPCalcInstalled());
} }
[Theory]
[InlineData(0, 0)]
[InlineData(1, 1)]
[InlineData(5, 213)]
[InlineData(10, 56_021)]
[InlineData(16, 16_112_341)]
[InlineData(19, 2_465_585_877)]
public void TestBitCounting(int expectedBits, uint number)
{
Assert.Equal(expectedBits, FingerprinterTask.CountBits(number));
}
[Fact] [Fact]
public void TestFingerprinting() public void TestFingerprinting()
{ {

View File

@ -82,7 +82,7 @@ public class Entrypoint : IServerEntryPoint
private void QueueLibraryContents(string rawId) private void QueueLibraryContents(string rawId)
{ {
// FIXME: do smarterer // FIXME: don't do this
var query = new UserViewQuery() var query = new UserViewQuery()
{ {

View File

@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging;
namespace ConfusedPolarBear.Plugin.IntroSkipper; namespace ConfusedPolarBear.Plugin.IntroSkipper;
/// <summary> /// <summary>
/// Fingerprint all queued episodes at the set time. /// Fingerprint and analyze all queued episodes for common audio sequences.
/// </summary> /// </summary>
public class FingerprinterTask : IScheduledTask public class FingerprinterTask : IScheduledTask
{ {
@ -24,12 +24,12 @@ public class FingerprinterTask : IScheduledTask
private const double MaximumDifferences = 3; private const double MaximumDifferences = 3;
/// <summary> /// <summary>
/// Maximum time permitted between timestamps before they are considered non-contiguous. /// Maximum time (in seconds) permitted between timestamps before they are considered non-contiguous.
/// </summary> /// </summary>
private const double MaximumDistance = 3.25; private const double MaximumDistance = 3.25;
/// <summary> /// <summary>
/// Seconds of audio in one number from the fingerprint. Defined by Chromaprint. /// Seconds of audio in one fingerprint point. This value is defined by the Chromaprint library and should not be changed.
/// </summary> /// </summary>
private const double SamplesToSeconds = 0.128; private const double SamplesToSeconds = 0.128;
@ -72,7 +72,7 @@ public class FingerprinterTask : IScheduledTask
/// <summary> /// <summary>
/// Analyze all episodes in the queue. /// Analyze all episodes in the queue.
/// </summary> /// </summary>
/// <param name="progress">Progress.</param> /// <param name="progress">Task progress.</param>
/// <param name="cancellationToken">Cancellation token.</param> /// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken) public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
@ -84,8 +84,11 @@ public class FingerprinterTask : IScheduledTask
{ {
var first = season.Value[0]; var first = season.Value[0];
// Don't analyze seasons with <= 1 episode or specials /* Don't analyze specials or seasons with an insufficient number of episodes.
if (season.Value.Count <= 1 || first.SeasonNumber == 0) * A season with only 1 episode can't be analyzed as it would compare the episode to itself,
* which would result in the entire episode being marked as an introduction, as the audio is identical.
*/
if (season.Value.Count < 2 || first.SeasonNumber == 0)
{ {
continue; continue;
} }
@ -222,8 +225,6 @@ public class FingerprinterTask : IScheduledTask
// TODO: if an episode fails but others in the season succeed, reanalyze it against two that succeeded. // TODO: if an episode fails but others in the season succeed, reanalyze it against two that succeeded.
// TODO: is this the optimal way to indicate that an intro couldn't be found?
// the goal here is to not waste time every task run reprocessing episodes that we know will fail.
StoreIntro(lhsEpisode.EpisodeId, 0, 0); StoreIntro(lhsEpisode.EpisodeId, 0, 0);
StoreIntro(rhsEpisode.EpisodeId, 0, 0); StoreIntro(rhsEpisode.EpisodeId, 0, 0);
@ -353,13 +354,13 @@ public class FingerprinterTask : IScheduledTask
// Tweak the end timestamps just a bit to ensure as little content as possible is skipped over. // Tweak the end timestamps just a bit to ensure as little content as possible is skipped over.
if (lContiguous.Duration >= 90) if (lContiguous.Duration >= 90)
{ {
lContiguous.End -= 6; lContiguous.End -= 2 * MaximumDistance;
rContiguous.End -= 6; rContiguous.End -= 2 * MaximumDistance;
} }
else if (lContiguous.Duration >= 35) else if (lContiguous.Duration >= 35)
{ {
lContiguous.End -= 3; lContiguous.End -= MaximumDistance;
rContiguous.End -= 3; rContiguous.End -= MaximumDistance;
} }
return (lContiguous, rContiguous); return (lContiguous, rContiguous);
@ -370,7 +371,7 @@ public class FingerprinterTask : IScheduledTask
var intro = new Intro() var intro = new Intro()
{ {
EpisodeId = episode, EpisodeId = episode,
Valid = introEnd > 0, Valid = introEnd > 0, // don't test introStart here as the intro could legitimately happen at the start.
IntroStart = introStart, IntroStart = introStart,
IntroEnd = introEnd IntroEnd = introEnd
}; };
@ -384,7 +385,12 @@ public class FingerprinterTask : IScheduledTask
Plugin.Instance.Intros[episode] = intro; Plugin.Instance.Intros[episode] = intro;
} }
private static int CountBits(uint number) /// <summary>
/// Count the number of bits that are set in the provided number.
/// </summary>
/// <param name="number">Number to count bits in.</param>
/// <returns>Number of bits that are equal to 1.</returns>
public static int CountBits(uint number)
{ {
var count = 0; var count = 0;