public void ExtractAudio(DirectoryRecord dr, string path) { int sectorId = (int)dr.ExtentLocation; int filecounter = 0; Int32 prev1, prev2; List <Int16> pcms = new List <Int16>(); SectorHeader sh = fs.Sectors[sectorId]; prev1 = 0; prev2 = 0; while ((sh.Submode & Submodes.EOF) == 0) { if ((sh.Submode & Submodes.Audio) > 0) { XASectorForm2 s = fs.ReadXA2Sector(sectorId); for (int sg = 0; sg < 18; sg++) { byte[] data = new byte[128]; Array.Copy(s.Data, sg * 128, data, 0, 128); ADPCMBlock block = new ADPCMBlock(data); pcms.AddRange(block.getPCM(ref prev1, ref prev2)); } if ((sh.Submode & Submodes.EOR) > 0) { FileStream f = new FileStream(Path.Combine(path, "track" + filecounter.ToString("00") + ".wav"), FileMode.Create); BinaryWriter bw = new BinaryWriter(f); bw.Write(Encoding.ASCII.GetBytes("RIFF")); // "RIFF" bw.Write((Int32)(pcms.Count * 2) + 36); // size of entire file with 16-bit data bw.Write(Encoding.ASCII.GetBytes("WAVE")); // "WAVE" // chunk 1: bw.Write(Encoding.ASCII.GetBytes("fmt ")); // "fmt " bw.Write((Int32)16); // size of chunk in bytes bw.Write((Int16)1); // 1 - for PCM bw.Write((Int16)1); // only Stereo files in this version bw.Write((Int32)44100); // sample rate per second (usually 44100) bw.Write((Int32)(2 * 44100)); // bytes per second (usually 176400) bw.Write((Int16)2); // data align 4 bytes (2 bytes sample stereo) bw.Write((Int16)16); // only 16-bit in this version // chunk 2: bw.Write(Encoding.ASCII.GetBytes("data")); // "data" bw.Write((Int32)(pcms.Count * 2)); // size of audio data 16-bit foreach (Int16 pcm in pcms) { bw.Write(pcm); } bw.Flush(); bw.Close(); f.Close(); pcms = new List <Int16>(); prev1 = 0; prev2 = 0; filecounter++; } } sectorId++; sh = fs.Sectors[sectorId]; } }
public XASectorForm2 ReadXA2Sector(int LBAIndex) { byte[] buffer = new byte[2352]; SectorHeader header = _sectors[LBAIndex]; XASectorForm2 sector = new XASectorForm2(); FileStream fs = _streams[header.FileStreamId].Item1; fs.Seek(header.FileStreamOffset, SeekOrigin.Begin); fs.Read(buffer, 0, 2352); sector.ReadBytes(buffer); return(sector); }