/// <summary> /// Write the RIFF. /// </summary> /// <param name="w">The writer.</param> public override void Write(FileWriter w) { //Init. using (RiffWriter rw = new RiffWriter(w.BaseStream)) { //Init file. rw.InitFile("WAVE"); //Format block. rw.StartChunk("fmt "); rw.Write((ushort)1); rw.Write((ushort)Audio.Channels.Count); rw.Write(SampleRate); uint bitsPerSample = Audio.EncodingType.Equals(typeof(PCM16)) ? 16u : 8u; rw.Write((uint)(SampleRate * Audio.Channels.Count * (bitsPerSample / 8))); rw.Write((ushort)(bitsPerSample / 8 * Audio.Channels.Count)); rw.Write((ushort)bitsPerSample); rw.EndChunk(); //Sample block. if (Loops) { rw.StartChunk("smpl"); rw.Write(new uint[2]); rw.Write((uint)(1d / SampleRate * 1000000000)); rw.Write((uint)60); rw.Write(new uint[3]); rw.Write((uint)1); rw.Write(new uint[3]); rw.Write(LoopStart /* * bitsPerSample / 8*/); rw.Write(LoopEnd /* * bitsPerSample / 8*/); rw.Write((ulong)0); rw.EndChunk(); } //Data block. Audio.ChangeBlockSize((int)bitsPerSample / 8); rw.StartChunk("data"); w.Position = rw.Position; Audio.Write(w); rw.Position = w.Position; while (rw.Position % 2 != 0) { rw.Write((byte)0); } rw.EndChunk(); //Close file. rw.CloseFile(); Audio.ChangeBlockSize(-1); } }
/// <summary> /// Write the file. /// </summary> /// <param name="w2">The file writer.</param> public override void Write(FileWriter w2) { //Use a RIFF writer. using (RiffWriter w = new RiffWriter(w2.BaseStream)) { //Init file. w.InitFile("DLS "); //Instrument count. w.StartChunk("colh"); w.Write((uint)Instruments.Count); w.EndChunk(); //Instruments. w.StartListChunk("lins"); foreach (var inst in Instruments) { w.StartListChunk("ins "); w.StartChunk("insh"); w.Write((uint)inst.Regions.Count); w.Write(inst.BankId); w.Write(inst.InstrumentId); w.EndChunk(); w.StartListChunk("lrgn"); foreach (Region r in inst.Regions) { w.StartListChunk("rgn2"); w.StartChunk("rgnh"); w.Write(r.NoteLow); w.Write(r.NoteHigh); w.Write(r.VelocityLow); w.Write(r.VelocityHigh); w.Write((ushort)(r.DoublePlayback ? 1 : 0)); w.Write((ushort)r.KeyGroup); w.Write(r.Layer); w.EndChunk(); w.StartChunk("wsmp"); w.Write((uint)0x14); w.Write((ushort)r.RootNote); w.Write(r.Tuning); w.Write(r.Gain); uint flags = 0; if (r.NoTruncation) { flags |= 0b1; } if (r.NoCompression) { flags |= 0b10; } w.Write(flags); w.Write((uint)(r.Loops ? 1 : 0)); if (r.Loops) { w.Write((uint)0x10); w.Write((uint)(r.LoopAndRelease ? 1 : 0)); w.Write(r.LoopStart); w.Write(r.LoopLength); } w.EndChunk(); w.StartChunk("wlnk"); ushort flg = 0; if (r.PhaseMaster) { flg |= 0b1; } if (r.MultiChannel) { flg |= 0b10; } w.Write(flg); w.Write(r.PhaseGroup); w.Write(r.ChannelFlags); w.Write(r.WaveId); w.EndChunk(); w.StartListChunk("lar2"); foreach (var a in r.Articulators) { w.StartChunk("art2"); w.Write((uint)8); w.Write((uint)a.Connections.Count); foreach (var c in a.Connections) { w.Write((ushort)c.SourceConnection); w.Write(c.ControlConnection); w.Write((ushort)c.DestinationConnection); w.Write((ushort)c.TransformConnection); w.Write(c.Scale); } w.EndChunk(); } w.EndChunk(); w.EndChunk(); } w.EndChunk(); if (inst.Name != "") { w.StartListChunk("INFO"); w.StartChunk("INAM"); w.Write(inst.Name.ToCharArray()); w.Write("\0".ToCharArray()); int len = inst.Name.Length + 1; while (len % 4 != 0) { w.Write((byte)0); len++; } w.EndChunk(); w.EndChunk(); } w.EndChunk(); } w.EndChunk(); //Pointer table initializing. w.StartChunk("ptbl"); w.Write((uint)8); w.Write((uint)Waves.Count); long ptblStart = w.BaseStream.Position; w.Write(new byte[Waves.Count * 4]); w.EndChunk(); //Write waves. w.StartListChunk("wvpl"); long waveTableStart = w.BaseStream.Position; int waveNum = 0; foreach (var wav in Waves) { long wBak = w.BaseStream.Position; w.BaseStream.Position = ptblStart + waveNum++ *4; w.Write((uint)(wBak - waveTableStart)); w.BaseStream.Position = wBak; w.WriteWave(wav); } w.EndChunk(); //Write info. w.StartListChunk("INFO"); w.StartChunk("INAM"); w.Write("Instrument Set".ToCharArray()); w.EndChunk(); w.EndChunk(); //Close file. w.CloseFile(); } }
/// <summary> /// Write the file. /// </summary> /// <param name="w2">The writer.</param> public override void Write(FileWriter w2) { //Use a RIFF writer. using (RiffWriter w = new RiffWriter(w2.BaseStream)) { //Start file. w.InitFile("sfbk"); //Start INFO. w.StartListChunk("INFO"); //Version. w.StartChunk("ifil"); w.Write((ushort)2); w.Write((ushort)1); w.EndChunk(); //Sound engine. w.StartChunk("isng"); w.WriteNullTerminated(SoundEngine); w.Align(2); w.EndChunk(); //Bank name. w.StartChunk("INAM"); w.WriteNullTerminated(BankName); w.Align(2); w.EndChunk(); //ROM name. if (!RomName.Equals("")) { w.StartChunk("irom"); w.WriteNullTerminated(RomName); w.Align(2); w.EndChunk(); } //ROM version. if (RomVersion != null) { w.StartChunk("iver"); w.Write(RomVersion.Item1); w.Write(RomVersion.Item2); w.EndChunk(); } //Creation date. if (!CreationDate.Equals("")) { w.StartChunk("ICRD"); w.WriteNullTerminated(CreationDate); w.Align(2); w.EndChunk(); } //Sound designer. if (!SoundDesigner.Equals("")) { w.StartChunk("IENG"); w.WriteNullTerminated(SoundDesigner); w.Align(2); w.EndChunk(); } //Product. if (!Product.Equals("")) { w.StartChunk("IPRD"); w.WriteNullTerminated(Product); w.Align(2); w.EndChunk(); } //Copyright. if (!Copyright.Equals("")) { w.StartChunk("ICOP"); w.WriteNullTerminated(Copyright); w.Align(2); w.EndChunk(); } //Comment. if (!Comment.Equals("")) { w.StartChunk("ICMT"); w.WriteNullTerminated(Comment); w.Align(2); w.EndChunk(); } //Tools. if (!Tools.Equals("")) { w.StartChunk("ISFT"); w.WriteNullTerminated(Tools); w.Align(2); w.EndChunk(); } //End INFO. w.EndChunk(); //Sample block. w.StartListChunk("sdta"); w.StartChunk("smpl"); long waveTableStart = w.Position; Dictionary <SampleItem, long> samplePositions = new Dictionary <SampleItem, long>(); foreach (var s in Samples) { samplePositions.Add(s, w.Position); w.Write(new short[s.Wave.Audio.NumSamples]); w.Write(new short[46]); } w.EndChunk(); w.EndChunk(); //The hydra. w.StartListChunk("pdta"); //Presets. w.StartChunk("phdr"); ushort currBagIndex = 0; List <Zone> zones = new List <Zone>(); foreach (var p in Presets) { p.ReadingBagIndex = currBagIndex; currBagIndex += (ushort)p.NumZones; w.Write(p); zones.AddRange(p.GetAllZones()); } w.Write(new Preset() { Name = "EOP", Bank = 255, PresetNumber = 255, ReadingBagIndex = currBagIndex }); w.EndChunk(); //Preset bags. w.StartChunk("pbag"); ushort currGenIndex = 0; ushort currModIndex = 0; foreach (var z in zones) { w.Write(currGenIndex); w.Write(currModIndex); currGenIndex += (ushort)z.Generators.Count; currModIndex += (ushort)z.Modulators.Count; } w.Write(currGenIndex); w.Write(currModIndex); w.EndChunk(); //Preset modulators. w.StartChunk("pmod"); foreach (var z in zones) { foreach (var v in z.Modulators) { w.Write(v); } } w.Write(new Modulator()); w.EndChunk(); //Preset generators. w.StartChunk("pgen"); foreach (var z in zones) { foreach (var v in z.Generators) { w.Write(v); } } w.Write(new Generator()); w.EndChunk(); //Instruments. w.StartChunk("inst"); currBagIndex = 0; zones = new List <Zone>(); foreach (var p in Instruments) { p.ReadingBagIndex = currBagIndex; currBagIndex += (ushort)p.NumZones; w.Write(p); zones.AddRange(p.GetAllZones()); } w.Write(new Instrument() { Name = "EOI", ReadingBagIndex = currBagIndex }); w.EndChunk(); //Instrument bags. w.StartChunk("ibag"); currGenIndex = 0; currModIndex = 0; foreach (var z in zones) { w.Write(currGenIndex); w.Write(currModIndex); currGenIndex += (ushort)z.Generators.Count; currModIndex += (ushort)z.Modulators.Count; } w.Write(currGenIndex); w.Write(currModIndex); w.EndChunk(); //Instrument modulators. w.StartChunk("imod"); foreach (var z in zones) { foreach (var v in z.Modulators) { w.Write(v); } } w.Write(new Modulator()); w.EndChunk(); //Instrument generators. w.StartChunk("igen"); foreach (var z in zones) { foreach (var v in z.Generators) { w.Write(v); } } w.Write(new Generator()); w.EndChunk(); //Samples. w.StartChunk("shdr"); foreach (var s in Samples) { w.CurrentOffset = samplePositions[s]; w.StructureOffsets.Push(waveTableStart); w.Write(s); } w.Write("EOS".ToCharArray()); w.Write(new byte[0x2B]); w.EndChunk(); //End the hydra. w.EndChunk(); //Close file. w.CloseFile(); } }