Skip to content

Commit 500fa59

Browse files
authored
Option for bulk audio conversion (#646)
1 parent 1c48a27 commit 500fa59

8 files changed

Lines changed: 91 additions & 35 deletions

File tree

FModel/Settings/UserSettings.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,13 @@ public bool ReadShaderMaps
266266
set => SetProperty(ref _readShaderMaps, value);
267267
}
268268

269+
private bool _convertAudioOnBulkExport;
270+
public bool ConvertAudioOnBulkExport
271+
{
272+
get => _convertAudioOnBulkExport;
273+
set => SetProperty(ref _convertAudioOnBulkExport, value);
274+
}
275+
269276
private IDictionary<string, DirectorySettings> _perDirectory = new Dictionary<string, DirectorySettings>();
270277
public IDictionary<string, DirectorySettings> PerDirectory
271278
{

FModel/ViewModels/AudioPlayerViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ private bool TryConvertCriware()
655655
}
656656

657657
private bool TryConvert(out string wavFilePath) => TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, out wavFilePath);
658-
private bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath)
658+
public static bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath)
659659
{
660660
wavFilePath = string.Empty;
661661
var vgmFilePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "test.exe");

FModel/ViewModels/CUE4ParseViewModel.cs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
780780
case "bank":
781781
{
782782
var archive = entry.CreateReader();
783-
if (!FModProvider.TryLoadBank(archive, entry.NameWithoutExtension, out var fmodReader))
783+
if (!FmodProvider.TryLoadBank(archive, entry.NameWithoutExtension, out var fmodReader))
784784
{
785785
Log.Error($"Failed to load FMOD bank {entry.Path}");
786786
break;
@@ -792,7 +792,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
792792
var directory = Path.GetDirectoryName(entry.Path) ?? "/FMOD/Desktop/";
793793
foreach (var sound in extractedSounds)
794794
{
795-
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
795+
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
796796
}
797797

798798
break;
@@ -807,7 +807,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
807807
var medias = WwiseProvider.ExtractBankSounds(wwise);
808808
foreach (var media in medias)
809809
{
810-
SaveAndPlaySound(media.OutputPath, media.Extension, media.Data, saveAudio);
810+
SaveAndPlaySound(media.OutputPath, media.Extension, media.Data, saveAudio, updateUi);
811811
}
812812

813813
break;
@@ -823,7 +823,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
823823
var extractedSounds = CriWareProvider.ExtractCriWareSounds(awbReader, archive.Name);
824824
foreach (var sound in extractedSounds)
825825
{
826-
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
826+
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
827827
}
828828

829829
break;
@@ -839,7 +839,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
839839
var extractedSounds = CriWareProvider.ExtractCriWareSounds(acbReader, archive.Name);
840840
foreach (var sound in extractedSounds)
841841
{
842-
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
842+
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
843843
}
844844

845845
break;
@@ -854,7 +854,7 @@ public void Extract(CancellationToken cancellationToken, GameFile entry, bool ad
854854
// todo: CSCore.MediaFoundation.MediaFoundationException The byte stream type of the given URL is unsupported. case "aif":
855855
{
856856
var data = Provider.SaveAsset(entry);
857-
SaveAndPlaySound(entry.PathWithoutExtension, entry.Extension, data, saveAudio);
857+
SaveAndPlaySound(entry.PathWithoutExtension, entry.Extension, data, saveAudio, updateUi);
858858

859859
break;
860860
}
@@ -1114,15 +1114,15 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11141114
case UExternalSource when (isNone || saveAudio) && pointer.Object.Value is UExternalSource externalSource:
11151115
{
11161116
var audioName = Path.GetFileNameWithoutExtension(externalSource.ExternalSourcePath);
1117-
SaveAndPlaySound(audioName, "wem", externalSource.Data?.WemFile ?? [], saveAudio);
1117+
SaveAndPlaySound(audioName, "wem", externalSource.Data?.WemFile ?? [], saveAudio, updateUi);
11181118
return false;
11191119
}
11201120
case UAkAudioEvent when (isNone || saveAudio) && pointer.Object.Value is UAkAudioEvent audioEvent:
11211121
{
11221122
var extractedSounds = WwiseProvider.ExtractAudioEventSounds(audioEvent);
11231123
foreach (var sound in extractedSounds)
11241124
{
1125-
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
1125+
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
11261126
}
11271127
return false;
11281128
}
@@ -1132,7 +1132,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11321132
var directory = Path.GetDirectoryName(fmodEvent.Owner?.Name) ?? "/FMOD/Desktop/";
11331133
foreach (var sound in extractedSounds)
11341134
{
1135-
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
1135+
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
11361136
}
11371137
return false;
11381138
}
@@ -1142,7 +1142,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11421142
var directory = Path.GetDirectoryName(fmodBank.Owner?.Name) ?? "/FMOD/Desktop/";
11431143
foreach (var sound in extractedSounds)
11441144
{
1145-
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
1145+
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
11461146
}
11471147
return false;
11481148
}
@@ -1161,7 +1161,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11611161
directory = Path.GetDirectoryName(atomObject.Owner.Provider.FixPath(directory));
11621162
foreach (var sound in extractedSounds)
11631163
{
1164-
SaveAndPlaySound(Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio);
1164+
SaveAndPlaySound(Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio, updateUi);
11651165
}
11661166
return false;
11671167
}
@@ -1181,7 +1181,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11811181
return false;
11821182
}
11831183

