source: OniSplit/Sound/WavImporter.cs @ 1156

Last change on this file since 1156 was 1156, checked in by geyser, 14 months ago

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.

File size: 4.0 KB
Line 
1using System;
2using System.IO;
3
4namespace Oni.Sound
5{
6    internal class WavImporter : Importer
7    {
8        private readonly bool convertToDemo;
9
10        public WavImporter(bool toDemo)
11            : base(toDemo?InstanceFileHeader.OniMacTemplateChecksum:InstanceFileHeader.OniPCTemplateChecksum)
12        {
13            convertToDemo = toDemo;
14        }
15
16        public override void Import(string filePath, string outputDirPath)
17        {
18            var wav = WavFile.FromFile(filePath);
19
20            if (wav.Format != WavFormat.Pcm && wav.Format != WavFormat.Adpcm)
21            {
22                Console.Error.WriteLine("Unsupported WAV format (0x{0:X})", wav.Format);
23                return;
24            }
25
26            if (wav.ChannelCount != 1 && wav.ChannelCount != 2)
27            {
28                Console.Error.WriteLine("Unsupported number of channels ({0})", wav.ChannelCount);
29                return;
30            }
31
32            if (wav.SampleRate != 22050 && wav.SampleRate != 44100)
33            {
34                Console.Error.WriteLine("Unsupported sample rate ({0} Hz)", wav.SampleRate);
35                return;
36            }
37
38            if (wav.ExtraData.Length > 32)
39                throw new NotSupportedException(string.Format("Unsupported wave format extra data size ({0})", wav.ExtraData.Length));
40
41            BeginImport();
42            WriteSNDD(Path.GetFileNameWithoutExtension(filePath), wav);
43            Write(outputDirPath);
44        }
45
46        private void WriteSNDD(string name, WavFile wav)
47        {
48            float duration = wav.SampleCount * 60.0f / wav.SampleRate;
49
50            var sndd = CreateInstance(TemplateTag.SNDD, name);
51            if (convertToDemo)
52            {
53                // TODO: also validate other ADPCM parameters (coefficient table)?
54                if (wav.Format != WavFormat.Adpcm) // Or is PCM supported, actually?
55                    Console.WriteLine("Cannot convert to PC demo: ADPCM format required!");
56                if (wav.SampleRate != 22050)
57                    Console.WriteLine("Cannot convert to PC demo: 22050 kHz required!");
58                if (wav.BlockAlign != 512 * wav.ChannelCount)
59                    Console.WriteLine("Cannot convert to PC demo: wrong block alignment!");
60                if (wav.BitsPerSample != 4)
61                    Console.WriteLine("Cannot convert to PC demo: wrong bits per sample!");
62
63                using (var writer = sndd.OpenWrite())
64                {
65                    if (wav.ChannelCount == 2)
66                        writer.WriteInt16(3);
67                    else 
68                        writer.WriteInt16(1);
69                    writer.WriteInt16(0);
70                    writer.Write((int)duration);
71                    writer.Write(wav.SoundData.Length);
72                    writer.Write(WriteRawPart(wav.SoundData));
73                    writer.Skip(8);
74                }
75            }
76            else
77            {
78                using (var writer = sndd.OpenWrite())
79                {
80                    if (wav.Format == WavFormat.Adpcm)
81                        writer.WriteInt16(8);
82                    else
83                        writer.WriteInt16(0);
84                    writer.WriteInt16(0);
85                    writer.Write((short)wav.Format);
86                    writer.WriteInt16(wav.ChannelCount);
87                    writer.Write(wav.SampleRate);
88                    writer.Write(wav.AverageBytesPerSecond);
89                    writer.WriteInt16(wav.BlockAlign);
90                    writer.WriteInt16(wav.BitsPerSample);
91                    writer.WriteInt16(wav.ExtraData.Length);
92                    writer.Write(wav.ExtraData);
93                    writer.Skip(32 - wav.ExtraData.Length);
94                    writer.Write((short)duration);
95                    writer.Write(wav.SoundData.Length);
96                    writer.Write(WriteRawPart(wav.SoundData));
97                    writer.Skip(24);
98                }
99            }
100        }
101    }
102}
Note: See TracBrowser for help on using the repository browser.