diff --git a/FreeMote.Plugins/Audio/OpusFormatter.cs b/FreeMote.Plugins/Audio/OpusFormatter.cs index a77a020..ed2e38f 100644 --- a/FreeMote.Plugins/Audio/OpusFormatter.cs +++ b/FreeMote.Plugins/Audio/OpusFormatter.cs @@ -14,7 +14,7 @@ namespace FreeMote.Plugins.Audio [Export(typeof(IPsbAudioFormatter))] [ExportMetadata("Name", "FreeMote.NxOpus")] [ExportMetadata("Author", "Ulysses")] - [ExportMetadata("Comment", "NX Opus support via VGAudio.")] + [ExportMetadata("Comment", "NX/Android Opus support via VGAudio.")] class OpusFormatter : IPsbAudioFormatter { public List Extensions { get; } = new List {".opus"}; @@ -29,9 +29,13 @@ public bool CanToArchData(byte[] wave, Dictionary context = null return wave != null; } + public static bool IsOgg(byte[] data) + { + return data != null && data.Length > 4 && data[0] == 'O' && data[1] == 'g' && data[2] == 'g' && data[3] == 'S'; + } + public byte[] ToWave(AudioMetadata md, IArchData archData, string fileName = null, Dictionary context = null) { - NxOpusReader reader = new NxOpusReader(); byte[] rawData = archData.Data?.Data; if (archData is OpusArchData data) @@ -44,7 +48,7 @@ public byte[] ToWave(AudioMetadata md, IArchData archData, string fileName = nul { rawData = data.Body.Data.Data; } - else + else if (rawData == null) { rawData = data.Body?.Data?.Data ?? data.Intro?.Data?.Data; } @@ -55,6 +59,12 @@ public byte[] ToWave(AudioMetadata md, IArchData archData, string fileName = nul return null; } + if (IsOgg(rawData)) + { + return rawData; + } + + NxOpusReader reader = new NxOpusReader(); var audioData = reader.Read(rawData); using MemoryStream oms = new MemoryStream(); WaveWriter writer = new WaveWriter(); @@ -68,6 +78,13 @@ public bool ToArchData(AudioMetadata md, IArchData archData, in byte[] wave, str { return false; } + + if (IsOgg(wave)) + { + data.Data.Data = wave; //must link to existed PsbResource + return true; + } + WaveReader reader = new WaveReader(); var rawData = reader.Read(wave); using MemoryStream oms = new MemoryStream(); @@ -157,6 +174,10 @@ public bool TryGetArchData(AudioMetadata md, PsbDictionary channel, out IArchDat if (archDic["data"] is PsbResource res) { opus.Data = res; + if (IsOgg(res.Data)) + { + opus.WaveExtension = ".ogg"; + } } //if (opus.Body != null && opus.Intro == null) diff --git a/FreeMote.Psb/Resources/ArchDatas.cs b/FreeMote.Psb/Resources/ArchDatas.cs index 8e42e08..64e1617 100644 --- a/FreeMote.Psb/Resources/ArchDatas.cs +++ b/FreeMote.Psb/Resources/ArchDatas.cs @@ -553,6 +553,15 @@ public IList DataList { public IPsbValue ToPsbArchData() { + if (Data != null && PsbArchData != null) //android raw ogg + { + if (PsbArchData.ContainsKey("archData")) + { + return PsbArchData["archData"]; + } + return PsbArchData; + } + var archData = new PsbDictionary { {"channelCount", ChannelCount.ToPsbNumber()}, diff --git a/FreeMote.Psb/Resources/AudioMetadata.cs b/FreeMote.Psb/Resources/AudioMetadata.cs index 2e9a244..c11412e 100644 --- a/FreeMote.Psb/Resources/AudioMetadata.cs +++ b/FreeMote.Psb/Resources/AudioMetadata.cs @@ -104,7 +104,7 @@ public void Link(string fullPath, FreeMountContext context) { return; } - if (ChannelList.Count > 1 && AudioFormat != PsbAudioFormat.Unknown && AudioFormat != PsbAudioFormat.ADPCM) + if (ChannelList.Count > 1 && Pan != PsbAudioPan.LeftRight && AudioFormat != PsbAudioFormat.Unknown && AudioFormat != PsbAudioFormat.ADPCM) { Logger.LogWarn("[WARN] Audio with multiple channels is not supported. Send me the sample for research."); }