1184-
SaveAndPlaySound(TabControl.SelectedTab.Entry.PathWithoutExtension.Replace('\\', '/'), audioFormat, data, saveAudio);
1184+
SaveAndPlaySound(TabControl.SelectedTab.Entry.PathWithoutExtension.Replace('\\', '/'), audioFormat, data, saveAudio, updateUi);
11851185
return false;
11861186
}
11871187
case UAkMediaAsset when (isNone || saveAudio) && pointer.Object.Value is UAkMediaAsset akMediaAsset:
@@ -1192,7 +1192,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
11921192
var shouldDecompress = UserSettings.Default.CompressedAudioMode is ECompressedAudio.PlayDecompressed;
11931193
akMediaAssetData.Decode(shouldDecompress, out var audioFormat, out var data);
11941194

1195-
SaveAndPlaySound(audioName, audioFormat, data, saveAudio);
1195+
SaveAndPlaySound(audioName, audioFormat, data, saveAudio, updateUi);
11961196
}
11971197
return false;
11981198
}
@@ -1208,7 +1208,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
12081208
var audioName = akMediaAsset.MediaName ?? $"{akAudioEventData.Outer.Name} ({akMediaAsset.ID})";
12091209
akMediaAssetData.Decode(shouldDecompress, out var audioFormat, out var data);
12101210

1211-
SaveAndPlaySound(audioName, audioFormat, data, saveAudio);
1211+
SaveAndPlaySound(audioName, audioFormat, data, saveAudio, updateUi);
12121212
}
12131213
}
12141214
}
@@ -1225,7 +1225,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
12251225
var extractedSounds = WwiseProvider.ExtractAudioEventBorderlands4(faceFXAnimData.ID.Name, false);
12261226
foreach (var sound in extractedSounds)
12271227
{
1228-
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
1228+
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
12291229
}
12301230
}
12311231

@@ -1239,7 +1239,7 @@ public void ExtractAndScroll(CancellationToken cancellationToken, string fullPat
12391239
var extractedSounds = WwiseProvider.ExtractAudioEventBorderlands4(eventName, useSoundTag);
12401240
foreach (var sound in extractedSounds)
12411241
{
1242-
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
1242+
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
12431243
}
12441244
}
12451245

@@ -1379,7 +1379,7 @@ public void Decompile(GameFile entry)
13791379
TabControl.SelectedTab.SetDocumentText(cpp, false, false);
13801380
}
13811381

