Changeset 1156


Ignore:
Timestamp:
May 8, 2021, 3:44:24 AM (13 months ago)
Author:
geyser
Message:

Fixed importing of "fact" chunk, as well as an unhandled fatal when attempting to transcode IMA4 to MS ADPCM. Also added missing padding to SNDD template and fixed the duration calculation for WAV-to-SNDD.

Location:
OniSplit/Sound
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • OniSplit/Sound/AifExporter.cs

    r1131 r1156  
    3131        {
    3232            var sound = SoundData.Read(descriptor, do_pc_demo_test);
     33            if (!(sound.IsIMA4))
     34                throw new NotSupportedException("Transcoding from MS ADPCM (PC) to IMA4 ADPCM (Mac) not supported!");
    3335
    3436            using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".aif")))
    3537            using (var writer = new BinaryWriter(stream))
    3638            {
    37                 if (!(sound.IsIMA4))
    38                 {
    39                     throw new NotSupportedException("Transcoding from MS ADPCM (PC) to IMA4 ADPCM (Mac) not supported!");
    40                 }
    4139                writer.Write(Utils.ByteSwap(fcc_FORM));
    4240                writer.Write(Utils.ByteSwap(50 + sound.Data.Length));
  • OniSplit/Sound/AifImporter.cs

    r1114 r1156  
    5353                writer.Write(aif.SoundData.Length);
    5454                writer.Write(WriteRawPart(aif.SoundData));
     55                writer.Skip(8);
    5556            }
    5657                }
  • OniSplit/Sound/SoundData.cs

    r1155 r1156  
    158158                }
    159159            }
    160 //            Console.WriteLine("Sample count:");
    161 //            Console.WriteLine(sound.SampleCount);
    162 
    163160            return sound;
    164161        }
  • OniSplit/Sound/WavExporter.cs

    r1154 r1156  
    154154            using (var writer = new BinaryWriter(stream))
    155155            {
    156                 var blockSizeADPCM = sound.BlockAlignment;
    157                
    158                 int wholeBlocks = sound.Data.Length / blockSizeADPCM;
    159                 int leftoverBytes = sound.Data.Length - (wholeBlocks * blockSizeADPCM);
    160                 int leftoverSamples = 0;
    161                 if(leftoverBytes > 14)
    162                     leftoverSamples = 2 + (leftoverBytes - 7 * sound.ChannelCount)
    163                                     * 8 / sound.BitsPerSample / sound.ChannelCount;
    164                 int paddingBytes = 0;
    165                 if (leftoverBytes > 0) // incomplete trailing block
    166                     paddingBytes = blockSizeADPCM - leftoverBytes;
    167                 var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / sound.BitsPerSample;
    168 
    169                 Int32 sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
    170 
     156                int blockSizeADPCM, samplesPerBlock, sampleCount, paddingBytes = 0;
    171157                if (sound.IsIMA4) // IMA4 ADPCM format
    172158                {
     
    174160                    samplesPerBlock = 64;
    175161                    sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock;
     162                }
     163                else
     164                {
     165                    blockSizeADPCM = sound.BlockAlignment;
     166                    int wholeBlocks = sound.Data.Length / blockSizeADPCM;
     167                    int leftoverBytes = sound.Data.Length - (wholeBlocks * blockSizeADPCM);
     168                    int leftoverSamples = 0;
     169                    if (leftoverBytes > 7 * sound.ChannelCount)
     170                        leftoverSamples = 2 + (leftoverBytes - 7 * sound.ChannelCount)
     171                                        * 8 / sound.BitsPerSample / sound.ChannelCount;
     172                    else
     173                        Console.Error.WriteLine("Improper trailing bytes/samples!");
     174                    if (leftoverBytes > 0) // incomplete trailing block
     175                        paddingBytes = blockSizeADPCM - leftoverBytes;
     176                    samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / sound.BitsPerSample;
     177                    sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
    176178                }
    177179                if (!convert_to_PCM)
  • OniSplit/Sound/WavFile.cs

    r1154 r1156  
    4040                var header = new WavFile()
    4141                {
    42                     sampleCount = 0
     42                    sampleCount = -1
    4343                };
    4444
     
    5656                        header.ReadDataChunk(reader, chunkSize);
    5757                }
    58 
    59                 header.ValidateSampleCount();
     58                header.TruncatePerFact();
    6059                return header;
    6160            }
     
    8685            soundData = reader.ReadBytes(chunkSize);
    8786        }
    88         private void ValidateSampleCount() // TODO: ACTUAL VALIDATION/CORRECTION
     87        private void TruncatePerFact() // TODO: MORE THOROUGH VALIDATION?
    8988        {
    90             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)
    9390            {
    9491                Console.WriteLine("The imported WAV file has no FACT chunk.");
    9592            }
    96             else // TODO: calculate sampleCountFromData, compare with sampleCount
     93            else if (format == WavFormat.Adpcm) // calculate truncated data size
    9794            {
    98 
     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);
    99109            }
    100110        }
     
    106116        public int BlockAlign => blockAlign;
    107117        public int BitsPerSample => bitsPerSample;
     118        public int SampleCount => sampleCount;
    108119        public byte[] ExtraData => extraData;
    109120        public byte[] SoundData => soundData;
  • OniSplit/Sound/WavImporter.cs

    r1154 r1156  
    4646        private void WriteSNDD(string name, WavFile wav)
    4747        {
    48             float duration = wav.SoundData.Length * 8.0f / wav.BitsPerSample;
    49             duration /= wav.SampleRate;
    50             duration /= wav.ChannelCount;
    51             duration *= 60.0f;
     48            float duration = wav.SampleCount * 60.0f / wav.SampleRate;
    5249
    5350            var sndd = CreateInstance(TemplateTag.SNDD, name);
     
    7471                    writer.Write(wav.SoundData.Length);
    7572                    writer.Write(WriteRawPart(wav.SoundData));
     73                    writer.Skip(8);
    7674                }
    7775            }
     
    9795                    writer.Write(wav.SoundData.Length);
    9896                    writer.Write(WriteRawPart(wav.SoundData));
     97                    writer.Skip(24);
    9998                }
    10099            }
Note: See TracChangeset for help on using the changeset viewer.