| 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 |
} |