diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs index 6f0a1574..94120fe1 100644 --- a/ArcFormats/Properties/Settings.Designer.cs +++ b/ArcFormats/Properties/Settings.Designer.cs @@ -753,5 +753,17 @@ namespace GameRes.Formats.Properties { this["PFSEncodingCP"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("44100")] + public uint ODNAudioSampleRate { + get { + return ((uint)(this["ODNAudioSampleRate"])); + } + set { + this["ODNAudioSampleRate"] = value; + } + } } } diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings index 1027fb43..8bb080fb 100644 --- a/ArcFormats/Properties/Settings.settings +++ b/ArcFormats/Properties/Settings.settings @@ -185,5 +185,8 @@ 65001 + + 44100 + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs index 65f20dd1..d5a6b229 100644 --- a/ArcFormats/Strings/arcStrings.Designer.cs +++ b/ArcFormats/Strings/arcStrings.Designer.cs @@ -606,6 +606,15 @@ namespace GameRes.Formats.Strings { } } + /// + /// Looks up a localized string similar to Default audio sampling rate. + /// + public static string ODNAudioSampleRate { + get { + return ResourceManager.GetString("ODNAudioSampleRate", resourceCulture); + } + } + /// /// Looks up a localized string similar to Fix Ogg files checksums. /// diff --git a/ArcFormats/Strings/arcStrings.ja-JP.resx b/ArcFormats/Strings/arcStrings.ja-JP.resx index f350c4d7..a409eeb8 100644 --- a/ArcFormats/Strings/arcStrings.ja-JP.resx +++ b/ArcFormats/Strings/arcStrings.ja-JP.resx @@ -501,4 +501,7 @@ Choose encryption scheme or enter a passphrase. Default file names encoding + + Default audio sampling rate + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.ko-KR.resx b/ArcFormats/Strings/arcStrings.ko-KR.resx index f2b54c4c..e6eb57d2 100644 --- a/ArcFormats/Strings/arcStrings.ko-KR.resx +++ b/ArcFormats/Strings/arcStrings.ko-KR.resx @@ -403,4 +403,8 @@ Default file names encoding translation pending + + Default audio sampling rate + translation pending + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx index 3543e6f7..06d01c01 100644 --- a/ArcFormats/Strings/arcStrings.resx +++ b/ArcFormats/Strings/arcStrings.resx @@ -401,4 +401,7 @@ Choose encryption scheme or enter a passphrase. Default file names encoding + + Default audio sampling rate + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.ru-RU.resx b/ArcFormats/Strings/arcStrings.ru-RU.resx index ed00719e..278cb2dc 100644 --- a/ArcFormats/Strings/arcStrings.ru-RU.resx +++ b/ArcFormats/Strings/arcStrings.ru-RU.resx @@ -276,6 +276,9 @@ Ключи шифрования (требуются даже если содержимое не шифруется) + + Частота дискретизации аудио + Исправлять контрольные суммы в Ogg аудио файлах diff --git a/ArcFormats/Strings/arcStrings.zh-Hans.resx b/ArcFormats/Strings/arcStrings.zh-Hans.resx index 0d256a66..da7fe1f5 100644 --- a/ArcFormats/Strings/arcStrings.zh-Hans.resx +++ b/ArcFormats/Strings/arcStrings.zh-Hans.resx @@ -404,4 +404,8 @@ Default file names encoding translation pending + + Default audio sampling rate + translation pending + \ No newline at end of file diff --git a/ArcFormats/Valkyria/ArcODN.cs b/ArcFormats/Valkyria/ArcODN.cs index 0c44068a..5537f181 100644 --- a/ArcFormats/Valkyria/ArcODN.cs +++ b/ArcFormats/Valkyria/ArcODN.cs @@ -32,6 +32,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Windows.Media; +using GameRes.Formats.Strings; using GameRes.Utility; namespace GameRes.Formats.Valkyria @@ -55,7 +56,7 @@ namespace GameRes.Formats.Valkyria } [Export(typeof(ArchiveFormat))] - public class OdnOpener : ArchiveFormat + sealed public class OdnOpener : ArchiveFormat { public override string Tag { get { return "ODN"; } } public override string Description { get { return "Valkyria resource archive"; } } @@ -63,6 +64,17 @@ namespace GameRes.Formats.Valkyria public override bool IsHierarchic { get { return false; } } public override bool CanWrite { get { return false; } } + public OdnOpener () + { + Settings = new[] { AudioSampleRate }; + } + + FixedSetSetting AudioSampleRate = new FixedSetSetting (Properties.Settings.Default) { + Name = "ODNAudioSampleRate", + Text = arcStrings.ODNAudioSampleRate, + ValuesSet = new[] { 22050u, 44100u }, + }; + public override ArcFile TryOpen (ArcView file) { if (!file.Name.HasExtension (".odn")) @@ -92,6 +104,7 @@ namespace GameRes.Formats.Valkyria internal static readonly Regex Image24NameRe = new Regex ("^(?:back|phii)"); internal static readonly Regex Image32NameRe = new Regex ("^(?:data|codn|cccc)"); internal static readonly Regex ScriptNameRe = new Regex ("^(?:scrp|menu|sysm)"); + internal static readonly Regex AudioNameRe = new Regex ("^hime"); public override Stream OpenEntry (ArcFile arc, Entry entry) { @@ -102,6 +115,24 @@ namespace GameRes.Formats.Valkyria Decrypt (data, data.Length, key); return new BinMemoryStream (data); } + if (AudioNameRe.IsMatch (entry.Name)) + { + using (var wav = new MemoryStream (0x2C)) + { + var format = new WaveFormat { + FormatTag = 1, + Channels = 1, + SamplesPerSecond = AudioSampleRate.Get(), + BlockAlign = 2, + BitsPerSample = 16, + }; + format.SetBPS(); + WaveAudio.WriteRiffHeader (wav, format, entry.Size); + var header = wav.ToArray(); + var data = arc.File.CreateStream (entry.Offset, entry.Size); + return new PrefixStream (header, data); + } + } var input = arc.File.CreateStream (entry.Offset, entry.Size); if (0x5E6A6A42 == input.Signature) { @@ -247,6 +278,11 @@ namespace GameRes.Formats.Valkyria index_offset += 0x10; if (m_entry_buf.AsciiEqual (0, "END_ffffffffffff")) break; + else if (m_entry_buf.AsciiEqual (0, "HIME_END")) + { + index_offset += 8; + break; + } var name = m_enc.GetString (m_entry_buf, 0, 8); var offset = m_enc.GetString (m_entry_buf, 8, 8); var entry = new Entry { Name = name, Offset = Convert.ToUInt32 (offset, 16) }; @@ -254,6 +290,8 @@ namespace GameRes.Formats.Valkyria } foreach (var entry in m_dir) entry.Offset += index_offset; + if (m_dir.Any() && m_dir[m_dir.Count-1].Offset == m_file.MaxOffset) + m_dir.RemoveAt (m_dir.Count-1); } void ReadV2 (uint record_size) @@ -321,6 +359,10 @@ namespace GameRes.Formats.Valkyria { entry.Type = "script"; } + else if (OdnOpener.AudioNameRe.IsMatch (entry.Name)) + { + entry.Type = "audio"; + } else if (entry.Size > 4) { var signature = m_file.View.ReadUInt32 (entry.Offset); diff --git a/ArcFormats/app.config b/ArcFormats/app.config index 9904da27..0f145199 100644 --- a/ArcFormats/app.config +++ b/ArcFormats/app.config @@ -187,6 +187,9 @@ 65001 + + 44100 +