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

Comparing OniSplit/Sound/WavExporter.cs (file contents):
Revision 1130 by geyser, Thu May 28 21:28:44 2020 UTC vs.
Revision 1156 by geyser, Sat May 8 01:44:24 2021 UTC

# Line 7 | Line 7 | namespace Oni.Sound
7      {
8          #region Private data
9          private bool convert_to_PCM;
10 +        private bool do_pc_demo_test;
11  
12          private const int fcc_RIFF = 0x46464952;
13          private const int fcc_WAVE = 0x45564157;
# Line 85 | Line 86 | namespace Oni.Sound
86          };
87          #endregion
88  
89 <        public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false)
89 >        public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false, bool noDemo = false)
90              : base(fileManager, outputDirPath)
91          {
92              convert_to_PCM = convertToPCM;
93 +            do_pc_demo_test = !noDemo;
94          }
95  
96          private static void ClampToRange(ref int value, int lower, int upper)
# Line 146 | Line 148 | namespace Oni.Sound
148  
149          protected override void ExportInstance(InstanceDescriptor descriptor)
150          {
151 <            var sound = SoundData.Read(descriptor);
151 >            var sound = SoundData.Read(descriptor, do_pc_demo_test);
152  
153              using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".wav")))
154              using (var writer = new BinaryWriter(stream))
155              {
156 <                var blockSizeADPCM = 512 * sound.ChannelCount * sound.SampleRate / 22050;
155 <                int wholeBlocks = sound.Data.Length / blockSizeADPCM;
156 <                int leftoverBytes = sound.Data.Length - (wholeBlocks * blockSizeADPCM);
157 <                int leftoverSamples = 8 * (leftoverBytes - 7 * sound.ChannelCount)
158 <                                      / 4 / sound.ChannelCount + 2; // 4 bits per sample
159 <                int paddingBytes = 0;
160 <                if (leftoverBytes > 0) // incomplete trailing block
161 <                    paddingBytes = blockSizeADPCM - leftoverBytes;
162 <                var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / 4;
163 <
164 <                Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
165 <                
156 >                int blockSizeADPCM, samplesPerBlock, sampleCount, paddingBytes = 0;
157                  if (sound.IsIMA4) // IMA4 ADPCM format
158                  {
159                      blockSizeADPCM = 34 * sound.ChannelCount;
160                      samplesPerBlock = 64;
161                      sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock;
162                  }
163 <
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;
178 >                }
179                  if (!convert_to_PCM)
180                  {
181                      if (sound.IsIMA4)
182                      {
183 <                        throw new NotSupportedException("Transcoding from Mac/demo ADPCM to PC ADPCM not supported! Please use -extract:pcm");
183 >                        throw new NotSupportedException("Transcoding from IMA4 ADPCM (Mac) to MS ADPCM (PC) not supported! Please use -extract:pcm");
184                      }
185                      var format = (byte[])formatTemplate_ADPCM.Clone();
186                      var fact = (byte[])factTemplate.Clone(); // needed for ADPCM (to specify the actual sample count)
# Line 270 | Line 276 | namespace Oni.Sound
276                                  if (predictorL > 32767) predictorL -= 65536;
277                              }
278                              stepIndexL = headerLoL & 0x7f;
279 +                            if (stepIndexL > 88)
280 +                                Console.WriteLine("Block {0} (L): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexL);
281 +                            ClampToRange(ref stepIndexL, 0, 88);
282 +
283                              for (int b = 0; b < 32; b++)
284                              {
285                                  Byte nibblesL = sound.Data[pos++];
# Line 290 | Line 300 | namespace Oni.Sound
300                                      if (predictorR > 32767) predictorR -= 65536;
301                                  }
302                                  stepIndexR = headerLoR & 0x7f;
303 +                                if (stepIndexR > 88)
304 +                                    Console.WriteLine("Block {0} (R): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexR);
305 +                                ClampToRange(ref stepIndexR, 0, 88);
306  
307                                  for (int b = 0; b < 32; b++)
308                                  {
# Line 359 | Line 372 | namespace Oni.Sound
372                                      samplesR[iSampleR++] = sample1R;
373                                  }
374                              }
375 <                            // read pair of nibbles
376 <                            Byte nibbles = sound.Data[pos++];
377 <                            Byte nibbleHi = (Byte)(nibbles >> 4);
378 <                            Byte nibbleLo = (Byte)(nibbles & 0xF);
379 <                            samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
380 <                            if (sound.ChannelCount == 2)
381 <                                samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
382 <                            else
383 <                                samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
375 >                            else // read pair of nibbles
376 >                            {
377 >                                Byte nibbles = sound.Data[pos++];
378 >                                Byte nibbleHi = (Byte)(nibbles >> 4);
379 >                                Byte nibbleLo = (Byte)(nibbles & 0xF);
380 >                                samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
381 >                                if (sound.ChannelCount == 2)
382 >                                    samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
383 >                                else
384 >                                    samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
385 >                            }
386                          }
387                      }
388                      writer.Write(fcc_data);

Diff Legend

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