Changeset 1131


Ignore:
Timestamp:
May 30, 2020, 2:08:12 PM (5 years ago)
Author:
geyser
Message:

Yay, another SNDD fix that no one cares about: PC demo SNDDs! (short .dat headers, but the .raw data is MS ADPCM; use -nodemo to treat as Mac/IMA4 anyway).

Location:
OniSplit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • OniSplit/Program.cs

    r1130 r1131  
    367367
    368368            SoundExporter exporter;
    369 
     369            var noDemo = args.Any(a => a == "-nodemo");
     370            Console.WriteLine(noDemo);
    370371            switch (fileType)
    371372            {
    372373                case "aif":
    373                     exporter = new AifExporter(fileManager, outputDirPath);
     374                    exporter = new AifExporter(fileManager, outputDirPath, noDemo);
    374375                    break;
    375376                case "wav":
    376                     exporter = new WavExporter(fileManager, outputDirPath);
     377                    exporter = new WavExporter(fileManager, outputDirPath, false, noDemo);
    377378                    break;
    378379                case "pcm":
    379                     exporter = new WavExporter(fileManager, outputDirPath, true);
     380                    exporter = new WavExporter(fileManager, outputDirPath, true, noDemo);
    380381                    break;
    381382                default:
  • OniSplit/Sound/AifExporter.cs

    r1130 r1131  
    77    {
    88        #region Private data
     9        private bool do_pc_demo_test;
     10
    911        private const int fcc_FORM = 0x464f524d;
    1012        private const int fcc_AIFC = 0x41494643;
     
    2022        #endregion
    2123
    22         public AifExporter(InstanceFileManager fileManager, string outputDirPath)
     24        public AifExporter(InstanceFileManager fileManager, string outputDirPath, bool noDemo = false)
    2325            : base(fileManager, outputDirPath)
    2426        {
     27            do_pc_demo_test = !noDemo;
    2528        }
    2629
    2730        protected override void ExportInstance(InstanceDescriptor descriptor)
    2831        {
    29             var sound = SoundData.Read(descriptor);
     32            var sound = SoundData.Read(descriptor, do_pc_demo_test);
    3033
    3134            using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".aif")))
     
    3437                if (!(sound.IsIMA4))
    3538                {
    36                     throw new NotSupportedException("Transcoding from PC ADPCM to Mac/demo ADPCM not supported!");
     39                    throw new NotSupportedException("Transcoding from MS ADPCM (PC) to IMA4 ADPCM (Mac) not supported!");
    3740                }
    3841                writer.Write(Utils.ByteSwap(fcc_FORM));
  • OniSplit/Sound/SoundData.cs

    r1130 r1131  
    1212        public byte[] Data;
    1313
    14         public static SoundData Read(InstanceDescriptor sndd)
     14        public static SoundData Read(InstanceDescriptor sndd, bool do_pc_demo_test)
    1515        {
    1616            if (sndd.Template.Tag != TemplateTag.SNDD)
     
    4747                sound.Data = rawReader.ReadBytes(dataSize);
    4848
     49            if (sound.IsIMA4 && do_pc_demo_test) // check if the raw data actually looks like IMA4
     50            {
     51                int nIMABlocks = sound.Data.Length / 34;
     52                int remainder = sound.Data.Length - nIMABlocks * 34;
     53                if (remainder == 0 && (nIMABlocks % sound.ChannelCount) == 0)
     54                {
     55                    bool stepIndexAbove88 = false;
     56                    for (int ii = 0; ii < nIMABlocks; ii++)
     57                    {
     58                        Byte cc = sound.Data[ii * 34 + 1];
     59                        if ((cc & 0x7F) > 88)
     60                            stepIndexAbove88 = true;
     61                    }
     62                    if (stepIndexAbove88)
     63                        sound.IsIMA4 = false;
     64                }
     65                else
     66                    sound.IsIMA4 = false;
     67                if (!(sound.IsIMA4))
     68                    Console.WriteLine("PC-demo MS ADPCM detected; use -nodemo flag to treat as IMA4.");
     69            }
     70
    4971            return sound;
    5072        }
  • OniSplit/Sound/WavExporter.cs

    r1130 r1131  
    88        #region Private data
    99        private bool convert_to_PCM;
     10        private bool do_pc_demo_test;
    1011
    1112        private const int fcc_RIFF = 0x46464952;
     
    8687        #endregion
    8788
    88         public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false)
     89        public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false, bool noDemo = false)
    8990            : base(fileManager, outputDirPath)
    9091        {
    9192            convert_to_PCM = convertToPCM;
     93            do_pc_demo_test = !noDemo;
    9294        }
    9395
     
    147149        protected override void ExportInstance(InstanceDescriptor descriptor)
    148150        {
    149             var sound = SoundData.Read(descriptor);
     151            var sound = SoundData.Read(descriptor, do_pc_demo_test);
    150152
    151153            using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".wav")))
     
    162164                var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / 4;
    163165
    164                 Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples; 
    165                
     166                Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
     167
    166168                if (sound.IsIMA4) // IMA4 ADPCM format
    167169                {
     
    170172                    sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock;
    171173                }
    172 
    173174                if (!convert_to_PCM)
    174175                {
    175176                    if (sound.IsIMA4)
    176177                    {
    177                         throw new NotSupportedException("Transcoding from Mac/demo ADPCM to PC ADPCM not supported! Please use -extract:pcm");
     178                        throw new NotSupportedException("Transcoding from IMA4 ADPCM (Mac) to MS ADPCM (PC) not supported! Please use -extract:pcm");
    178179                    }
    179180                    var format = (byte[])formatTemplate_ADPCM.Clone();
     
    271272                            }
    272273                            stepIndexL = headerLoL & 0x7f;
     274                            if (stepIndexL > 88)
     275                                Console.WriteLine("Block {0} (L): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexL);
     276                            ClampToRange(ref stepIndexL, 0, 88);
     277
    273278                            for (int b = 0; b < 32; b++)
    274279                            {
     
    291296                                }
    292297                                stepIndexR = headerLoR & 0x7f;
     298                                if (stepIndexR > 88)
     299                                    Console.WriteLine("Block {0} (R): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexR);
     300                                ClampToRange(ref stepIndexR, 0, 88);
    293301
    294302                                for (int b = 0; b < 32; b++)
     
    360368                                }
    361369                            }
    362                             // read pair of nibbles
    363                             Byte nibbles = sound.Data[pos++];
    364                             Byte nibbleHi = (Byte)(nibbles >> 4);
    365                             Byte nibbleLo = (Byte)(nibbles & 0xF);
    366                             samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
    367                             if (sound.ChannelCount == 2)
    368                                 samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
    369                             else
    370                                 samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
     370                            else // read pair of nibbles
     371                            {
     372                                Byte nibbles = sound.Data[pos++];
     373                                Byte nibbleHi = (Byte)(nibbles >> 4);
     374                                Byte nibbleLo = (Byte)(nibbles & 0xF);
     375                                samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
     376                                if (sound.ChannelCount == 2)
     377                                    samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
     378                                else
     379                                    samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
     380                            }
    371381                        }
    372382                    }
Note: See TracChangeset for help on using the changeset viewer.