/// <summary> /// Read the RIFF. /// </summary> /// <param name="r">The reader.</param> public override void Read(FileReader r) { //Init. using (RiffReader rr = new RiffReader(r.BaseStream)) { //Format. rr.OpenChunk(rr.Chunks.Where(x => x.Magic.Equals("fmt ")).FirstOrDefault()); if (rr.ReadUInt16() != 1) { throw new Exception("Unexpected standard WAV data format."); } int numChannels = rr.ReadUInt16(); SampleRate = rr.ReadUInt32(); rr.ReadUInt32(); //Byte rate. rr.ReadUInt16(); //Blocks. ushort bitsPerSample = rr.ReadUInt16(); LoopStart = 0; LoopEnd = 0; Loops = false; if (bitsPerSample != 8 && bitsPerSample != 16) { throw new Exception("This tool only accepts 8-bit or 16-bit WAV files."); } //Sample. var smpl = rr.Chunks.Where(x => x.Magic.Equals("smpl")).FirstOrDefault(); if (smpl != null) { rr.OpenChunk(smpl); rr.ReadUInt32s(7); Loops = rr.ReadUInt32() > 0; if (Loops) { rr.ReadUInt32s(3); LoopStart = r.ReadUInt32(); //(uint)(r.ReadUInt32() / (bitsPerSample / 8)); LoopEnd = r.ReadUInt32(); //(uint)(r.ReadUInt32() / (bitsPerSample / 8)); } } //Data. rr.OpenChunk(rr.Chunks.Where(x => x.Magic.Equals("data")).FirstOrDefault()); uint dataSize = rr.Chunks.Where(x => x.Magic.Equals("data")).FirstOrDefault().Size; uint numBlocks = (uint)(dataSize / numChannels / (bitsPerSample / 8)); r.Position = rr.Position; Audio.Read(r, bitsPerSample == 16 ? typeof(PCM16) : typeof(PCM8), numChannels, numBlocks, (uint)bitsPerSample / 8, 1, (uint)bitsPerSample / 8, 1, 0); Audio.ChangeBlockSize(-1); } }
/// <summary> /// Read the file. /// </summary> /// <param name="r2">The file reader.</param> public override void Read(FileReader r2) { //Use a RIFF reader. using (RiffReader r = new RiffReader(r2.BaseStream)) { //Get the number of instruments. r.OpenChunk(r.GetChunk("colh")); uint numInsts = r.ReadUInt32(); //Pointer table is skipped since it's just offsets to wave data relative to the first wave identifier. //Read wave data. Waves = new List <RiffWave>(); foreach (var c in (r.GetChunk("wvpl") as ListChunk).Chunks) { //Open block. r.OpenChunk(c); //Set position for proper RIFF reading. r.BaseStream.Position -= 8; int len = r.ReadInt32() + 8; r.BaseStream.Position -= 8; RiffWave wav = new RiffWave(); wav.Read(r.ReadBytes(len)); Waves.Add(wav); } //Read each instrument. foreach (ListChunk c in (r.GetChunk("lins") as ListChunk).Chunks) { //Open block. r.OpenChunk(c); //New instrument. Instrument inst = new Instrument(); //Read header. r.OpenChunk(c.GetChunk("insh")); r.ReadUInt32(); inst.BankId = r.ReadUInt32(); inst.InstrumentId = r.ReadUInt32(); //Read regions. foreach (ListChunk g in (c.GetChunk("lrgn") as ListChunk).Chunks) { //New region. Region reg = new Region(); //Region header. r.OpenChunk(g.GetChunk("rgnh")); reg.NoteLow = r.ReadUInt16(); reg.NoteHigh = r.ReadUInt16(); reg.VelocityLow = r.ReadUInt16(); reg.VelocityHigh = r.ReadUInt16(); reg.DoublePlayback = r.ReadUInt16() > 0; reg.KeyGroup = (byte)r.ReadUInt16(); reg.Layer = r.ReadUInt16(); //Note information. r.OpenChunk(g.GetChunk("wsmp")); r.ReadUInt32(); reg.RootNote = (byte)r.ReadUInt16(); reg.Tuning = r.ReadInt16(); reg.Gain = r.ReadInt32(); uint flags = r.ReadUInt32(); reg.NoTruncation = (flags & 0b1) > 0; reg.NoCompression = (flags & 0b10) > 0; reg.Loops = r.ReadUInt32() > 0; if (reg.Loops) { r.ReadUInt32(); reg.LoopAndRelease = r.ReadUInt32() > 0; reg.LoopStart = r.ReadUInt32(); reg.LoopLength = r.ReadUInt32(); } //Wave link. r.OpenChunk(g.GetChunk("wlnk")); uint flg = r.ReadUInt16(); reg.PhaseMaster = (flg & 0b1) > 0; reg.MultiChannel = (flg & 0b10) > 0; reg.PhaseGroup = r.ReadUInt16(); reg.ChannelFlags = r.ReadUInt32(); reg.WaveId = r.ReadUInt32(); //Loop. Waves[(int)reg.WaveId].Loops = reg.Loops; if (reg.Loops) { Waves[(int)reg.WaveId].LoopStart = reg.LoopStart; Waves[(int)reg.WaveId].LoopEnd = reg.LoopLength == 0 ? (uint)Waves[(int)reg.WaveId].Audio.NumSamples : reg.LoopStart + reg.LoopLength; } //Articulators. var lar = g.GetChunk("lar2"); if (lar == null) { lar = g.GetChunk("lar1"); } foreach (Chunk art in (g.GetChunk("lar2") as ListChunk).Chunks) { //Read articulator. Articulator a = new Articulator(); r.OpenChunk(art); r.ReadUInt32(); uint numCons = r.ReadUInt32(); for (uint i = 0; i < numCons; i++) { Connection con = new Connection(); con.SourceConnection = (SourceConnection)r.ReadUInt16(); con.ControlConnection = r.ReadUInt16(); con.DestinationConnection = (DestinationConnection)r.ReadUInt16(); con.TransformConnection = (TransformConnection)r.ReadUInt16(); con.Scale = r.ReadInt32(); a.Connections.Add(con); } reg.Articulators.Add(a); } //Add region. inst.Regions.Add(reg); } //Read name. var info = c.GetChunk("INFO"); if (info != null) { var inam = (info as ListChunk).GetChunk("INAM"); if (inam != null) { r.OpenChunk(inam); r.BaseStream.Position -= 4; uint siz = r.ReadUInt32(); inst.Name = new string(r.ReadChars((int)siz).Where(x => x != 0).ToArray()); } } //Add instrument. Instruments.Add(inst); } } }