source: OniSplit/Sound/WavImporter.cs@ 1154

Last change on this file since 1154 was 1154, checked in by geyser, 4 years 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.