source: OniSplit/Sound/WavImporter.cs @ 1154

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

Implemented import/export of "fact" chunk for .wav files. Added a -demo tag for storing sounds in the PC demo format (if compatible).

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.SoundData.Length * 8.0f / wav.BitsPerSample;
49            duration /= wav.SampleRate;
50            duration /= wav.ChannelCount;
51            duration *= 60.0f;
52
53            var sndd = CreateInstance(TemplateTag.SNDD, name);
54            if (convertToDemo)
55            {
56                // TODO: also validate other ADPCM parameters (coefficient table)?
57                if (wav.Format != WavFormat.Adpcm) // Or is PCM supported, actually?
58                    Console.WriteLine("Cannot convert to PC demo: ADPCM format required!");
59                if (wav.SampleRate != 22050)
60                    Console.WriteLine("Cannot convert to PC demo: 22050 kHz required!");
61                if (wav.BlockAlign != 512 * wav.ChannelCount)
62                    Console.WriteLine("Cannot convert to PC demo: wrong block alignment!");
63                if (wav.BitsPerSample != 4)
64                    Console.WriteLine("Cannot convert to PC demo: wrong bits per sample!");
65
66                using (var writer = sndd.OpenWrite())
67                {
68                    if (wav.ChannelCount == 2)
69                        writer.WriteInt16(3);
70                    else 
71                        writer.WriteInt16(1);
72                    writer.WriteInt16(0);
73                    writer.Write((int)duration);
74                    writer.Write(wav.SoundData.Length);
75                    writer.Write(WriteRawPart(wav.SoundData));
76                }
77            }
78            else
79            {
80                using (var writer = sndd.OpenWrite())
81                {
82                    if (wav.Format == WavFormat.Adpcm)
83                        writer.WriteInt16(8);
84                    else
85                        writer.WriteInt16(0);
86                    writer.WriteInt16(0);
87                    writer.Write((short)wav.Format);
88                    writer.WriteInt16(wav.ChannelCount);
89                    writer.Write(wav.SampleRate);
90                    writer.Write(wav.AverageBytesPerSecond);
91                    writer.WriteInt16(wav.BlockAlign);
92                    writer.WriteInt16(wav.BitsPerSample);
93                    writer.WriteInt16(wav.ExtraData.Length);
94                    writer.Write(wav.ExtraData);
95                    writer.Skip(32 - wav.ExtraData.Length);
96                    writer.Write((short)duration);
97                    writer.Write(wav.SoundData.Length);
98                    writer.Write(WriteRawPart(wav.SoundData));
99                }
100            }
101        }
102    }
103}
Note: See TracBrowser for help on using the repository browser.