Index: /OniSplit/Sound/SoundData.cs
===================================================================
--- /OniSplit/Sound/SoundData.cs	(revision 1154)
+++ /OniSplit/Sound/SoundData.cs	(revision 1155)
@@ -2,4 +2,5 @@
 using System.Collections.Generic;
 using System.Text;
+using System.IO;
 
 namespace Oni.Sound
@@ -7,8 +8,25 @@
     internal class SoundData
     {
+        public bool IsPCM;
         public bool IsIMA4;
         public int SampleRate;
         public int ChannelCount;
         public byte[] Data;
+
+        public UInt16 nGameTicks;
+
+        public int SampleCount; // calculated 
+
+        //MS WAV variables
+        public int AverageDataRate;
+        public int BlockAlignment;
+        public int BitsPerSample;
+        public int HeaderSizeADPCM;
+
+        // optional MSADPCM values
+        public UInt16 SamplesPerBlock;
+        public UInt16 nCoefPairs;
+        public Int16[] CoefADPCMa;
+        public Int16[] CoefADPCMb;
 
         public static SoundData Read(InstanceDescriptor sndd, bool do_pc_demo_test)
@@ -24,17 +42,47 @@
             using (var reader = sndd.OpenRead())
             {
+// sample rate
+// duration in frames
+
+// IMA4 or
+// MS ADPCM: block size (default 512 for mono, 1024 for stereo, interruptible)
+
+// sample count (automatic for IMA4 and PC demo)
+
+
+// size in raw / offset in raw
                 if (sndd.IsMacFile)
                 {
-                    sound.ChannelCount = (reader.ReadInt32() >> 1) + 1;
+                    sound.ChannelCount = (reader.ReadInt32() >> 1) + 1; // TODO: interpret the low bit? (uncompressed/compressed?)
                     sound.SampleRate = 22050;
-                    reader.Skip(4);
+                    sound.nGameTicks = (UInt16)reader.ReadInt32();
+
                     sound.IsIMA4 = true;
+                    sound.IsPCM = false;
                 }
                 else
                 {
-                    reader.Skip(6); // ADPCM format identifiers (change to support PCM?)
+                    sound.IsPCM = false;
+                    reader.Skip(4); // flags (1=?, 2=?, 4=?, 8=compressed) TODO: Try uncompressed (even for demo?)
+                    reader.Skip(2); // Int16; format ID (2= ADPCM, 1=PCM?) TODO: Try uncompressed (even for demo?)
                     sound.ChannelCount = reader.ReadInt16();
                     sound.SampleRate = reader.ReadInt32();
-                    reader.Skip(44);
+                    sound.AverageDataRate = reader.ReadInt32(); // in B/s (2 or 4 for PCM; 11155, 22311 or 22179 for Vanilla ADPCM)
+                    sound.BlockAlignment = reader.ReadInt16(); // 2 or 4 bytes per block for PCM; 512 or 1024 for Vanilla ADPCM
+                    sound.BitsPerSample = reader.ReadInt16(); // bits per sample per channel (4 bits per sample for ADPCM, 16 bits for PCM)
+                    sound.HeaderSizeADPCM = reader.ReadInt16(); // size of additional (ADPCM) header (zero for PCM); typically 32 bytes
+
+                    sound.SamplesPerBlock = reader.ReadUInt16(); // UInt16; samples per block (can be inferred from block alignment etc)
+
+                    sound.nCoefPairs = reader.ReadUInt16(); // usually 7
+                    sound.CoefADPCMa = new Int16[sound.nCoefPairs]; // usually     256     512     0       192     240     460     392
+                    sound.CoefADPCMb = new Int16[sound.nCoefPairs]; // usually     0      -256     0       64      0      -208    -232
+                    for (int coefPair = 0; coefPair < sound.nCoefPairs; ++coefPair)
+                    {
+                        sound.CoefADPCMa[coefPair] = reader.ReadInt16();
+                        sound.CoefADPCMb[coefPair] = reader.ReadInt16();
+                    }
+
+                    sound.nGameTicks = reader.ReadUInt16(); // UInt16; number of game ticks (truncated to lower value)
                     sound.IsIMA4 = false;
                 }
@@ -65,7 +113,51 @@
                 else
                     sound.IsIMA4 = false;
-                if (!(sound.IsIMA4))
-                    Console.WriteLine("PC-demo MS ADPCM detected; use -nodemo flag to treat as IMA4.");
+                if (!(sound.IsIMA4)) // fill in default values of WAV (MS ADCPM) header
+                {
+                    sound.IsPCM = false;
+                    Console.WriteLine("PC-demo MS ADPCM detected; use -nodemo flag to treat as Mac IMA4.");
+                    sound.AverageDataRate = (sound.ChannelCount == 1) ? 11155 : 22311;
+                    sound.BlockAlignment = (sound.ChannelCount == 1) ? 512 : 1024;
+                    sound.BitsPerSample = 4;
+                    sound.SamplesPerBlock = 1012;
+                    sound.HeaderSizeADPCM = 32;
+                    sound.nCoefPairs = 7;
+                    sound.CoefADPCMa = new Int16[7]; // usually     256     512     0       192     240     460     392
+                    sound.CoefADPCMb = new Int16[7]; // usually     0      -256     0       64      0      -208    -232
+                    sound.CoefADPCMa[0] = 256;  sound.CoefADPCMb[0] =    0;
+                    sound.CoefADPCMa[1] = 512;  sound.CoefADPCMb[1] = -256;
+                    sound.CoefADPCMa[2] =   0;  sound.CoefADPCMb[2] =    0;
+                    sound.CoefADPCMa[3] = 192;  sound.CoefADPCMb[3] =   64;
+                    sound.CoefADPCMa[4] = 240;  sound.CoefADPCMb[4] =    0;
+                    sound.CoefADPCMa[5] = 460;  sound.CoefADPCMb[5] = -208;
+                    sound.CoefADPCMa[6] = 392;  sound.CoefADPCMb[6] = -232;
+                }
             }
+            // validate data and calculate sample count
+            if(sound.IsIMA4) // get the sample count
+            {
+                int nIMABlocks = sound.Data.Length / 34 / sound.ChannelCount;
+                if(sound.Data.Length - nIMABlocks * 34 * sound.ChannelCount > 0)
+                    throw new InvalidDataException("IMA4 data shouldn't have incomplete blocks.");
+                sound.SampleCount = nIMABlocks * 64;
+            }
+            else
+            {
+                // TODO: validate all the parameters: resolve conflicts if any, or bail out
+                // TODO: handle PCM (the following assumes MS ADPCM)
+                if (sound.IsPCM)
+                {
+                }
+                else
+                {
+                    int wholeBlocks = sound.Data.Length / sound.BlockAlignment;
+                    int leftoverBytes = sound.Data.Length - (wholeBlocks * sound.BlockAlignment);
+                    int leftoverSamples = 8 * (leftoverBytes - 7 * sound.ChannelCount)
+                                          / sound.BitsPerSample / sound.ChannelCount + 2; // assuming 4 bits per sample
+                    sound.SampleCount = wholeBlocks * sound.SamplesPerBlock + leftoverSamples;
+                }
+            }
+//            Console.WriteLine("Sample count:");
+//            Console.WriteLine(sound.SampleCount);
 
             return sound;
