--- OniSplit/Sound/WavFile.cs 2021/05/03 15:22:15 1154 +++ OniSplit/Sound/WavFile.cs 2021/05/08 01:44:24 1156 @@ -39,7 +39,7 @@ namespace Oni.Sound var header = new WavFile() { - sampleCount = 0 + sampleCount = -1 }; for (int chunkType, chunkSize, chunkStart; reader.Position < size; reader.Position = chunkStart + chunkSize) @@ -55,8 +55,7 @@ namespace Oni.Sound if (chunkType == fcc_data) header.ReadDataChunk(reader, chunkSize); } - - header.ValidateSampleCount(); + header.TruncatePerFact(); return header; } } @@ -85,17 +84,28 @@ namespace Oni.Sound { soundData = reader.ReadBytes(chunkSize); } - private void ValidateSampleCount() // TODO: ACTUAL VALIDATION/CORRECTION + private void TruncatePerFact() // TODO: MORE THOROUGH VALIDATION? { - int sampleCountFromData = 0; - int wholeBlocks = soundData.Length / blockAlign; - if(sampleCount == 0) // not explicitly set (no fact chunk present) + if(sampleCount == -1) // not explicitly set (no fact chunk present) { Console.WriteLine("The imported WAV file has no FACT chunk."); } - else // TODO: calculate sampleCountFromData, compare with sampleCount + else if (format == WavFormat.Adpcm) // calculate truncated data size { - + var blockSizeADPCM = blockAlign; + var samplesPerBlock = 2 + (blockSizeADPCM - channelCount * 7) * 8 / channelCount / bitsPerSample; + int wholeBlocks = sampleCount / samplesPerBlock; + if (wholeBlocks * blockAlign > soundData.Length) + Console.Error.WriteLine("Sample count exceeds the range of sound data."); + int leftoverSamples = sampleCount - wholeBlocks * samplesPerBlock; + if (leftoverSamples < 2) // a block always starts with at least two samples? + Console.Error.WriteLine("Improper trailing bytes/samples!"); + if (bitsPerSample != 4) // are MS ADPCM nibbles always 4-bit-sized? + Console.Error.WriteLine("Nibble size is expected to be 4 bits!"); + int leftoverNibbles = (leftoverSamples - 2) * channelCount; + int leftoverBytes = 7 * channelCount + + (int)Math.Ceiling((leftoverNibbles * bitsPerSample) * 0.125); + Array.Resize(ref soundData, wholeBlocks * blockAlign + leftoverBytes); } } @@ -105,6 +115,7 @@ namespace Oni.Sound public int AverageBytesPerSecond => averageBytesPerSecond; public int BlockAlign => blockAlign; public int BitsPerSample => bitsPerSample; + public int SampleCount => sampleCount; public byte[] ExtraData => extraData; public byte[] SoundData => soundData; }