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
+