New mp3 options and improved encoding performance

This commit is contained in:
Michael Bucari-Tovo 2023-02-24 12:12:41 -07:00
parent 49982043e0
commit 1b0a7f5062
25 changed files with 299 additions and 63 deletions

View file

@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AAXClean.Codecs" Version="0.5.16" />
<PackageReference Include="AAXClean.Codecs" Version="1.0.0" />
</ItemGroup>
<ItemGroup>

View file

@ -40,8 +40,14 @@ namespace AaxDecrypter
AaxFile.AppleTags.Album = AaxFile.AppleTags.Album?.Replace(" (Unabridged)", "");
}
if (DownloadOptions.FixupFile && !string.IsNullOrWhiteSpace(AaxFile.AppleTags.Narrator))
AaxFile.AppleTags.AppleListBox.EditOrAddTag("TCOM", AaxFile.AppleTags.Narrator);
if (DownloadOptions.FixupFile)
{
if (!string.IsNullOrWhiteSpace(AaxFile.AppleTags.Narrator))
AaxFile.AppleTags.AppleListBox.EditOrAddTag("TCOM", AaxFile.AppleTags.Narrator);
if (!string.IsNullOrWhiteSpace(AaxFile.AppleTags.Copyright))
AaxFile.AppleTags.Copyright = AaxFile.AppleTags.Copyright.Replace("(P)", "℗").Replace("&#169;", "©");
}
//Finishing configuring lame encoder.
if (DownloadOptions.OutputFormat == OutputFormat.Mp3)

View file

@ -93,15 +93,13 @@ That naming may not be desirable for everyone, but it's an easy change to instea
? AaxFile.ConvertToMultiMp4aAsync
(
splitChapters,
newSplitCallback => newSplit(++chapterCount, splitChapters, newSplitCallback),
DownloadOptions.TrimOutputToChapterLength
newSplitCallback => newSplit(++chapterCount, splitChapters, newSplitCallback)
)
: AaxFile.ConvertToMultiMp3Async
(
splitChapters,
newSplitCallback => newSplit(++chapterCount, splitChapters, newSplitCallback),
DownloadOptions.LameConfig,
DownloadOptions.TrimOutputToChapterLength
DownloadOptions.LameConfig
);
void newSplit(int currentChapter, ChapterInfo splitChapters, NewSplitCallback newSplitCallback)

View file

@ -3,6 +3,7 @@ using AAXClean.Codecs;
using Dinah.Core.Net.Http;
using FileManager;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
@ -14,12 +15,15 @@ namespace AaxDecrypter
public AaxcDownloadSingleConverter(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
: base(outFileName, cacheDirectory, dlOptions)
{
var step = 1;
AsyncSteps.Name = $"Download and Convert Aaxc To {DownloadOptions.OutputFormat}";
AsyncSteps["Step 1: Get Aaxc Metadata"] = () => Task.Run(Step_GetMetadata);
AsyncSteps["Step 2: Download Decrypted Audiobook"] = Step_DownloadAndDecryptAudiobookAsync;
AsyncSteps["Step 3: Download Clips and Bookmarks"] = Step_DownloadClipsBookmarksAsync;
AsyncSteps["Step 4: Create Cue"] = Step_CreateCueAsync;
AsyncSteps[$"Step {step++}: Get Aaxc Metadata"] = () => Task.Run(Step_GetMetadata);
AsyncSteps[$"Step {step++}: Download Decrypted Audiobook"] = Step_DownloadAndDecryptAudiobookAsync;
if (DownloadOptions.MoveMoovToBeginning && DownloadOptions.OutputFormat is OutputFormat.M4b)
AsyncSteps[$"Step {step++}: Move moov atom to beginning"] = Step_MoveMoov;
AsyncSteps[$"Step {step++}: Download Clips and Bookmarks"] = Step_DownloadClipsBookmarksAsync;
AsyncSteps[$"Step {step++}: Create Cue"] = Step_CreateCueAsync;
}
protected async override Task<bool> Step_DownloadAndDecryptAudiobookAsync()
@ -31,18 +35,7 @@ namespace AaxDecrypter
try
{
await (AaxConversion = decryptAsync(outputFile));
if (AaxConversion.IsCompletedSuccessfully
&& DownloadOptions.MoveMoovToBeginning
&& DownloadOptions.OutputFormat is OutputFormat.M4b)
{
outputFile.Close();
AaxConversion = Mp4File.RelocateMoovAsync(OutputFileName);
AaxConversion.ConversionProgressUpdate += AaxConversion_MoovProgressUpdate;
await AaxConversion;
AaxConversion.ConversionProgressUpdate -= AaxConversion_MoovProgressUpdate;
}
await (AaxConversion = decryptAsync(outputFile));
return AaxConversion.IsCompletedSuccessfully;
}
@ -52,23 +45,30 @@ namespace AaxDecrypter
}
}
private async Task<bool> Step_MoveMoov()
{
AaxConversion = Mp4File.RelocateMoovAsync(OutputFileName);
AaxConversion.ConversionProgressUpdate += AaxConversion_MoovProgressUpdate;
await AaxConversion;
AaxConversion.ConversionProgressUpdate -= AaxConversion_MoovProgressUpdate;
return AaxConversion.IsCompletedSuccessfully;
}
private void AaxConversion_MoovProgressUpdate(object sender, ConversionProgressEventArgs e)
{
averageSpeed.AddPosition(e.ProcessPosition.TotalSeconds);
var remainingTimeToProcess = (e.TotalDuration - e.ProcessPosition).TotalSeconds;
var remainingTimeToProcess = (e.EndTime - e.ProcessPosition).TotalSeconds;
var estTimeRemaining = remainingTimeToProcess / averageSpeed.Average;
if (double.IsNormal(estTimeRemaining))
OnDecryptTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining));
var progressPercent = 100d * (1 - remainingTimeToProcess / e.TotalDuration.TotalSeconds);
OnDecryptProgressUpdate(
new DownloadProgress
{
ProgressPercentage = progressPercent,
BytesReceived = (long)(InputFileStream.Length * progressPercent),
ProgressPercentage = 100 * e.FractionCompleted,
BytesReceived = (long)(InputFileStream.Length * e.FractionCompleted),
TotalBytesToReceive = InputFileStream.Length
});
}
@ -79,15 +79,13 @@ namespace AaxDecrypter
(
outputFile,
DownloadOptions.LameConfig,
DownloadOptions.ChapterInfo,
DownloadOptions.TrimOutputToChapterLength
DownloadOptions.ChapterInfo
)
: DownloadOptions.FixupFile
? AaxFile.ConvertToMp4aAsync
(
outputFile,
DownloadOptions.ChapterInfo,
DownloadOptions.TrimOutputToChapterLength
DownloadOptions.ChapterInfo
)
: AaxFile.ConvertToMp4aAsync(outputFile);
}

