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 1154 by geyser, Mon May 3 15:22:15 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;
156 >                var blockSizeADPCM = sound.BlockAlignment;
157 >                
158                  int wholeBlocks = sound.Data.Length / blockSizeADPCM;
159                  int leftoverBytes = sound.Data.Length - (wholeBlocks * blockSizeADPCM);
160 <                int leftoverSamples = 8 * (leftoverBytes - 7 * sound.ChannelCount)
161 <                                      / 4 / sound.ChannelCount + 2; // 4 bits per sample
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 / 4;
167 >                var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / sound.BitsPerSample;
168 >
169 >                Int32 sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
170  
164                Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples;
165                
171                  if (sound.IsIMA4) // IMA4 ADPCM format
172                  {
173                      blockSizeADPCM = 34 * sound.ChannelCount;
174                      samplesPerBlock = 64;
175                      sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock;
176                  }
172
177                  if (!convert_to_PCM)
178                  {
179                      if (sound.IsIMA4)
180                      {
181 <                        throw new NotSupportedException("Transcoding from Mac/demo ADPCM to PC ADPCM not supported! Please use -extract:pcm");
181 >                        throw new NotSupportedException("Transcoding from IMA4 ADPCM (Mac) to MS ADPCM (PC) not supported! Please use -extract:pcm");
182                      }
183                      var format = (byte[])formatTemplate_ADPCM.Clone();
184                      var fact = (byte[])factTemplate.Clone(); // needed for ADPCM (to specify the actual sample count)
# Line 270 | Line 274 | namespace Oni.Sound
274                                  if (predictorL > 32767) predictorL -= 65536;
275                              }
276                              stepIndexL = headerLoL & 0x7f;
277 +                            if (stepIndexL > 88)
278 +                                Console.WriteLine("Block {0} (L): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexL);
279 +                            ClampToRange(ref stepIndexL, 0, 88);
280 +
281                              for (int b = 0; b < 32; b++)
282                              {
283                                  Byte nibblesL = sound.Data[pos++];
# Line 290 | Line 298 | namespace Oni.Sound
298                                      if (predictorR > 32767) predictorR -= 65536;
299                                  }
300                                  stepIndexR = headerLoR & 0x7f;
301 +                                if (stepIndexR > 88)
302 +                                    Console.WriteLine("Block {0} (R): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexR);
303 +                                ClampToRange(ref stepIndexR, 0, 88);
304  
305                                  for (int b = 0; b < 32; b++)
306                                  {
# Line 359 | Line 370 | namespace Oni.Sound
370                                      samplesR[iSampleR++] = sample1R;
371                                  }
372                              }
373 <                            // read pair of nibbles
374 <                            Byte nibbles = sound.Data[pos++];
375 <                            Byte nibbleHi = (Byte)(nibbles >> 4);
376 <                            Byte nibbleLo = (Byte)(nibbles & 0xF);
377 <                            samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
378 <                            if (sound.ChannelCount == 2)
379 <                                samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
380 <                            else
381 <                                samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
373 >                            else // read pair of nibbles
374 >                            {
375 >                                Byte nibbles = sound.Data[pos++];
376 >                                Byte nibbleHi = (Byte)(nibbles >> 4);
377 >                                Byte nibbleLo = (Byte)(nibbles & 0xF);
378 >                                samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi);
379 >                                if (sound.ChannelCount == 2)
380 >                                    samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo);
381 >                                else
382 >                                    samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo);
383 >                            }
384                          }
385                      }
386                      writer.Write(fcc_data);

Diff Legend

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