diff --git a/AssetStudio/Classes/AnimationClip.cs b/AssetStudio/Classes/AnimationClip.cs index e4ee63d..e1e282b 100644 --- a/AssetStudio/Classes/AnimationClip.cs +++ b/AssetStudio/Classes/AnimationClip.cs @@ -984,14 +984,18 @@ namespace AssetStudio public AnimationEvent(ObjectReader reader) { + var version = reader.version; time = reader.ReadSingle(); functionName = reader.ReadAlignedString(); data = reader.ReadAlignedString(); - objectReferenceParameter = new PPtr(reader); - floatParameter = reader.ReadSingle(); - if (reader.version >= 3) //3 and up + if (version >= (2, 6)) //2.6 and up { - intParameter = reader.ReadInt32(); + objectReferenceParameter = new PPtr(reader); + floatParameter = reader.ReadSingle(); + if (version >= 3) //3 and up + { + intParameter = reader.ReadInt32(); + } } messageOptions = reader.ReadInt32(); } @@ -1067,7 +1071,10 @@ namespace AssetStudio { m_Legacy = true; } - m_Compressed = reader.ReadBoolean(); + if (version >= (2, 6)) //2.6 and up + { + m_Compressed = reader.ReadBoolean(); + } if (version >= (4, 3))//4.3 and up { m_UseHighQualityCurve = reader.ReadBoolean(); @@ -1080,11 +1087,14 @@ namespace AssetStudio m_RotationCurves[i] = new QuaternionCurve(reader); } - int numCRCurves = reader.ReadInt32(); - m_CompressedRotationCurves = new CompressedAnimationCurve[numCRCurves]; - for (int i = 0; i < numCRCurves; i++) + if (version >= (2, 6)) //2.6 and up { - m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader); + int numCRCurves = reader.ReadInt32(); + m_CompressedRotationCurves = new CompressedAnimationCurve[numCRCurves]; + for (int i = 0; i < numCRCurves; i++) + { + m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader); + } } if (version >= (5, 3))//5.3 and up @@ -1129,7 +1139,10 @@ namespace AssetStudio } m_SampleRate = reader.ReadSingle(); - m_WrapMode = reader.ReadInt32(); + if (version >= (2, 6)) //2.6 and up + { + m_WrapMode = reader.ReadInt32(); + } if (version >= (3, 4)) //3.4 and up { m_Bounds = new AABB(reader); diff --git a/AssetStudio/Classes/AudioClip.cs b/AssetStudio/Classes/AudioClip.cs index 53a4c93..df9549c 100644 --- a/AssetStudio/Classes/AudioClip.cs +++ b/AssetStudio/Classes/AudioClip.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace AssetStudio +namespace AssetStudio { public sealed class AudioClip : NamedObject { @@ -36,11 +30,19 @@ namespace AssetStudio if (version < 5) { m_Format = reader.ReadInt32(); - m_Type = (FMODSoundType)reader.ReadInt32(); - m_3D = reader.ReadBoolean(); - m_UseHardware = reader.ReadBoolean(); - reader.AlignStream(); - + if (version >= (2, 6)) //2.6 to 5 + { + m_Type = (FMODSoundType)reader.ReadInt32(); + m_3D = reader.ReadBoolean(); + m_UseHardware = reader.ReadBoolean(); + reader.AlignStream(); + } + else + { + m_Length = reader.ReadSingle(); + m_Frequency = reader.ReadInt32(); + m_Channels = m_Format != 0x05 ? m_Format >> 1 : 0; + } if (version >= (3, 2)) //3.2.0 to 5 { int m_Stream = reader.ReadInt32(); diff --git a/AssetStudio/Classes/PlayerSettings.cs b/AssetStudio/Classes/PlayerSettings.cs index c5168c8..823b93b 100644 --- a/AssetStudio/Classes/PlayerSettings.cs +++ b/AssetStudio/Classes/PlayerSettings.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace AssetStudio +namespace AssetStudio { public sealed class PlayerSettings : Object { @@ -12,37 +7,40 @@ namespace AssetStudio public PlayerSettings(ObjectReader reader) : base(reader) { - if (version >= (5, 4)) //5.4.0 and up + if (version >= (3, 0)) { - var productGUID = reader.ReadBytes(16); - } - - var AndroidProfiler = reader.ReadBoolean(); - //bool AndroidFilterTouchesWhenObscured 2017.2 and up - //bool AndroidEnableSustainedPerformanceMode 2018 and up - reader.AlignStream(); - int defaultScreenOrientation = reader.ReadInt32(); - int targetDevice = reader.ReadInt32(); - if (version < (5, 3)) //5.3 down - { - if (version < 5) //5.0 down + if (version >= (5, 4)) //5.4.0 and up { - int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics - if (version >= (4, 6)) //4.6 and up - { - var targetIOSGraphics = reader.ReadInt32(); - } + var productGUID = reader.ReadBytes(16); } - int targetResolution = reader.ReadInt32(); - } - else - { - var useOnDemandResources = reader.ReadBoolean(); + + var AndroidProfiler = reader.ReadBoolean(); + //bool AndroidFilterTouchesWhenObscured 2017.2 and up + //bool AndroidEnableSustainedPerformanceMode 2018 and up reader.AlignStream(); - } - if (version >= (3, 5)) //3.5 and up - { - var accelerometerFrequency = reader.ReadInt32(); + int defaultScreenOrientation = reader.ReadInt32(); + int targetDevice = reader.ReadInt32(); + if (version < (5, 3)) //5.3 down + { + if (version < 5) //5.0 down + { + int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics + if (version >= (4, 6)) //4.6 and up + { + var targetIOSGraphics = reader.ReadInt32(); + } + } + int targetResolution = reader.ReadInt32(); + } + else + { + var useOnDemandResources = reader.ReadBoolean(); + reader.AlignStream(); + } + if (version >= (3, 5)) //3.5 and up + { + var accelerometerFrequency = reader.ReadInt32(); + } } companyName = reader.ReadAlignedString(); productName = reader.ReadAlignedString(); diff --git a/AssetStudio/ResourceReader.cs b/AssetStudio/ResourceReader.cs index 72612d1..e44f753 100644 --- a/AssetStudio/ResourceReader.cs +++ b/AssetStudio/ResourceReader.cs @@ -84,13 +84,13 @@ namespace AssetStudio } } - public void GetData(byte[] buff) + public void GetData(byte[] buff, int startIndex = 0) { var binaryReader = GetReader(); lock (binaryReader) { binaryReader.BaseStream.Position = Offset; - binaryReader.Read(buff, 0, (int) size); + binaryReader.Read(buff, startIndex, (int) size); } } diff --git a/AssetStudioCLI/ParallelExporter.cs b/AssetStudioCLI/ParallelExporter.cs index 91b87b5..0ee6fc8 100644 --- a/AssetStudioCLI/ParallelExporter.cs +++ b/AssetStudioCLI/ParallelExporter.cs @@ -109,7 +109,7 @@ namespace AssetStudioCLI return false; } var converter = new AudioClipConverter(m_AudioClip); - if (CLIOptions.o_audioFormat.Value != AudioFormat.None && converter.IsSupport) + if (CLIOptions.o_audioFormat.Value != AudioFormat.None && (converter.IsSupport || converter.IsLegacy)) { if (!TryExportFile(exportPath, item, ".wav", out exportFullPath)) return false; @@ -118,14 +118,28 @@ namespace AssetStudioCLI { var sb = new StringBuilder(); sb.AppendLine($"Converting {item.TypeString} \"{m_AudioClip.m_Name}\" to wav.."); - sb.AppendLine(m_AudioClip.version < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); - sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); - sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); - sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + if (m_AudioClip.version >= (2, 6)) + { + sb.AppendLine(m_AudioClip.version < 5 + ? $"AudioClip type: {m_AudioClip.m_Type}" + : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + } + else + { + sb.AppendLine($"Is raw AudioClip: {m_AudioClip.m_Format != 0x05}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + } debugLog += sb.ToString(); } - var buffer = converter.ConvertToWav(m_AudioData, out var debugLogConverter); + var debugLogConverter = ""; + var buffer = converter.IsLegacy + ? converter.RawAudioClipToWav(out debugLogConverter) + : converter.ConvertToWav(m_AudioData, out debugLogConverter); debugLog += debugLogConverter; if (buffer == null) { @@ -143,13 +157,26 @@ namespace AssetStudioCLI { var sb = new StringBuilder(); sb.AppendLine($"Exporting non-fmod {item.TypeString} \"{m_AudioClip.m_Name}\".."); - sb.AppendLine(m_AudioClip.version < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); - sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); - sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); - sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + if (m_AudioClip.version >= (2, 6)) + { + sb.AppendLine(m_AudioClip.version < 5 + ? $"AudioClip type: {m_AudioClip.m_Type}" + : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + } + else + { + sb.AppendLine($"Is raw AudioClip: {m_AudioClip.m_Format != 0x05}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + } debugLog += sb.ToString(); } - File.WriteAllBytes(exportFullPath, m_AudioData); + using (var file = File.OpenWrite(exportFullPath)) + { + file.Write(m_AudioData, 0, m_AudioClip.m_AudioData.Size); + } } debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\""; return true; diff --git a/AssetStudioGUI/ParallelExport.cs b/AssetStudioGUI/ParallelExport.cs index ab622fe..7748cd2 100644 --- a/AssetStudioGUI/ParallelExport.cs +++ b/AssetStudioGUI/ParallelExport.cs @@ -108,7 +108,7 @@ namespace AssetStudioGUI return false; } var converter = new AudioClipConverter(m_AudioClip); - if (Properties.Settings.Default.convertAudio && converter.IsSupport) + if (Properties.Settings.Default.convertAudio && (converter.IsSupport || converter.IsLegacy)) { if (!TryExportFile(exportPath, item, ".wav", out exportFullPath)) return false; @@ -117,16 +117,29 @@ namespace AssetStudioGUI { var sb = new StringBuilder(); sb.AppendLine($"Converting {item.TypeString} \"{m_AudioClip.m_Name}\" to wav.."); - sb.AppendLine(m_AudioClip.version < 5 - ? $"AudioClip type: {m_AudioClip.m_Type}" - : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); - sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); - sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); - sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + if (m_AudioClip.version >= (2, 6)) + { + sb.AppendLine(m_AudioClip.version < 5 + ? $"AudioClip type: {m_AudioClip.m_Type}" + : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + } + else + { + sb.AppendLine($"Is raw AudioClip: {m_AudioClip.m_Format != 0x05}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + } + debugLog += sb.ToString(); } - var buffer = converter.ConvertToWav(m_AudioData, out var debugLogConverter); + var debugLogConverter = ""; + var buffer = converter.IsLegacy + ? converter.RawAudioClipToWav(out debugLogConverter) + : converter.ConvertToWav(m_AudioData, out debugLogConverter); debugLog += debugLogConverter; if (buffer == null) { @@ -144,15 +157,27 @@ namespace AssetStudioGUI { var sb = new StringBuilder(); sb.AppendLine($"Exporting non-fmod {item.TypeString} \"{m_AudioClip.m_Name}\".."); - sb.AppendLine(m_AudioClip.version < 5 - ? $"AudioClip type: {m_AudioClip.m_Type}" - : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); - sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); - sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); - sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + if (m_AudioClip.version >= (2, 6)) + { + sb.AppendLine(m_AudioClip.version < 5 + ? $"AudioClip type: {m_AudioClip.m_Type}" + : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}"); + sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}"); + } + else + { + sb.AppendLine($"Is raw AudioClip: {m_AudioClip.m_Format != 0x05}"); + sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}"); + } + debugLog += sb.ToString(); } - File.WriteAllBytes(exportFullPath, m_AudioData); + using (var file = File.OpenWrite(exportFullPath)) + { + file.Write(m_AudioData, 0, m_AudioClip.m_AudioData.Size); + } } debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\""; return true; diff --git a/AssetStudioUtility/AudioClipConverter.cs b/AssetStudioUtility/AudioClipConverter.cs index 2a78e56..97c97aa 100644 --- a/AssetStudioUtility/AudioClipConverter.cs +++ b/AssetStudioUtility/AudioClipConverter.cs @@ -8,6 +8,7 @@ namespace AssetStudio public class AudioClipConverter { public bool IsSupport => m_AudioClip.IsConvertSupport(); + public bool IsLegacy => m_AudioClip.IsLegacyConvertSupport(); private AudioClip m_AudioClip; private static FMOD.System system; @@ -84,8 +85,32 @@ namespace AssetStudio return null; var buffer = new byte[len1 + 44]; //添加wav头 + WriteWavHeader(buffer, len1, sampleRate, channels, bits); + Marshal.Copy(ptr1, buffer, 44, (int)len1); + result = sound.unlock(ptr1, ptr2, len1, len2); + if (result != RESULT.OK) + return null; + return buffer; + } + + public byte[] RawAudioClipToWav(out string debugLog) + { + var audioSize = m_AudioClip.m_Size; + var channels = m_AudioClip.m_Channels; + var sampleRate = m_AudioClip.m_Frequency; + var bits = 16; + + debugLog = "[Legacy wav converter] Generating wav header..\n"; + var buffer = new byte[audioSize + 44]; + m_AudioClip.m_AudioData.GetData(buffer, 44); + WriteWavHeader(buffer, audioSize, sampleRate, channels, bits); + return buffer; + } + + private static void WriteWavHeader(byte[] buffer, long size, int sampleRate, int channels, int bits) + { Encoding.ASCII.GetBytes("RIFF").CopyTo(buffer, 0); - BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4); + BitConverter.GetBytes(size + 36).CopyTo(buffer, 4); Encoding.ASCII.GetBytes("WAVEfmt ").CopyTo(buffer, 8); BitConverter.GetBytes(16).CopyTo(buffer, 16); BitConverter.GetBytes((short)1).CopyTo(buffer, 20); @@ -95,12 +120,7 @@ namespace AssetStudio BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32); BitConverter.GetBytes((short)bits).CopyTo(buffer, 34); Encoding.ASCII.GetBytes("data").CopyTo(buffer, 36); - BitConverter.GetBytes(len1).CopyTo(buffer, 40); - Marshal.Copy(ptr1, buffer, 44, (int)len1); - result = sound.unlock(ptr1, ptr2, len1, len2); - if (result != RESULT.OK) - return null; - return buffer; + BitConverter.GetBytes(size).CopyTo(buffer, 40); } public string GetExtensionName() @@ -201,5 +221,10 @@ namespace AssetStudio } } } + + public static bool IsLegacyConvertSupport(this AudioClip m_AudioClip) + { + return m_AudioClip.version < (2, 6) && m_AudioClip.m_Format != 0x05; + } } }