From aa3c648c4c54fb6927595af26f379895ee637eb4 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 30 Jun 2021 13:21:39 -0600 Subject: [PATCH] Refactored remaining time estimate. --- AaxDecrypter/AaxcDownloadConverter.cs | 63 +++------------------------ AaxDecrypter/FFMpegAaxcProcesser.cs | 23 ++++++++-- 2 files changed, 25 insertions(+), 61 deletions(-) diff --git a/AaxDecrypter/AaxcDownloadConverter.cs b/AaxDecrypter/AaxcDownloadConverter.cs index 6c6aa3b3..5115bb58 100644 --- a/AaxDecrypter/AaxcDownloadConverter.cs +++ b/AaxDecrypter/AaxcDownloadConverter.cs @@ -168,72 +168,19 @@ namespace AaxDecrypter return aaxcProcesser.Succeeded; } - private void AaxcProcesser_ProgressUpdate(object sender, TimeSpan e) + private void AaxcProcesser_ProgressUpdate(object sender, AaxcProcessUpdate e) { - double averageRate = getAverageProcessRate(e); - double remainingSecsToProcess = (aaxcTagLib.Properties.Duration - e).TotalSeconds; - double estTimeRemaining = remainingSecsToProcess / averageRate; + double remainingSecsToProcess = (aaxcTagLib.Properties.Duration - e.ProcessPosition).TotalSeconds; + double estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed; if (double.IsNormal(estTimeRemaining)) - DecryptTimeRemaining?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining)); + DecryptTimeRemaining?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining)); - double progressPercent = 100 * e.TotalSeconds / aaxcTagLib.Properties.Duration.TotalSeconds; + double progressPercent = 100 * e.ProcessPosition.TotalSeconds / aaxcTagLib.Properties.Duration.TotalSeconds; DecryptProgressUpdate?.Invoke(this, (int)progressPercent); } - /// - /// Calculates the average processing rate based on the last 2 to samples. - /// - /// Position in the audio file last processed - /// The average processing rate, in book_duration_seconds / second. - private double getAverageProcessRate(TimeSpan lastProcessedPosition) - { - streamPositions.Enqueue(new StreamPosition - { - ProcessPosition = lastProcessedPosition, - EventTime = DateTime.Now, - }); - - if (streamPositions.Count < 2) - return double.PositiveInfinity; - - //Calculate the harmonic mean of the last 2 to MAX_NUM_AVERAGE progress updates - //Units are Book_Duration_Seconds / second - - var lastPos = streamPositions.Count > MAX_NUM_AVERAGE ? streamPositions.Dequeue() : null; - - double harmonicDenominator = 0; - int harmonicNumerator = 0; - - foreach (var pos in streamPositions) - { - if (lastPos is null) - { - lastPos = pos; - continue; - } - double dP = (pos.ProcessPosition - lastPos.ProcessPosition).TotalSeconds; - double dT = (pos.EventTime - lastPos.EventTime).TotalSeconds; - - harmonicDenominator += dT / dP; - harmonicNumerator++; - lastPos = pos; - } - - double harmonicMean = harmonicNumerator / harmonicDenominator; - return harmonicMean; - } - - private const int MAX_NUM_AVERAGE = 15; - private class StreamPosition - { - public TimeSpan ProcessPosition { get; set; } - public DateTime EventTime { get; set; } - } - - private Queue streamPositions = new Queue(); - /// /// Copy all aacx metadata to m4b file, including cover art. /// diff --git a/AaxDecrypter/FFMpegAaxcProcesser.cs b/AaxDecrypter/FFMpegAaxcProcesser.cs index 89734dcf..6c144a3f 100644 --- a/AaxDecrypter/FFMpegAaxcProcesser.cs +++ b/AaxDecrypter/FFMpegAaxcProcesser.cs @@ -7,13 +7,25 @@ using System.Threading.Tasks; namespace AaxDecrypter { + class AaxcProcessUpdate + { + public AaxcProcessUpdate(TimeSpan position, double speed) + { + ProcessPosition = position; + ProcessSpeed = speed; + EventTime = DateTime.Now; + } + public TimeSpan ProcessPosition { get; } + public double ProcessSpeed { get; } + public DateTime EventTime { get; } + } /// /// Download audible aaxc, decrypt, and remux with chapters. /// class FFMpegAaxcProcesser { - public event EventHandler ProgressUpdate; + public event EventHandler ProgressUpdate; public string FFMpegPath { get; } public DownloadLicense DownloadLicense { get; } public bool IsRunning { get; private set; } @@ -24,7 +36,7 @@ namespace AaxDecrypter private StringBuilder remuxerError = new StringBuilder(); private StringBuilder downloaderError = new StringBuilder(); - private static Regex processedTimeRegex = new Regex("time=(\\d{2}):(\\d{2}):(\\d{2}).\\d{2}", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static Regex processedTimeRegex = new Regex("time=(\\d{2}):(\\d{2}):(\\d{2}).\\d{2}.*speed=\\s{0,1}([0-9]*[.]?[0-9]+)(?:e\\+([0-9]+)){0,1}", RegexOptions.IgnoreCase | RegexOptions.Compiled); private Process downloader; private Process remuxer; @@ -115,6 +127,7 @@ namespace AaxDecrypter if (processedTimeRegex.IsMatch(e.Data)) { //get timestamp of of last processed audio stream position + //and processing speed var match = processedTimeRegex.Match(e.Data); int hours = int.Parse(match.Groups[1].Value); @@ -123,7 +136,11 @@ namespace AaxDecrypter var position = new TimeSpan(hours, minutes, seconds); - ProgressUpdate?.Invoke(sender, position); + double speed = double.Parse(match.Groups[4].Value); + int exp = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0; + speed *= Math.Pow(10, exp); + + ProgressUpdate?.Invoke(this, new AaxcProcessUpdate(position, speed)); } if (e.Data.Contains("aac bitstream error"))