ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/OniSplit/Sound/WavFile.cs
(Generate patch)

Comparing OniSplit/Sound/WavFile.cs (file contents):
Revision 1154 by geyser, Mon May 3 15:22:15 2021 UTC vs.
Revision 1156 by geyser, Sat May 8 01:44:24 2021 UTC

# Line 39 | Line 39 | namespace Oni.Sound
39  
40                  var header = new WavFile()
41                  {
42 <                    sampleCount = 0
42 >                    sampleCount = -1
43                  };
44  
45                  for (int chunkType, chunkSize, chunkStart; reader.Position < size; reader.Position = chunkStart + chunkSize)
# Line 55 | Line 55 | namespace Oni.Sound
55                      if (chunkType == fcc_data)
56                          header.ReadDataChunk(reader, chunkSize);
57                  }
58 <
59 <                header.ValidateSampleCount();
58 >                header.TruncatePerFact();
59                  return header;
60              }
61          }
# Line 85 | Line 84 | namespace Oni.Sound
84          {
85              soundData = reader.ReadBytes(chunkSize);
86          }
87 <        private void ValidateSampleCount() // TODO: ACTUAL VALIDATION/CORRECTION
87 >        private void TruncatePerFact() // TODO: MORE THOROUGH VALIDATION?
88          {
89 <            int sampleCountFromData = 0;
91 <            int wholeBlocks = soundData.Length / blockAlign;
92 <            if(sampleCount == 0) // not explicitly set (no fact chunk present)
89 >            if(sampleCount == -1) // not explicitly set (no fact chunk present)
90              {
91                  Console.WriteLine("The imported WAV file has no FACT chunk.");
92              }
93 <            else // TODO: calculate sampleCountFromData, compare with sampleCount
93 >            else if (format == WavFormat.Adpcm) // calculate truncated data size
94              {
95 <
95 >                var blockSizeADPCM = blockAlign;
96 >                var samplesPerBlock = 2 + (blockSizeADPCM - channelCount * 7) * 8 / channelCount / bitsPerSample;
97 >                int wholeBlocks = sampleCount / samplesPerBlock;
98 >                if (wholeBlocks * blockAlign > soundData.Length)
99 >                    Console.Error.WriteLine("Sample count exceeds the range of sound data.");
100 >                int leftoverSamples = sampleCount - wholeBlocks * samplesPerBlock;
101 >                if (leftoverSamples < 2) // a block always starts with at least two samples?
102 >                    Console.Error.WriteLine("Improper trailing bytes/samples!");
103 >                if (bitsPerSample != 4) // are MS ADPCM nibbles always 4-bit-sized?
104 >                    Console.Error.WriteLine("Nibble size is expected to be 4 bits!");
105 >                int leftoverNibbles = (leftoverSamples - 2) * channelCount;
106 >                int leftoverBytes = 7 * channelCount
107 >                    + (int)Math.Ceiling((leftoverNibbles * bitsPerSample) * 0.125);
108 >                Array.Resize(ref soundData, wholeBlocks * blockAlign + leftoverBytes);
109              }
110          }
111  
# Line 105 | Line 115 | namespace Oni.Sound
115          public int AverageBytesPerSecond => averageBytesPerSecond;
116          public int BlockAlign => blockAlign;
117          public int BitsPerSample => bitsPerSample;
118 +        public int SampleCount => sampleCount;
119          public byte[] ExtraData => extraData;
120          public byte[] SoundData => soundData;
121      }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)