--- OniSplit/Sound/SoundData.cs 2020/01/22 14:08:57 1114 +++ OniSplit/Sound/SoundData.cs 2020/05/30 12:08:12 1131 @@ -6,11 +6,12 @@ namespace Oni.Sound { internal class SoundData { + public bool IsIMA4; public int SampleRate; public int ChannelCount; public byte[] Data; - public static SoundData Read(InstanceDescriptor sndd) + public static SoundData Read(InstanceDescriptor sndd, bool do_pc_demo_test) { if (sndd.Template.Tag != TemplateTag.SNDD) throw new ArgumentException("descriptor"); @@ -27,13 +28,15 @@ namespace Oni.Sound sound.ChannelCount = (reader.ReadInt32() >> 1) + 1; sound.SampleRate = 22050; reader.Skip(4); + sound.IsIMA4 = true; } else { - reader.Skip(6); + reader.Skip(6); // ADPCM format identifiers (change to support PCM?) sound.ChannelCount = reader.ReadInt16(); sound.SampleRate = reader.ReadInt32(); reader.Skip(44); + sound.IsIMA4 = false; } dataSize = reader.ReadInt32(); @@ -43,6 +46,28 @@ namespace Oni.Sound using (var rawReader = sndd.GetRawReader(dataOffset)) sound.Data = rawReader.ReadBytes(dataSize); + if (sound.IsIMA4 && do_pc_demo_test) // check if the raw data actually looks like IMA4 + { + int nIMABlocks = sound.Data.Length / 34; + int remainder = sound.Data.Length - nIMABlocks * 34; + if (remainder == 0 && (nIMABlocks % sound.ChannelCount) == 0) + { + bool stepIndexAbove88 = false; + for (int ii = 0; ii < nIMABlocks; ii++) + { + Byte cc = sound.Data[ii * 34 + 1]; + if ((cc & 0x7F) > 88) + stepIndexAbove88 = true; + } + if (stepIndexAbove88) + sound.IsIMA4 = false; + } + else + sound.IsIMA4 = false; + if (!(sound.IsIMA4)) + Console.WriteLine("PC-demo MS ADPCM detected; use -nodemo flag to treat as IMA4."); + } + return sound; } }