1382-
private void SaveAndPlaySound(string fullPath, string ext, byte[] data, bool isBulk)
1382+
private void SaveAndPlaySound(string fullPath, string ext, byte[] data, bool isBulk, bool updateUi)
13831383
{
13841384
if (fullPath.StartsWith('/')) fullPath = fullPath[1..];
13851385
var savedAudioPath = Path.Combine(UserSettings.Default.AudioDirectory,
@@ -1389,9 +1389,28 @@ private void SaveAndPlaySound(string fullPath, string ext, byte[] data, bool isB
13891389
{
13901390
Directory.CreateDirectory(savedAudioPath.SubstringBeforeLast('/'));
13911391
using var stream = new FileStream(savedAudioPath, FileMode.Create, FileAccess.Write);
1392-
using var writer = new BinaryWriter(stream);
1393-
writer.Write(data);
1394-
writer.Flush();
1392+
using (var writer = new BinaryWriter(stream))
1393+
{
1394+
writer.Write(data);
1395+
writer.Flush();
1396+
}
1397+
1398+
if (UserSettings.Default.ConvertAudioOnBulkExport)
1399+
{
1400+
AudioPlayerViewModel.TryConvert(savedAudioPath, data, out string wavFilePath);
1401+
savedAudioPath = wavFilePath;
1402+
}
1403+
1404+
Log.Information("Successfully saved {FilePath}", savedAudioPath);
1405+
if (updateUi)
1406+
{
1407+
FLogger.Append(ELog.Information, () =>
1408+
{
1409+
FLogger.Text("Successfully saved ", Constants.WHITE);
1410+
FLogger.Link(Path.GetFileName(savedAudioPath), savedAudioPath, true);
1411+
});
1412+
}
1413+
13951414
return;
13961415
}
13971416

FModel/ViewModels/Commands/MenuCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public override async void Execute(ApplicationViewModel contextViewModel, object
6565
Process.Start(new ProcessStartInfo { FileName = Constants.DISCORD_LINK, UseShellExecute = true });
6666
break;
6767
case "ToolBox_Clear_Logs":
68-
FLogger.Logger.Text = string.Empty;
68+
FLogger.ClearLogs();
6969
break;
7070
case "ToolBox_Open_Output_Directory":
7171
Process.Start(new ProcessStartInfo { FileName = UserSettings.Default.OutputDirectory, UseShellExecute = true });

FModel/ViewModels/GameFileViewModel.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using CUE4Parse.UE4.Assets.Exports.Engine;
2222
using CUE4Parse.UE4.Assets.Exports.Engine.Font;
2323
using CUE4Parse.UE4.Assets.Exports.Fmod;
24+
using CUE4Parse.UE4.Assets.Exports.FMod;
2425
using CUE4Parse.UE4.Assets.Exports.Foliage;
2526
using CUE4Parse.UE4.Assets.Exports.Internationalization;
2627
using CUE4Parse.UE4.Assets.Exports.LevelSequence;
@@ -240,6 +241,10 @@ private Task ResolveByPackageAsync(EResolveCompute resolve)
240241
USoundAtomCue or UAkAudioEvent or USoundCue or UFMODEvent
241242
or UAkAssetData or UAkAssetPlatformData => (EAssetCategory.AudioEvent, EBulkType.Audio),
242243

244+
UFMODBankLookup => (EAssetCategory.Data, EBulkType.None),
245+
246+
UFMODBus or UFMODSnapshot or UFMODSnapshotReverb or UFMODVCA => (EAssetCategory.Audio, EBulkType.None),
247+
243248
UFMODBank or UAkAudioBank or UAtomWaveBank or UAkInitBank => (EAssetCategory.SoundBank, EBulkType.Audio),
244249

245250
UWwiseAssetLibrary or USoundBase or UAkMediaAssetData or UAtomCueSheet
@@ -320,7 +325,8 @@ bool LookupPreview(FInstancedStruct[] dataList)
320325
private Task ResolveByExtensionAsync(EResolveCompute resolve)
321326
{
322327
Resolved |= EResolveCompute.Preview;
323-
switch (Asset.Extension)
328+
var lowercaseExtension = Asset.Extension.ToLowerInvariant();
329+
switch (lowercaseExtension)
324330
{
325331
case "uproject":
326332
case "uefnproject":
@@ -393,7 +399,7 @@ private Task ResolveByExtensionAsync(EResolveCompute resolve)
393399
stream.Position = 0;
394400

395401
SKBitmap bitmap;
396-
if (Asset.Extension == "svg")
402+
if (lowercaseExtension == "svg")
397403
{
398404
var svg = new SKSvg();
399405
svg.Load(stream);
@@ -415,7 +421,7 @@ private Task ResolveByExtensionAsync(EResolveCompute resolve)
415421
bitmap = SKBitmap.Decode(stream);
416422
}
417423

418-
using var image = bitmap.Encode(Asset.Extension == "jpg" ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100);
424+
using var image = bitmap.Encode(lowercaseExtension == "jpg" ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100);
419425
SetPreviewImage(image);
420426

421427
bitmap.Dispose();

FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ public void SetText(FlowDocument document, string text)
155155
{
156156
new TextRange(document.ContentStart, document.ContentEnd).Text = text;
157157
}
158+
159+
public static void ClearLogs()
160+
{
161+
Logger.Document.Blocks.Clear();
162+
_previous = 0;
163+
}
158164
}
159165

160166
public class CustomRichTextBox : RichTextBox

0 commit comments

Comments
 (0)