using System; using System.IO; namespace Oni.Sound { internal class WavImporter : Importer { private readonly bool convertToDemo; public WavImporter(bool toDemo) : base(toDemo?InstanceFileHeader.OniMacTemplateChecksum:InstanceFileHeader.OniPCTemplateChecksum) { convertToDemo = toDemo; } public override void Import(string filePath, string outputDirPath) { var wav = WavFile.FromFile(filePath); if (wav.Format != WavFormat.Pcm && wav.Format != WavFormat.Adpcm) { Console.Error.WriteLine("Unsupported WAV format (0x{0:X})", wav.Format); return; } if (wav.ChannelCount != 1 && wav.ChannelCount != 2) { Console.Error.WriteLine("Unsupported number of channels ({0})", wav.ChannelCount); return; } if (wav.SampleRate != 22050 && wav.SampleRate != 44100) { Console.Error.WriteLine("Unsupported sample rate ({0} Hz)", wav.SampleRate); return; } if (wav.ExtraData.Length > 32) throw new NotSupportedException(string.Format("Unsupported wave format extra data size ({0})", wav.ExtraData.Length)); BeginImport(); WriteSNDD(Path.GetFileNameWithoutExtension(filePath), wav); Write(outputDirPath); } private void WriteSNDD(string name, WavFile wav) { float duration = wav.SoundData.Length * 8.0f / wav.BitsPerSample; duration /= wav.SampleRate; duration /= wav.ChannelCount; duration *= 60.0f; var sndd = CreateInstance(TemplateTag.SNDD, name); if (convertToDemo) { // TODO: also validate other ADPCM parameters (coefficient table)? if (wav.Format != WavFormat.Adpcm) // Or is PCM supported, actually? Console.WriteLine("Cannot convert to PC demo: ADPCM format required!"); if (wav.SampleRate != 22050) Console.WriteLine("Cannot convert to PC demo: 22050 kHz required!"); if (wav.BlockAlign != 512 * wav.ChannelCount) Console.WriteLine("Cannot convert to PC demo: wrong block alignment!"); if (wav.BitsPerSample != 4) Console.WriteLine("Cannot convert to PC demo: wrong bits per sample!"); using (var writer = sndd.OpenWrite()) { if (wav.ChannelCount == 2) writer.WriteInt16(3); else writer.WriteInt16(1); writer.WriteInt16(0); writer.Write((int)duration); writer.Write(wav.SoundData.Length); writer.Write(WriteRawPart(wav.SoundData)); } } else { using (var writer = sndd.OpenWrite()) { if (wav.Format == WavFormat.Adpcm) writer.WriteInt16(8); else writer.WriteInt16(0); writer.WriteInt16(0); writer.Write((short)wav.Format); writer.WriteInt16(wav.ChannelCount); writer.Write(wav.SampleRate); writer.Write(wav.AverageBytesPerSecond); writer.WriteInt16(wav.BlockAlign); writer.WriteInt16(wav.BitsPerSample); writer.WriteInt16(wav.ExtraData.Length); writer.Write(wav.ExtraData); writer.Skip(32 - wav.ExtraData.Length); writer.Write((short)duration); writer.Write(wav.SoundData.Length); writer.Write(WriteRawPart(wav.SoundData)); } } } } }