View file

@ -27,6 +27,7 @@ namespace AaxDecrypter
protected IDownloadOptions DownloadOptions { get; }
protected NetworkFileStream InputFileStream => nfsPersister.NetworkFileStream;
protected virtual long InputFilePosition => InputFileStream.Position;
private bool downloadFinished;
private readonly NetworkFileStreamPersister nfsPersister;
private readonly DownloadProgress zeroProgress;
@ -84,7 +85,11 @@ namespace AaxDecrypter
{
AverageSpeed averageSpeed = new();
while (InputFileStream.CanRead && InputFileStream.Length > InputFilePosition && !InputFileStream.IsCancelled)
while (
InputFileStream.CanRead
&& InputFileStream.Length > InputFilePosition
&& !InputFileStream.IsCancelled
&& !downloadFinished)
{
averageSpeed.AddPosition(InputFilePosition);
@ -138,8 +143,7 @@ namespace AaxDecrypter
protected virtual void FinalizeDownload()
{
nfsPersister?.Dispose();
OnDecryptTimeRemaining(TimeSpan.Zero);
OnDecryptProgressUpdate(zeroProgress);
downloadFinished = true;
}
protected async Task<bool> Step_DownloadClipsBookmarksAsync()

View file

@ -1,5 +1,6 @@
using AAXClean;
using NAudio.Lame;
using System;
namespace AaxDecrypter
{
@ -9,17 +10,26 @@ namespace AaxDecrypter
{
double bitrateMultiple = 1;
if (mp4File.TimeScale < lameConfig.OutputSampleRate)
{
lameConfig.OutputSampleRate = mp4File.TimeScale;
}
else if (mp4File.TimeScale > lameConfig.OutputSampleRate)
{
bitrateMultiple *= (double)lameConfig.OutputSampleRate / mp4File.TimeScale;
}
if (mp4File.AudioChannels == 2)
{
if (downsample)
bitrateMultiple = 0.5;
bitrateMultiple /= 2;
else
lameConfig.Mode = MPEGMode.Stereo;
}
if (matchSourceBitrate)
{
int kbps = (int)(mp4File.AverageBitrate * bitrateMultiple / 1024);
int kbps = (int)Math.Round(mp4File.AverageBitrate * bitrateMultiple / 1024);
if (lameConfig.VBR is null)
lameConfig.BitRate = kbps;

View file

@ -14,6 +14,7 @@ namespace AaxDecrypter
public class NetworkFileStream : Stream, IUpdatable
{
public event EventHandler Updated;
public event EventHandler DownloadCompleted;
#region Public Properties
@ -139,7 +140,10 @@ namespace AaxDecrypter
public async Task BeginDownloadingAsync()
{
if (ContentLength != 0 && WritePosition == ContentLength)
{
_backgroundDownloadTask = Task.CompletedTask;
return;
}
if (ContentLength != 0 && WritePosition > ContentLength)
throw new WebException($"Specified write position (0x{WritePosition:X10}) is larger than {nameof(ContentLength)} (0x{ContentLength:X10}).");
@ -230,6 +234,7 @@ namespace AaxDecrypter
_writeFile.Close();
_downloadedPiece.Set();
OnUpdate();
DownloadCompleted?.Invoke(this, null);
}
}

View file

@ -26,8 +26,11 @@ namespace AaxDecrypter
protected override async Task<bool> Step_DownloadAndDecryptAudiobookAsync()
{
while (InputFilePosition < InputFileStream.Length && !InputFileStream.IsCancelled)
await Task.Delay(200);
TaskCompletionSource completionSource = new();
InputFileStream.DownloadCompleted += (_, _) => completionSource.SetResult();
await completionSource.Task;
if (IsCanceled)
return false;