--- OniSplit/Sound/WavExporter.cs 2020/05/28 21:28:44 1130 +++ OniSplit/Sound/WavExporter.cs 2020/05/30 12:08:12 1131 @@ -7,6 +7,7 @@ namespace Oni.Sound { #region Private data private bool convert_to_PCM; + private bool do_pc_demo_test; private const int fcc_RIFF = 0x46464952; private const int fcc_WAVE = 0x45564157; @@ -85,10 +86,11 @@ namespace Oni.Sound }; #endregion - public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false) + public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false, bool noDemo = false) : base(fileManager, outputDirPath) { convert_to_PCM = convertToPCM; + do_pc_demo_test = !noDemo; } private static void ClampToRange(ref int value, int lower, int upper) @@ -146,7 +148,7 @@ namespace Oni.Sound protected override void ExportInstance(InstanceDescriptor descriptor) { - var sound = SoundData.Read(descriptor); + var sound = SoundData.Read(descriptor, do_pc_demo_test); using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".wav"))) using (var writer = new BinaryWriter(stream)) @@ -161,20 +163,19 @@ namespace Oni.Sound paddingBytes = blockSizeADPCM - leftoverBytes; var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / 4; - Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples; - + Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples; + if (sound.IsIMA4) // IMA4 ADPCM format { blockSizeADPCM = 34 * sound.ChannelCount; samplesPerBlock = 64; sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock; } - if (!convert_to_PCM) { if (sound.IsIMA4) { - throw new NotSupportedException("Transcoding from Mac/demo ADPCM to PC ADPCM not supported! Please use -extract:pcm"); + throw new NotSupportedException("Transcoding from IMA4 ADPCM (Mac) to MS ADPCM (PC) not supported! Please use -extract:pcm"); } var format = (byte[])formatTemplate_ADPCM.Clone(); var fact = (byte[])factTemplate.Clone(); // needed for ADPCM (to specify the actual sample count) @@ -270,6 +271,10 @@ namespace Oni.Sound if (predictorL > 32767) predictorL -= 65536; } stepIndexL = headerLoL & 0x7f; + if (stepIndexL > 88) + Console.WriteLine("Block {0} (L): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexL); + ClampToRange(ref stepIndexL, 0, 88); + for (int b = 0; b < 32; b++) { Byte nibblesL = sound.Data[pos++]; @@ -290,6 +295,9 @@ namespace Oni.Sound if (predictorR > 32767) predictorR -= 65536; } stepIndexR = headerLoR & 0x7f; + if (stepIndexR > 88) + Console.WriteLine("Block {0} (R): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexR); + ClampToRange(ref stepIndexR, 0, 88); for (int b = 0; b < 32; b++) { @@ -359,15 +367,17 @@ namespace Oni.Sound samplesR[iSampleR++] = sample1R; } } - // read pair of nibbles - Byte nibbles = sound.Data[pos++]; - Byte nibbleHi = (Byte)(nibbles >> 4); - Byte nibbleLo = (Byte)(nibbles & 0xF); - samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi); - if (sound.ChannelCount == 2) - samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo); - else - samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo); + else // read pair of nibbles + { + Byte nibbles = sound.Data[pos++]; + Byte nibbleHi = (Byte)(nibbles >> 4); + Byte nibbleLo = (Byte)(nibbles & 0xF); + samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi); + if (sound.ChannelCount == 2) + samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo); + else + samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo); + } } } writer.Write(fcc_data);