1 |
using System; |
2 |
using System.IO; |
3 |
|
4 |
namespace Oni.Sound |
5 |
{ |
6 |
internal class WavExporter : SoundExporter |
7 |
{ |
8 |
#region Private data |
9 |
private const int fcc_RIFF = 0x46464952; |
10 |
private const int fcc_WAVE = 0x45564157; |
11 |
private const int fcc_fmt = 0x20746d66; |
12 |
private const int fcc_data = 0x61746164; |
13 |
|
14 |
private static readonly byte[] formatTemplate = new byte[50] |
15 |
{ |
16 |
0x02, 0, // format ID (always 2) |
17 |
0, 0, // ChannelCount (overwritten) |
18 |
0x22, 0x56, 0, 0, // SampleRate (usually 22050, can be 44100) |
19 |
0, 0, 0, 0, // average data rate (computed and overwritten) |
20 |
0, 0x02, // block alignment (default 512, can be 1024) |
21 |
0x04, 0, // bits per sample (always 4) |
22 |
0x20, 0, // size of extended header block |
23 |
0xf4, 0x03, // samples per block (usually 1012, can be 2036) |
24 |
0x07, 0, // standard ADPCM coefficient table (always the same) |
25 |
0, 0x01, 0, 0, |
26 |
0, 0x02, 0, 0xff, |
27 |
0, 0, 0, 0, |
28 |
0xc0, 0, 0x40, 0, |
29 |
0xf0, 0, 0, 0, |
30 |
0xcc, 0x01, 0x30, 0xff, |
31 |
0x88, 0x01, 0x18, 0xff |
32 |
}; |
33 |
|
34 |
#endregion |
35 |
|
36 |
public WavExporter(InstanceFileManager fileManager, string outputDirPath) |
37 |
: base(fileManager, outputDirPath) |
38 |
{ |
39 |
} |
40 |
|
41 |
protected override void ExportInstance(InstanceDescriptor descriptor) |
42 |
{ |
43 |
var sound = SoundData.Read(descriptor); |
44 |
|
45 |
using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".wav"))) |
46 |
using (var writer = new BinaryWriter(stream)) |
47 |
{ |
48 |
var format = (byte[])formatTemplate.Clone(); |
49 |
|
50 |
var blockAlignment = 512 * sound.ChannelCount * sound.SampleRate / 22050; |
51 |
var samplesPerBlock = 2 + (blockAlignment - sound.ChannelCount * 7) * 8 / sound.ChannelCount / 4; |
52 |
var averageRate = sound.SampleRate * blockAlignment / samplesPerBlock; |
53 |
Array.Copy(BitConverter.GetBytes(sound.ChannelCount), 0, format, 2, 2); |
54 |
Array.Copy(BitConverter.GetBytes(sound.SampleRate), 0, format, 4, 4); |
55 |
Array.Copy(BitConverter.GetBytes(averageRate), 0, format, 8, 4); |
56 |
Array.Copy(BitConverter.GetBytes(blockAlignment), 0, format, 12, 2); |
57 |
Array.Copy(BitConverter.GetBytes(samplesPerBlock), 0, format, 18, 2); |
58 |
|
59 |
writer.Write(fcc_RIFF); |
60 |
writer.Write(8 + format.Length + 8 + sound.Data.Length); |
61 |
writer.Write(fcc_WAVE); |
62 |
|
63 |
// |
64 |
// write format chunk |
65 |
// |
66 |
|
67 |
writer.Write(fcc_fmt); |
68 |
writer.Write(format.Length); |
69 |
writer.Write(format); |
70 |
|
71 |
// |
72 |
// write data chunk |
73 |
// |
74 |
|
75 |
writer.Write(fcc_data); |
76 |
writer.Write(sound.Data.Length); |
77 |
writer.Write(sound.Data); |
78 |
} |
79 |
} |
80 |
} |
81 |
} |