1 | using System; |
---|
2 | using System.IO; |
---|
3 | |
---|
4 | namespace 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 | } |
---|